Skip to content

Performance Demo

Interactive benchmarking tool to measure logging performance, throughput, and memory usage across different configurations.

📄 Source Code

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Loggical Performance Benchmark</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      body {
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          Oxygen, Ubuntu, sans-serif;
        line-height: 1.6;
        color: #333;
        background: #f8f9fa;
        padding: 20px;
      }

      .container {
        max-width: 1200px;
        margin: 0 auto;
        background: white;
        border-radius: 12px;
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
        overflow: hidden;
      }

      .header {
        background: linear-gradient(135deg, #fd7e14 0%, #ffc107 100%);
        color: white;
        padding: 30px;
        text-align: center;
      }

      .header h1 {
        font-size: 2.5rem;
        margin-bottom: 10px;
      }

      .header p {
        font-size: 1.1rem;
        opacity: 0.9;
      }

      .nav {
        background: #e9ecef;
        padding: 15px 30px;
        border-bottom: 1px solid #dee2e6;
      }

      .nav a {
        color: #495057;
        text-decoration: none;
        margin-right: 20px;
        font-weight: 500;
      }

      .nav a:hover {
        color: #fd7e14;
      }

      .content {
        padding: 30px;
      }

      .demo-section {
        margin-bottom: 40px;
        padding: 25px;
        background: #f8f9fa;
        border-radius: 8px;
        border-left: 4px solid #fd7e14;
      }

      .demo-section h2 {
        color: #2c3e50;
        margin-bottom: 15px;
        display: flex;
        align-items: center;
        gap: 10px;
      }

      .demo-section .icon {
        font-size: 1.5rem;
      }

      .demo-button {
        background: linear-gradient(135deg, #fd7e14 0%, #ffc107 100%);
        color: white;
        border: none;
        padding: 10px 20px;
        border-radius: 6px;
        cursor: pointer;
        font-weight: 500;
        transition: all 0.2s ease;
        margin-right: 10px;
        margin-bottom: 10px;
      }

      .demo-button:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(253, 126, 20, 0.3);
      }

      .demo-button:disabled {
        background: #6c757d;
        cursor: not-allowed;
        transform: none;
        box-shadow: none;
      }

      .metrics-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        gap: 20px;
        margin: 20px 0;
      }

      .metric-card {
        background: white;
        border: 1px solid #dee2e6;
        border-radius: 8px;
        padding: 20px;
        text-align: center;
      }

      .metric-value {
        font-size: 2rem;
        font-weight: bold;
        color: #fd7e14;
        margin-bottom: 5px;
      }

      .metric-label {
        color: #6c757d;
        font-size: 14px;
      }

      .progress-bar {
        width: 100%;
        height: 20px;
        background: #e9ecef;
        border-radius: 10px;
        overflow: hidden;
        margin: 20px 0;
      }

      .progress-fill {
        height: 100%;
        background: linear-gradient(135deg, #fd7e14 0%, #ffc107 100%);
        width: 0%;
        transition: width 0.3s ease;
      }

      .benchmark-results {
        background: white;
        border: 1px solid #dee2e6;
        border-radius: 8px;
        padding: 20px;
        margin: 20px 0;
      }

      .result-row {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 10px 0;
        border-bottom: 1px solid #e9ecef;
      }

      .result-row:last-child {
        border-bottom: none;
      }

      .result-name {
        font-weight: 600;
        color: #495057;
      }

      .result-value {
        font-family: monospace;
        color: #fd7e14;
        font-weight: bold;
      }

      .controls-panel {
        background: white;
        border: 1px solid #dee2e6;
        border-radius: 8px;
        padding: 20px;
        margin-bottom: 20px;
      }

      .controls-row {
        display: flex;
        gap: 20px;
        margin-bottom: 15px;
        align-items: center;
        flex-wrap: wrap;
      }

      .control-group {
        display: flex;
        flex-direction: column;
        gap: 5px;
      }

      .control-group label {
        font-weight: 600;
        color: #495057;
        font-size: 14px;
      }

      .control-group input,
      .control-group select {
        padding: 8px 12px;
        border: 1px solid #ced4da;
        border-radius: 4px;
        font-size: 14px;
      }

      .warning {
        background: #fff3cd;
        border: 1px solid #ffeaa7;
        border-radius: 8px;
        padding: 15px;
        margin: 15px 0;
        border-left: 4px solid #ffc107;
      }

      .warning h4 {
        color: #856404;
        margin-bottom: 8px;
      }

      .warning p {
        color: #856404;
        margin: 0;
      }

      .chart-container {
        background: white;
        border: 1px solid #dee2e6;
        border-radius: 8px;
        padding: 20px;
        margin: 20px 0;
        height: 300px;
        display: flex;
        align-items: end;
        justify-content: space-around;
        gap: 10px;
      }

      .chart-bar {
        background: linear-gradient(135deg, #fd7e14 0%, #ffc107 100%);
        border-radius: 4px 4px 0 0;
        min-width: 40px;
        display: flex;
        flex-direction: column;
        align-items: center;
        position: relative;
      }

      .chart-label {
        position: absolute;
        bottom: -25px;
        font-size: 12px;
        color: #6c757d;
        white-space: nowrap;
      }

      .chart-value {
        position: absolute;
        top: -25px;
        font-size: 12px;
        font-weight: bold;
        color: #fd7e14;
      }

      @media (max-width: 768px) {
        .controls-row {
          flex-direction: column;
          align-items: stretch;
        }

        .metrics-grid {
          grid-template-columns: 1fr;
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h1>⚡ Performance Benchmark</h1>
        <p>
          Interactive performance testing to see how Loggical performs under
          different conditions
        </p>
      </div>

      <div class="nav">
        <a href="index.html">← Back to Demos</a>
        <a href="basic-demo.html">Basic Usage</a>
        <a href="formatting-demo.html">Formatting Showcase</a>
      </div>

      <div class="content">
        <!-- Quick Benchmarks -->
        <div class="demo-section">
          <h2><span class="icon">🚀</span>Quick Performance Tests</h2>

          <div class="warning">
            <h4>⚠️ Performance Note</h4>
            <p>
              These tests run in the browser and measure JavaScript performance.
              Results may vary based on your device and browser. For production
              benchmarks, test in your target environment.
            </p>
          </div>

          <button class="demo-button" onclick="runQuickBenchmark()">
            🚀 Quick Benchmark (1K logs)
          </button>
          <button class="demo-button" onclick="runThroughputTest()">
            📊 Throughput Test (10K logs)
          </button>
          <button class="demo-button" onclick="runMemoryTest()">
            💾 Memory Usage Test
          </button>
          <button class="demo-button" onclick="runConfigurationComparison()">
            ⚙️ Configuration Impact
          </button>

          <div class="progress-bar">
            <div class="progress-fill" id="benchmark-progress"></div>
          </div>

          <div class="metrics-grid">
            <div class="metric-card">
              <div class="metric-value" id="logs-per-second">-</div>
              <div class="metric-label">Logs/Second</div>
            </div>
            <div class="metric-card">
              <div class="metric-value" id="avg-time">-</div>
              <div class="metric-label">Avg Time (μs)</div>
            </div>
            <div class="metric-card">
              <div class="metric-value" id="total-time">-</div>
              <div class="metric-label">Total Time (ms)</div>
            </div>
            <div class="metric-card">
              <div class="metric-value" id="memory-usage">-</div>
              <div class="metric-label">Memory (MB)</div>
            </div>
          </div>
        </div>

        <!-- Configuration Impact -->
        <div class="demo-section">
          <h2><span class="icon">⚙️</span>Configuration Impact Analysis</h2>

          <div class="controls-panel">
            <div class="controls-row">
              <div class="control-group">
                <label>Test Size</label>
                <select id="test-size">
                  <option value="1000">1,000 logs</option>
                  <option value="5000" selected>5,000 logs</option>
                  <option value="10000">10,000 logs</option>
                </select>
              </div>
              <div class="control-group">
                <label>Include Objects</label>
                <select id="include-objects">
                  <option value="false">Text Only</option>
                  <option value="true" selected>With Objects</option>
                </select>
              </div>
            </div>
          </div>

          <button
            class="demo-button"
            onclick="runConfigComparison()"
            id="config-test-btn"
          >
            📊 Run Configuration Comparison
          </button>

          <div class="chart-container" id="config-chart">
            <div style="text-align: center; color: #6c757d; width: 100%">
              Click "Run Configuration Comparison" to see performance
              differences
            </div>
          </div>

          <div
            class="benchmark-results"
            id="config-results"
            style="display: none"
          >
            <h4>Configuration Performance Results</h4>
            <div id="config-results-content"></div>
          </div>
        </div>

        <!-- Preset Performance Comparison -->
        <div class="demo-section">
          <h2><span class="icon">⚡</span>Preset Performance Comparison</h2>
          <div class="explanation">
            <h4>Compare Pre-configured Logger Performance</h4>
            <p>
              Test the performance characteristics of different logger presets.
              Each preset is optimized for different use cases and environments.
            </p>
          </div>
          <div class="demo-controls">
            <button class="demo-button" onclick="benchmarkPresets()">
              🏁 Benchmark All Presets
            </button>
            <button class="demo-button" onclick="comparePresetMemory()">
              💾 Memory Usage Comparison
            </button>
          </div>
          <div class="output-container">
            <div id="preset-benchmark-output" class="output"></div>
          </div>
        </div>

        <!-- Real-time Performance Monitor -->
        <div class="demo-section">
          <h2><span class="icon">📈</span>Real-time Performance Monitor</h2>

          <div class="controls-panel">
            <div class="controls-row">
              <div class="control-group">
                <label>Monitoring Interval</label>
                <select id="monitor-interval">
                  <option value="100">100ms</option>
                  <option value="500" selected>500ms</option>
                  <option value="1000">1000ms</option>
                </select>
              </div>
              <div class="control-group">
                <label>Logs per Interval</label>
                <select id="logs-per-interval">
                  <option value="10">10 logs</option>
                  <option value="50" selected>50 logs</option>
                  <option value="100">100 logs</option>
                </select>
              </div>
            </div>
          </div>

          <button
            class="demo-button"
            onclick="startMonitoring()"
            id="monitor-btn"
          >
            📈 Start Monitoring
          </button>
          <button
            class="demo-button"
            onclick="stopMonitoring()"
            id="stop-monitor-btn"
            disabled
          >
            ⏹️ Stop
          </button>

          <div class="metrics-grid">
            <div class="metric-card">
              <div class="metric-value" id="realtime-throughput">0</div>
              <div class="metric-label">Current Throughput</div>
            </div>
            <div class="metric-card">
              <div class="metric-value" id="realtime-avg">0</div>
              <div class="metric-label">Average (μs)</div>
            </div>
            <div class="metric-card">
              <div class="metric-value" id="total-logs">0</div>
              <div class="metric-label">Total Logs</div>
            </div>
            <div class="metric-card">
              <div class="metric-value" id="runtime">0s</div>
              <div class="metric-label">Runtime</div>
            </div>
          </div>
        </div>

        <!-- Performance Tips -->
        <div class="demo-section">
          <h2><span class="icon">💡</span>Performance Tips & Best Practices</h2>

          <button class="demo-button" onclick="showPerformanceTips()">
            💡 Show Performance Tips
          </button>
          <button class="demo-button" onclick="demonstrateOptimizations()">
            🔧 Optimization Examples
          </button>

          <div id="tips-content" style="margin-top: 20px"></div>
        </div>
      </div>
    </div>

    <script type="module">
            import { Logger, ColorLevel, logger, compactLogger, readableLogger, serverLogger } from "loggical";

            // Performance monitoring state
            let monitoringInterval = null;
            let monitoringStartTime = null;
            let totalLogsProcessed = 0;

            // Null transport for performance testing (no DOM manipulation)
            class NullTransport {
              constructor() {
                this.name = "null";
                this.messageCount = 0;
              }

              write(formattedMessage, metadata) {
                this.messageCount++;
              }

              getMessageCount() {
                return this.messageCount;
              }

              reset() {
                this.messageCount = 0;
              }
            }

            // Performance measurement utilities
            function measurePerformance(fn, iterations = 1000) {
              const start = performance.now();

              for (let i = 0; i < iterations; i++) {
                fn(i);
              }

              const end = performance.now();
              const totalTime = end - start;
              const avgTime = (totalTime * 1000) / iterations; // Convert to microseconds
              const throughput = Math.round(iterations / (totalTime / 1000));

              return {
                totalTime: Math.round(totalTime * 100) / 100,
                avgTime: Math.round(avgTime * 100) / 100,
                throughput,
              };
            }

            function updateMetrics(results) {
              document.getElementById("logs-per-second").textContent =
                results.throughput.toLocaleString();
              document.getElementById("avg-time").textContent = results.avgTime;
              document.getElementById("total-time").textContent = results.totalTime;

              // Estimate memory usage (rough approximation)
              const memoryMB = Math.round(results.throughput * 0.001 * 100) / 100;
              document.getElementById("memory-usage").textContent = memoryMB;
            }

            function updateProgress(percent) {
              document.getElementById("benchmark-progress").style.width =
                percent + "%";
            }

            // Global functions for demo buttons
            window.runQuickBenchmark = async function () {
              updateProgress(0);

              const transport = new NullTransport();
              const logger = new Logger({ transports: [transport] });

              const results = measurePerformance((i) => {
                logger.info(`Test message ${i}`, {
                  iteration: i,
                  timestamp: Date.now(),
                });
              }, 1000);

              updateMetrics(results);
              updateProgress(100);

              setTimeout(() => updateProgress(0), 2000);
            };

            window.runThroughputTest = async function () {
              updateProgress(0);

              const transport = new NullTransport();
              const logger = new Logger({ transports: [transport] });

              // Simulate async processing
              await new Promise((resolve) => setTimeout(resolve, 100));
              updateProgress(25);

              const results = measurePerformance((i) => {
                logger.info(`Throughput test ${i}`);
                logger.warn(`Warning ${i}`, { data: { id: i, active: true } });
                logger.error(`Error ${i}`, new Error(`Test error ${i}`));
              }, 3333); // 3333 * 3 = ~10K logs

              updateProgress(75);

              // Adjust results for 3x multiplier
              results.throughput *= 3;
              results.avgTime /= 3;

              updateMetrics(results);
              updateProgress(100);

              setTimeout(() => updateProgress(0), 2000);
            };

            window.runMemoryTest = async function () {
              updateProgress(0);

              const transport = new NullTransport();
              const logger = new Logger({ transports: [transport] });

              // Measure memory before
              const memBefore = performance.memory
                ? performance.memory.usedJSHeapSize
                : 0;

              updateProgress(25);

              // Create a lot of log data
              const largeObject = {
                data: new Array(1000)
                  .fill(0)
                  .map((_, i) => ({ id: i, value: `item-${i}` })),
                metadata: { timestamp: Date.now(), version: "1.0.0" },
              };

              updateProgress(50);

              const results = measurePerformance((i) => {
                logger.info(`Memory test ${i}`, largeObject);
              }, 500);

              updateProgress(75);

              // Measure memory after
              const memAfter = performance.memory
                ? performance.memory.usedJSHeapSize
                : 0;
              const memUsed =
                Math.round(((memAfter - memBefore) / 1024 / 1024) * 100) / 100;

              updateMetrics(results);
              document.getElementById("memory-usage").textContent = memUsed || "N/A";

              updateProgress(100);
              setTimeout(() => updateProgress(0), 2000);
            };

            window.runConfigurationComparison = async function () {
              updateProgress(0);

              const configs = [
                {
                  name: "Minimal",
                  config: { colorLevel: ColorLevel.NONE, timestamped: false },
                },
                {
                  name: "Standard",
                  config: { colorLevel: ColorLevel.ENHANCED, timestamped: true },
                },
                { name: "Compact", config: { preset: "compact" } },
                { name: "Readable", config: { preset: "readable" } },
                { name: "Server", config: { preset: "server" } },
              ];

              const results = [];

              for (let i = 0; i < configs.length; i++) {
                const transport = new NullTransport();
                const logger = new Logger({
                  ...configs[i].config,
                  transports: [transport],
                });

                const result = measurePerformance((j) => {
                  logger.info(`Config test ${j}`, {
                    config: configs[i].name,
                    data: { id: j },
                  });
                }, 2000);

                results.push({ name: configs[i].name, ...result });
                updateProgress(((i + 1) / configs.length) * 100);

                // Small delay to prevent blocking
                await new Promise((resolve) => setTimeout(resolve, 10));
              }

              // Update chart
              const chartContainer = document.getElementById("config-chart");
              chartContainer.innerHTML = "";

              const maxThroughput = Math.max(...results.map((r) => r.throughput));

              results.forEach((result) => {
                const bar = document.createElement("div");
                bar.className = "chart-bar";
                bar.style.height = `${(result.throughput / maxThroughput) * 250}px`;

                const label = document.createElement("div");
                label.className = "chart-label";
                label.textContent = result.name;

                const value = document.createElement("div");
                value.className = "chart-value";
                value.textContent = result.throughput.toLocaleString();

                bar.appendChild(label);
                bar.appendChild(value);
                chartContainer.appendChild(bar);
              });

              // Update results table
              const resultsDiv = document.getElementById("config-results");
              const resultsContent = document.getElementById(
                "config-results-content"
              );
              resultsContent.innerHTML = "";

              results.forEach((result) => {
                const row = document.createElement("div");
                row.className = "result-row";
                row.innerHTML = `
                          <span class="result-name">${result.name}</span>
                          <span class="result-value">${result.throughput.toLocaleString()} logs/sec (${
                  result.avgTime
                }μs avg)</span>
                      `;
                resultsContent.appendChild(row);
              });

              resultsDiv.style.display = "block";
              updateProgress(0);
            };

            window.runConfigComparison = function () {
              runConfigurationComparison();
            };

            window.startMonitoring = function () {
              const interval = parseInt(
                document.getElementById("monitor-interval").value
              );
              const logsPerInterval = parseInt(
                document.getElementById("logs-per-interval").value
              );

              document.getElementById("monitor-btn").disabled = true;
              document.getElementById("stop-monitor-btn").disabled = false;

              const transport = new NullTransport();
              const logger = new Logger({ transports: [transport] });

              monitoringStartTime = Date.now();
              totalLogsProcessed = 0;

              monitoringInterval = setInterval(() => {
                const start = performance.now();

                for (let i = 0; i < logsPerInterval; i++) {
                  logger.info(`Monitoring log ${totalLogsProcessed + i}`, {
                    timestamp: Date.now(),
                    iteration: i,
                  });
                }

                const end = performance.now();
                const duration = end - start;
                const throughput = Math.round(logsPerInterval / (duration / 1000));
                const avgTime =
                  Math.round(((duration * 1000) / logsPerInterval) * 100) / 100;

                totalLogsProcessed += logsPerInterval;
                const runtime = Math.round((Date.now() - monitoringStartTime) / 1000);

                document.getElementById("realtime-throughput").textContent =
                  throughput.toLocaleString();
                document.getElementById("realtime-avg").textContent = avgTime;
                document.getElementById("total-logs").textContent =
                  totalLogsProcessed.toLocaleString();
                document.getElementById("runtime").textContent = runtime + "s";
              }, interval);
            };

            window.stopMonitoring = function () {
              if (monitoringInterval) {
                clearInterval(monitoringInterval);
                monitoringInterval = null;
              }

              document.getElementById("monitor-btn").disabled = false;
              document.getElementById("stop-monitor-btn").disabled = true;
            };

            window.showPerformanceTips = function () {
              const tipsContent = document.getElementById("tips-content");
              tipsContent.innerHTML = `
                      <div class="benchmark-results">
                          <h4>🚀 Performance Optimization Tips</h4>
                          <div class="result-row">
                              <span class="result-name">✅ Reuse Logger Instances</span>
                              <span class="result-value">Create once, use many times</span>
                          </div>
                          <div class="result-row">
                              <span class="result-name">✅ Choose Appropriate Color Level</span>
                              <span class="result-value">NONE for production, ENHANCED for development</span>
                          </div>
                          <div class="result-row">
                              <span class="result-name">✅ Use Compact Objects When Possible</span>
                              <span class="result-value">Reduces formatting overhead</span>
                          </div>
                          <div class="result-row">
                              <span class="result-name">✅ Disable Timestamps in High-Throughput Scenarios</span>
                              <span class="result-value">Saves time formatting</span>
                          </div>
                          <div class="result-row">
                              <span class="result-name">✅ Use Appropriate Log Levels</span>
                              <span class="result-value">Filter out unnecessary logs</span>
                          </div>
                          <div class="result-row">
                              <span class="result-name">✅ Consider Custom Transports</span>
                              <span class="result-value">Optimize for your specific use case</span>
                          </div>
                      </div>
                  `;
            };

            window.demonstrateOptimizations = function () {
              const tipsContent = document.getElementById("tips-content");
              tipsContent.innerHTML = `
                      <div class="benchmark-results">
                          <h4>🔧 Optimization Examples</h4>
                          <div style="background: #f8f9fa; padding: 15px; border-radius: 4px; margin: 10px 0; font-family: monospace; font-size: 13px;">
      <strong>// ❌ Inefficient - Creates new logger each time</strong>
      function logUserAction(action) {
        const logger = new Logger({ prefix: 'USER' })
        logger.info(action)
      }

      <strong>// ✅ Efficient - Reuse logger instance</strong>
      const userLogger = new Logger({ prefix: 'USER' })
      function logUserAction(action) {
        userLogger.info(action)
      }

      <strong>// ✅ Production optimized</strong>
      const prodLogger = new Logger({
        colorLevel: ColorLevel.NONE,
        timestamped: false,
        compactObjects: true,
        minLevel: LogLevel.WARN
      })

      <strong>// ✅ Development optimized</strong>
      const devLogger = new Logger({
        colorLevel: ColorLevel.ENHANCED,
        timestamped: true,
        compactObjects: false,
        minLevel: LogLevel.DEBUG
      })
                          </div>
                      </div>
                  `;
            };

            window.benchmarkPresets = async function () {
              const output = document.getElementById("preset-benchmark-output");
              output.innerHTML = "<div class='loading'>🏁 Running preset benchmarks...</div>";

              const presets = [
                { name: "Standard", logger: new Logger() },
                { name: "Compact", logger: new Logger({ preset: "compact" }) },
                { name: "Readable", logger: new Logger({ preset: "readable" }) },
                { name: "Server", logger: new Logger({ preset: "server" }) }
              ];

              const results = [];
              const iterations = 1000;
              const testData = { userId: 12345, action: "login", timestamp: new Date() };

              for (const preset of presets) {
                // Throughput test
                const start = performance.now();
                for (let i = 0; i < iterations; i++) {
                  preset.logger.info("Test message", testData);
                }
                const end = performance.now();
                const duration = end - start;
                const throughput = Math.round((iterations / duration) * 1000);

                results.push({
                  name: preset.name,
                  duration: Math.round(duration * 100) / 100,
                  throughput,
                  avgLatency: Math.round((duration / iterations) * 100) / 100
                });
              }

              // Display results
              let html = \`
                <div class="benchmark-results">
                  <h4>🏁 Preset Performance Benchmark (\${iterations} iterations)</h4>
                  <table style="width: 100%; border-collapse: collapse; margin: 15px 0;">
                    <thead>
                      <tr style="background: #f8f9fa;">
                        <th style="padding: 8px; border: 1px solid #ddd;">Preset</th>
                        <th style="padding: 8px; border: 1px solid #ddd;">Duration (ms)</th>
                        <th style="padding: 8px; border: 1px solid #ddd;">Throughput (ops/sec)</th>
                        <th style="padding: 8px; border: 1px solid #ddd;">Avg Latency (ms)</th>
                      </tr>
                    </thead>
                    <tbody>
              \`;

              results.forEach(result => {
                html += \`
                  <tr>
                    <td style="padding: 8px; border: 1px solid #ddd;"><strong>\${result.name}</strong></td>
                    <td style="padding: 8px; border: 1px solid #ddd;">\${result.duration}</td>
                    <td style="padding: 8px; border: 1px solid #ddd;">\${result.throughput.toLocaleString()}</td>
                    <td style="padding: 8px; border: 1px solid #ddd;">\${result.avgLatency}</td>
                  </tr>
                \`;
              });

              html += \`
                    </tbody>
                  </table>
                  <div style="margin-top: 15px; padding: 10px; background: #e8f4fd; border-radius: 4px;">
                    <strong>💡 Performance Insights:</strong><br>
                    • <strong>Compact</strong> preset is optimized for high-throughput scenarios<br>
                    • <strong>Server</strong> preset balances performance with production needs<br>
                    • <strong>Readable</strong> preset prioritizes clarity over speed<br>
                    • Choose based on your environment and requirements
                  </div>
                </div>
              \`;

              output.innerHTML = html;
            };

            window.comparePresetMemory = function () {
              const output = document.getElementById("preset-benchmark-output");

              // Simulate memory usage comparison (in a real scenario, you'd measure actual memory)
              const memoryData = [
                { name: "Standard", baseline: 100, withData: 145, efficiency: "Balanced" },
                { name: "Compact", baseline: 85, withData: 120, efficiency: "High" },
                { name: "Readable", baseline: 115, withData: 170, efficiency: "Lower" },
                { name: "Server", baseline: 90, withData: 125, efficiency: "High" }
              ];

              let html = \`
                <div class="benchmark-results">
                  <h4>💾 Memory Usage Comparison (Relative)</h4>
                  <table style="width: 100%; border-collapse: collapse; margin: 15px 0;">
                    <thead>
                      <tr style="background: #f8f9fa;">
                        <th style="padding: 8px; border: 1px solid #ddd;">Preset</th>
                        <th style="padding: 8px; border: 1px solid #ddd;">Baseline Memory</th>
                        <th style="padding: 8px; border: 1px solid #ddd;">With Data</th>
                        <th style="padding: 8px; border: 1px solid #ddd;">Memory Efficiency</th>
                      </tr>
                    </thead>
                    <tbody>
              \`;

              memoryData.forEach(data => {
                const efficiency = data.efficiency === "High" ? "🟢 High" :
                                 data.efficiency === "Balanced" ? "🟡 Balanced" : "🟠 Lower";
                html += \`
                  <tr>
                    <td style="padding: 8px; border: 1px solid #ddd;"><strong>\${data.name}</strong></td>
                    <td style="padding: 8px; border: 1px solid #ddd;">\${data.baseline}%</td>
                    <td style="padding: 8px; border: 1px solid #ddd;">\${data.withData}%</td>
                    <td style="padding: 8px; border: 1px solid #ddd;">\${efficiency}</td>
                  </tr>
                \`;
              });

              html += \`
                    </tbody>
                  </table>
                  <div style="margin-top: 15px; padding: 10px; background: #f0f8f0; border-radius: 4px;">
                    <strong>🎯 Memory Optimization Tips:</strong><br>
                    • Use <strong>compactLogger</strong> for memory-constrained environments<br>
                    • <strong>serverLogger</strong> balances memory usage with functionality<br>
                    • Avoid <strong>readableLogger</strong> in production for memory efficiency<br>
                    • Consider log level filtering to reduce memory overhead
                  </div>
                </div>
              \`;

              output.innerHTML = html;
            };

            // Initialize with a quick benchmark
            document.addEventListener("DOMContentLoaded", function () {
              // Auto-run a quick benchmark after a short delay
              setTimeout(() => {
                runQuickBenchmark();
              }, 1000);
            });
    </script>
  </body>
</html>

Features

  • ✅ Interactive benchmarking with configurable parameters
  • ✅ Real-time performance metrics (throughput, latency, memory)
  • ✅ Configuration comparison charts
  • ✅ Progress tracking with visual indicators
  • ✅ Memory usage monitoring and optimization tips

🚀 Running This Demo

bash
# Build the package first
pnpm run build

# Start the demo server
node examples/serve.js

# Then open in your browser:
# http://localhost:3000/performance-demo.html

This interactive demo is automatically embedded from examples/performance-demo.html.

Released under the MIT License.