Files
Jeong, YunWonandyouknowdot f0b1e82652 Add tracing profiler and Python 3.15 offline profiling tools (#9271)
* Add deterministic profiler and canonical Python 3.15 tools

Use the merged operation critical sections with interpreter-bound profiler
entry checks and short payload borrows. Trace owned code references for GC.
Import the canonical tracing and offline profiling output closure via the
repository updater, retaining existing test markers.

Assisted-by: dot:GPT-6.1

* Clarify standalone profiling license cross-reference

Preserve license terms and copyright notices; point to the reproduced
Apache text below instead of CPython's original OpenSSL section above.

Assisted-by: dot:GPT-6.1

* Defer unsupported sampling package from profiler extraction

Keep the deterministic tracing profiler and its canonical tools together.
Defer the entirely new sampling production, tests, assets and their license
as one closure until native record and binary-collector support is ready.
Retain canonical pstats for deterministic empty-profile handling; its
upstream sampled-file sorting issue is not patched here.

Assisted-by: dot:GPT-6.1

* Stage profiling root as a namespace until sampling is available

Omit the whole newly added canonical package initializer rather than
advertise an absent sampling module or hand-edit canonical __all__.
Explicit profiling.tracing and cProfile imports remain available.
The namespace root intentionally lacks canonical metadata/automatic exports.

This addresses test___all__ failures in the prior Linux, macOS and Windows
CI runs. No test assertions, skips or canonical file contents are changed.

Assisted-by: dot:GPT-6.1

* Match canonical static builtin profiler labels and metadata

Normalize the raw builtin receiver instead of its call-argument accessor.
Snapshot static method module metadata at construction, matching CPython,
so explicit module mutation and deletion remain observable. Avoid a
profiler-time fallback that would obscure deleted metadata.

Correct float.__getformat__ to CPython's classmethod calling convention,
including subclass binding, rather than special-casing its profiler label.

Assisted-by: dot:GPT-6.1

* Support collision-safe frozen package containers

Generate empty frozen packages only for source namespace directories with
real frozen descendants. Preserve genuine modules and packages across
frozen-library registrations while retaining real-real replacement order.

Record the container marker in FrozenModule and its library envelope;
legacy module/package encodings remain unchanged. This is closed-tree
frozen packaging, not full PEP 420 namespace merging.

Add structural codec, mock generator, and registration-priority checks.

* Revert frozen package containers before restoring canonical profiling root

The container implementation changed filesystem namespace precedence.
Restore the existing importer and frozen envelope unchanged; the following
offline sampling closure restores the canonical regular package root.

This reverses d5a8049234.

Assisted-by: dot:GPT-6.1

* Restore canonical profiling package with offline sampling codec

Provide native records, status constants and genuine uncompressed binary
reader/writer APIs for canonical offline tools. Keep the unsupported live
process capability absent and preserve existing canonical test gates.
Restore the complete selected sampling production/test/assets closure via
update_lib, including its asyncio frame-schema dependency. The prior frozen
container extension is reverted separately; canonical packages work with
both filesystem and frozen imports without changing namespace semantics.

Assisted-by: dot:GPT-6.1

* Keep platform-dependent C long normalization explicit

Allow only the c_long-to-i32 conversion lint: Windows uses the same type,
while LP64 requires the existing truncation to match CPython normalization.
No runtime behavior or test assertions change.

Assisted-by: dot:GPT-6.1

* Include profiling notices in library and desktop packages

Bundle a byte-identical copy of the root profiling notice in rustpython-pylib
and include the root notice in configured desktop resources. Avoid a symlink
so Windows checkouts preserve the actual notice text. Terms are unchanged.

Assisted-by: dot:GPT-6.1

* Keep profiling asset license notice in pylib crate

* Serve frozen profiling assets through native resource readers

* Preserve canonical profiling asset line endings on checkout

---------

Co-authored-by: youknowdot <dot@youknowone.org>
2026-10-22 11:18:03 +09:00

465 lines
24 KiB
HTML
Vendored

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{TITLE}}</title>
<!-- INLINE_VENDOR_D3_JS -->
<!-- INLINE_VENDOR_FLAMEGRAPH_CSS -->
<!-- INLINE_VENDOR_FLAMEGRAPH_JS -->
<!-- INLINE_VENDOR_FLAMEGRAPH_TOOLTIP_JS -->
<!-- INLINE_CSS -->
</head>
<body>
<div class="app-layout">
<!-- Top Bar -->
<header class="top-bar">
<div class="brand">
<div class="brand-logo" id="navbar-logo"></div>
<span class="brand-text">Tachyon</span>
<span class="brand-divider"></span>
<span class="brand-subtitle">{{SUBTITLE}}</span>
</div>
<div class="search-wrapper">
<input
type="text"
id="search-input"
class="search-input"
placeholder="Search functions..."
/>
<button
class="search-clear"
id="search-clear"
onclick="clearSearch()"
title="Clear search"
>&times;</button>
</div>
<div class="toolbar">
<button
class="toolbar-btn"
onclick="resetZoom()"
title="Reset zoom"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.708L2 8.207V13.5A1.5 1.5 0 0 0 3.5 15h9a1.5 1.5 0 0 0 1.5-1.5V8.207l.646.647a.5.5 0 0 0 .708-.708L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293zM13 7.207V13.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V7.207l5-5z"/>
</svg>
</button>
<button
class="toolbar-btn"
onclick="exportSVG()"
title="Export SVG"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5"/><path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708z"/>
</svg>
</button>
<a
class="toolbar-btn"
href="https://docs.python.org/<!-- PYTHON_VERSION -->/library/profiling.sampling.html"
target="_blank"
title="Documentation"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M1 2.828c.885-.37 2.154-.769 3.388-.893 1.33-.134 2.458.063 3.112.752v9.746c-.935-.53-2.12-.603-3.213-.493-1.18.12-2.37.461-3.287.811zm7.5-.141c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783"/>
</svg>
</a>
<button
class="toolbar-btn theme-toggle"
onclick="toggleTheme()"
title="Toggle theme"
id="theme-btn"
>
<svg class="icon-moon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M6 .278a.77.77 0 0 1 .08.858 7.2 7.2 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277q.792-.001 1.533-.16a.79.79 0 0 1 .81.316.73.73 0 0 1-.031.893A8.35 8.35 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.75.75 0 0 1 6 .278M4.858 1.311A7.27 7.27 0 0 0 1.025 7.71c0 4.02 3.279 7.276 7.319 7.276a7.32 7.32 0 0 0 5.205-2.162q-.506.063-1.029.063c-4.61 0-8.343-3.714-8.343-8.29 0-1.167.242-2.278.681-3.286"/>
</svg>
<svg class="icon-sun" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" style="display:none">
<path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6m0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8M8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0m0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13m8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5M3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8m10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0m-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0m9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707M4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708"/>
</svg>
</button>
</div>
</header>
<!-- Main Content -->
<div class="main-content">
<!-- Sidebar -->
<aside class="sidebar" id="sidebar">
<button
class="sidebar-toggle"
onclick="toggleSidebar()"
title="Toggle sidebar"
aria-label="Toggle sidebar"
>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div class="sidebar-resize-handle" id="sidebar-resize-handle"></div>
<div class="sidebar-content">
<!-- Logo Section -->
<div class="sidebar-logo">
<div class="sidebar-logo-img"><!-- INLINE_LOGO --></div>
</div>
<!-- View Mode Section -->
<section class="sidebar-section view-mode-section collapsible" id="view-mode-section">
<button class="section-header" onclick="toggleSection('view-mode-section')">
<h3 class="section-title">View Mode</h3>
<svg class="section-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div class="section-content">
<!-- Elided Stacks Toggle (only shown for diff flamegraphs with elided paths) -->
<div class="toggle-switch" id="toggle-elided" tabindex="0" style="display: none;">
<span class="toggle-label active" data-text="Differential">Differential</span>
<div class="toggle-track"></div>
<span class="toggle-label" data-text="Elided" title="Code paths that existed in baseline but are missing from current profile">Elided</span>
</div>
<div class="toggle-switch" id="toggle-path-display" title="Toggle between module names and full file paths" tabindex="0">
<span class="toggle-label" data-text="File Paths">File Paths</span>
<div class="toggle-track on"></div>
<span class="toggle-label active" data-text="Module Names">Module Names</span>
</div>
<div class="toggle-switch" id="toggle-invert" title="Toggle between standard and inverted flamegraph view" tabindex="0">
<span class="toggle-label active" data-text="Flamegraph">Flamegraph</span>
<div class="toggle-track"></div>
<span class="toggle-label" data-text="Inverted Flamegraph">Inverted Flamegraph</span>
</div>
</div>
</section>
<!-- Profile Summary Section -->
<section class="sidebar-section collapsible" id="summary-section">
<button class="section-header" onclick="toggleSection('summary-section')">
<h3 class="section-title">Profile Summary</h3>
<svg class="section-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div class="section-content">
<div class="summary-grid">
<div class="summary-card" id="summary-samples">
<div class="summary-icon">📊</div>
<div class="summary-data">
<div class="summary-value" id="stat-total-samples">--</div>
<div class="summary-label">Total Samples</div>
</div>
</div>
<div class="summary-card" id="summary-duration">
<div class="summary-icon">⏱</div>
<div class="summary-data">
<div class="summary-value" id="stat-duration">--</div>
<div class="summary-label">Duration</div>
</div>
</div>
<div class="summary-card" id="summary-rate">
<div class="summary-icon">⚡</div>
<div class="summary-data">
<div class="summary-value" id="stat-sample-rate">--</div>
<div class="summary-label">Samples/sec</div>
</div>
</div>
<div class="summary-card" id="summary-functions">
<div class="summary-icon">λ</div>
<div class="summary-data">
<div class="summary-value" id="stat-functions">--</div>
<div class="summary-label">Functions</div>
</div>
</div>
</div>
<!-- Efficiency Bar -->
<div class="efficiency-section" id="efficiency-section" style="display: none;">
<div class="bar-header">
<span class="bar-label">Sampling Efficiency</span>
<span class="bar-value" id="stat-efficiency">--</span>
</div>
<div class="bar">
<div class="bar-fill" id="efficiency-fill"></div>
</div>
<div class="bar-header">
<span class="bar-label">Missed samples</span>
<span class="bar-value" id="stat-missed-samples">--</span>
</div>
<div class="bar">
<div class="bar-fill" id="missed-samples-fill"></div>
</div>
</div>
</div>
</section>
<!-- Hotspots Section -->
<section class="sidebar-section collapsible" id="hotspots-section">
<button class="section-header" onclick="toggleSection('hotspots-section')">
<h3 class="section-title">Hotspots</h3>
<svg class="section-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div class="section-content">
<div class="hotspot" id="hotspot-1">
<div class="hotspot-rank hotspot-rank--1">1</div>
<div class="hotspot-info">
<div class="hotspot-func" id="hotspot-func-1">--</div>
<div class="hotspot-file" id="hotspot-file-1">--</div>
<div class="hotspot-stats">
<span class="hotspot-percent" id="hotspot-percent-1">--</span>
<span id="hotspot-samples-1"></span>
</div>
</div>
</div>
<div class="hotspot" id="hotspot-2">
<div class="hotspot-rank hotspot-rank--2">2</div>
<div class="hotspot-info">
<div class="hotspot-func" id="hotspot-func-2">--</div>
<div class="hotspot-file" id="hotspot-file-2">--</div>
<div class="hotspot-stats">
<span class="hotspot-percent" id="hotspot-percent-2">--</span>
<span id="hotspot-samples-2"></span>
</div>
</div>
</div>
<div class="hotspot" id="hotspot-3">
<div class="hotspot-rank hotspot-rank--3">3</div>
<div class="hotspot-info">
<div class="hotspot-func" id="hotspot-func-3">--</div>
<div class="hotspot-file" id="hotspot-file-3">--</div>
<div class="hotspot-stats">
<span class="hotspot-percent" id="hotspot-percent-3">--</span>
<span id="hotspot-samples-3"></span>
</div>
</div>
</div>
</div>
</section>
<!-- Thread Stats Section (GIL/GC) -->
<section class="sidebar-section thread-stats-section collapsible" id="thread-stats-bar" style="display: none;">
<button class="section-header" onclick="toggleSection('thread-stats-bar')">
<h3 class="section-title">Runtime Stats</h3>
<svg class="section-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div class="section-content">
<div class="stats-container">
<div class="stat-item" id="gil-held-stat">
<div class="bar-header">
<span class="bar-label">GIL Held</span>
<span class="bar-value" id="gil-held-pct">--</span>
</div>
<div class="bar">
<div class="bar-fill bar-fill--green" id="gil-held-fill"></div>
</div>
</div>
<div class="stat-item" id="gil-released-stat">
<div class="bar-header">
<span class="bar-label">GIL Released</span>
<span class="bar-value" id="gil-released-pct">--</span>
</div>
<div class="bar">
<div class="bar-fill bar-fill--red" id="gil-released-fill"></div>
</div>
</div>
<div class="stat-item" id="gil-waiting-stat">
<div class="bar-header">
<span class="bar-label">Waiting GIL</span>
<span class="bar-value" id="gil-waiting-pct">--</span>
</div>
<div class="bar">
<div class="bar-fill bar-fill--yellow" id="gil-waiting-fill"></div>
</div>
</div>
<div class="stat-item" id="gc-stat">
<div class="bar-header">
<span class="bar-label">GC</span>
<span class="bar-value" id="gc-pct">--</span>
</div>
<div class="bar">
<div class="bar-fill bar-fill--purple" id="gc-fill"></div>
</div>
</div>
<div class="stat-item" id="exc-stat">
<div class="bar-header">
<span class="bar-label">Exception</span>
<span class="bar-value" id="exc-pct">--</span>
</div>
<div class="bar">
<div class="bar-fill bar-fill--red" id="exc-fill"></div>
</div>
</div>
</div>
</div>
</section>
<!-- Thread Filter Section -->
<section class="sidebar-section filter-section" id="thread-section" style="display: none;">
<label class="filter-label" for="thread-filter">Thread Filter</label>
<select
id="thread-filter"
class="filter-select"
onchange="filterByThread()"
>
<option value="all">All Threads</option>
</select>
</section>
<!-- Heat Map Legend (shown for normal flamegraphs) -->
<section class="sidebar-section legend-section collapsible" id="heatmap-legend-section">
<button class="section-header" onclick="toggleSection('heatmap-legend-section')">
<h3 class="section-title">Heat Map</h3>
<svg class="section-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div class="section-content">
<div class="legend">
<div class="legend-item">
<div class="legend-color" style="background: var(--heat-8)"></div>
<span class="legend-label">Hottest</span>
<span class="legend-range">&ge;60%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--heat-7)"></div>
<span class="legend-label">Very Hot</span>
<span class="legend-range">35-60%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--heat-6)"></div>
<span class="legend-label">Hot</span>
<span class="legend-range">18-35%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--heat-5)"></div>
<span class="legend-label">Warm</span>
<span class="legend-range">12-18%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--heat-4)"></div>
<span class="legend-label">Medium</span>
<span class="legend-range">6-12%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--heat-3)"></div>
<span class="legend-label">Cool</span>
<span class="legend-range">3-6%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--heat-2)"></div>
<span class="legend-label">Cold</span>
<span class="legend-range">1-3%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--heat-1)"></div>
<span class="legend-label">Coldest</span>
<span class="legend-range">&lt;1%</span>
</div>
</div>
</div>
</section>
<!-- Differential Legend (shown for differential flamegraphs) -->
<section class="sidebar-section legend-section collapsible" id="diff-legend-section" style="display: none;">
<button class="section-header" onclick="toggleSection('diff-legend-section')">
<h3 class="section-title">Differential Colors</h3>
<svg class="section-chevron" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div class="section-content">
<div class="legend">
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-regression-deep)"></div>
<span class="legend-label">Deep Regression</span>
<span class="legend-range">&ge;100%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-regression-medium)"></div>
<span class="legend-label">Medium Regression</span>
<span class="legend-range">50-100%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-regression-light)"></div>
<span class="legend-label">Light Regression</span>
<span class="legend-range">30-50%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-regression-verylight)"></div>
<span class="legend-label">Minor Regression</span>
<span class="legend-range">15-30%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-neutral)"></div>
<span class="legend-label">Neutral</span>
<span class="legend-range">-15% to 15%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-improvement-verylight)"></div>
<span class="legend-label">Minor Improvement</span>
<span class="legend-range">-30% to -15%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-improvement-light)"></div>
<span class="legend-label">Light Improvement</span>
<span class="legend-range">-50% to -30%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-improvement-medium)"></div>
<span class="legend-label">Strong Improvement</span>
<span class="legend-range">&lt;-50%</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-new)"></div>
<span class="legend-label">New</span>
<span class="legend-range">No counterpart in baseline</span>
</div>
<div class="legend-item">
<div class="legend-color" style="background: var(--diff-elided)"></div>
<span class="legend-label">Removed</span>
<span class="legend-range">No counterpart in current</span>
</div>
</div>
</div>
</section>
</div>
</aside>
<!-- Chart Area -->
<main class="chart-area">
<div id="chart"></div>
</main>
</div>
<!-- Status Bar -->
<footer class="status-bar">
<span class="status-item" id="status-brand">
<span class="status-value">Tachyon Profiler</span>
</span>
<span class="status-item" id="status-tagline">
<span class="status-label">Python Sampling Profiler</span>
</span>
<span class="status-item" id="status-location" style="display: none;">
<span class="status-label">File:</span>
<span class="status-value" id="status-file">--</span>
</span>
<span class="status-item" id="status-func-item" style="display: none;">
<span class="status-label">Func:</span>
<span class="status-value" id="status-func">--</span>
</span>
<span class="status-item" id="status-time-item" style="display: none;">
<span class="status-label">Time:</span>
<span class="status-value" id="status-time">--</span>
</span>
<span class="status-item" id="status-percent-item" style="display: none;">
<span class="status-value accent" id="status-percent">--</span>
</span>
</footer>
</div>
<!-- INLINE_JS -->
</body>
</html>