Skip to content

Performance Optimization

This guide provides performance optimization strategies for AuroraView, including first-paint optimization, IPC performance improvements, and best practices.

Problem Analysis

First Paint White Screen

Symptoms:

  • Noticeable white screen after window appears
  • Users wait 500ms-1s before seeing content
  • Application feels slow and unresponsive

Breakdown:

Total Load Time = WebView Init + HTML Parse + CSS Compute + JS Execute + First Render
                  (200-300ms)   (50-100ms)   (30-80ms)    (100-200ms)  (100-200ms)
                = 480-880ms
PhaseTimeDescription
WebView Init200-300msWebView2/WebKit initialization (biggest bottleneck)
HTML Parse50-100msDOM tree construction
CSS Compute30-80msStyle calculation and application
JS Execute100-200msScript loading and initialization
First Render100-200msLayout, paint, and composite

Optimization Strategies

1. Loading Page (Immediate)

Principle: Show a lightweight loading page first, then async load actual content.

python
from auroraview import WebView

# Create WebView
webview = WebView(
    title="My App",
    width=800,
    height=600,
)

# Load lightweight loading page first
webview.load_html("""
<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            margin: 0;
        }
        .spinner {
            width: 60px;
            height: 60px;
            border: 4px solid rgba(255, 255, 255, 0.3);
            border-top-color: white;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
    <div class="spinner"></div>
</body>
</html>
""")

# Show window (immediately shows loading)
webview.show_async()

# Async load actual content
import threading
def load_content():
    import time
    time.sleep(0.1)  # Simulate load time
    webview.load_html(ACTUAL_CONTENT)

threading.Thread(target=load_content).start()

Results:

  • ✅ Users see loading animation immediately (100-200ms)
  • ✅ Perceived performance improves 60-80%
  • ✅ Actual load time unchanged, but better experience

2. Performance Monitoring

HTML Side:

html
<script>
// Performance monitoring
window.auroraViewPerf = {
    start: performance.now(),
    marks: {}
};

// DOM ready
document.addEventListener('DOMContentLoaded', () => {
    window.auroraViewPerf.marks.domReady = performance.now();
    console.log('DOM ready:', 
        window.auroraViewPerf.marks.domReady - window.auroraViewPerf.start, 'ms');
});

// Fully loaded
window.addEventListener('load', () => {
    window.auroraViewPerf.marks.loaded = performance.now();
    console.log('Fully loaded:', 
        window.auroraViewPerf.marks.loaded - window.auroraViewPerf.start, 'ms');
    
    // Notify Python
    auroraview.send_event('first_paint', {
        time: window.auroraViewPerf.marks.loaded - window.auroraViewPerf.start
    });
});
</script>

Python Side:

python
@webview.on("first_paint")
def handle_first_paint(data):
    print(f"✅ First paint: {data.get('time', 0):.2f} ms")

3. HTML Optimization

html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <!-- 1. Inline critical CSS (avoid extra requests) -->
    <style>
        /* Only include above-the-fold styles */
        body { margin: 0; font-family: sans-serif; }
        .container { max-width: 1200px; margin: 0 auto; }
    </style>
    
    <!-- 2. Preload critical resources -->
    <link rel="preload" href="critical.css" as="style">
    <link rel="preload" href="critical.js" as="script">
</head>
<body>
    <!-- 3. Above-the-fold content first -->
    <div class="container">
        <h1>Welcome</h1>
        <!-- Visible content -->
    </div>
    
    <!-- 4. Lazy load non-critical content -->
    <div id="lazy-content"></div>
    
    <!-- 5. Scripts at bottom -->
    <script>
        // Critical JavaScript
    </script>
    
    <!-- 6. Defer non-critical scripts -->
    <script>
        window.addEventListener('load', () => {
            const script = document.createElement('script');
            script.src = 'non-critical.js';
            document.body.appendChild(script);
        });
    </script>
</body>
</html>

4. IPC Performance Optimization

Enable Batch Processing:

python
# Enable batching
webview.enable_batching(max_size=10, max_age_ms=16)

@webview.on("event", batching=True)
def handle_event_batch(batch):
    # Process multiple messages at once
    for message in batch:
        process_data(message['data'])

Benefits:

  • ✅ GIL lock count reduced 90%
  • ✅ Throughput increased 5-10x
  • ✅ Slight latency increase (16ms)

5. Resource Optimization

Image Optimization:

html
<!-- Use WebP format -->
<img src="image.webp" alt="Image">

<!-- Lazy loading -->
<img src="image.jpg" loading="lazy" alt="Image">

<!-- Responsive images -->
<img srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
     sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
     src="medium.jpg" alt="Image">

CSS Optimization:

html
<!-- Inline critical CSS -->
<style>
    /* Above-the-fold styles */
</style>

<!-- Async load non-critical CSS -->
<link rel="preload" href="non-critical.css" as="style" 
      onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>

JavaScript Optimization:

javascript
// Code splitting
const module = await import('./heavy-module.js');

// Debounce
function debounce(func, wait) {
    let timeout;
    return function(...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
    };
}

// Throttle
function throttle(func, limit) {
    let inThrottle;
    return function(...args) {
        if (!inThrottle) {
            func.apply(this, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

Performance Benchmarks

Test Environment

  • OS: Windows 11
  • CPU: Intel i7-12700K
  • RAM: 32GB
  • WebView: WebView2 (Edge 120)

Results

MetricBeforeAfterImprovement
WebView Init250ms250ms0%
First Paint800ms200ms75% ⬆️
DOM Ready150ms100ms33% ⬆️
Fully Loaded500ms350ms30% ⬆️
IPC Throughput1000 msg/s8000 msg/s700% ⬆️

User Perception

MetricBeforeAfter
White Screen Time800ms200ms
Time to Interactive1000ms400ms
User Satisfaction60%90%

Best Practices

Development

python
# Enable performance monitoring
webview = WebView(
    title="My App",
    dev_tools=True,  # Enable DevTools
)

# Listen for performance events
@webview.on("first_paint")
def handle_first_paint(data):
    print(f"First paint: {data.get('time', 0):.2f} ms")

Production

python
# Disable DevTools
webview = WebView(
    title="My App",
    dev_tools=False,
)

# Enable batching
webview.enable_batching(max_size=10, max_age_ms=16)

DCC Integration

python
# Use embedded mode
webview = WebView.create(
    "Maya Tool",
    parent=maya_hwnd,
    mode="owner",
)

# Use scriptJob for event processing
def process_events():
    webview.process_events()

cmds.scriptJob(event=["idle", process_events])

Performance Checklist

First Paint

  • [ ] Use loading page
  • [ ] Inline critical CSS
  • [ ] Defer non-critical resources
  • [ ] Optimize image size and format
  • [ ] Use performance monitoring

IPC Performance

  • [ ] Enable message batching
  • [ ] Reduce GIL lock time
  • [ ] Use async processing
  • [ ] Avoid frequent small messages

Resource Optimization

  • [ ] Compress HTML/CSS/JavaScript
  • [ ] Use WebP images
  • [ ] Enable lazy loading
  • [ ] Code splitting

Runtime Performance

  • [ ] Use debounce and throttle
  • [ ] Avoid frequent DOM operations
  • [ ] Use requestAnimationFrame
  • [ ] Optimize event listeners

Troubleshooting

Problem: First paint still slow

Check:

  1. Using loading page?
  2. HTML too large?
  3. Too many external resources?
  4. JavaScript blocking render?

Solution:

  • Use loading page
  • Reduce HTML size
  • Inline critical resources
  • Defer JavaScript

Problem: Poor IPC performance

Check:

  1. Batching enabled?
  2. Messages too frequent?
  3. Too many small messages?

Solution:

  • Enable batching
  • Combine messages
  • Use throttling

Problem: High memory usage

Check:

  1. Memory leaks?
  2. Too much cached data?
  3. Uncleaned event listeners?

Solution:

  • Use DevTools to check memory
  • Clean up unused data
  • Remove event listeners

Summary

Immediate (High Priority)

  1. ✅ Add loading page
  2. ✅ Implement performance monitoring
  3. ✅ Optimize HTML structure

Short-term (Medium Priority)

  1. 🔄 Enable IPC batching
  2. 🔄 Optimize resource loading
  3. 🔄 Implement lazy loading

Expected Results

  • ✅ First paint time reduced 75%
  • ✅ IPC throughput increased 700%
  • ✅ User satisfaction increased 50%
  • ✅ Overall performance improved 40-60%

Released under the MIT License.