fix: implement human-readable memory formatting and ensure hierarchical tree respects profiler filtering

This commit is contained in:
2026-02-22 23:50:37 +01:00
parent a1223ce6b5
commit 0920d3ff45

View File

@@ -72,6 +72,19 @@ function cn(...inputs: (string | undefined | null | false)[]) {
return twMerge(clsx(inputs));
}
function formatBytes(bytes: number, decimals = 1) {
if (!bytes || bytes === 0) return '0 B';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
}
function formatMB(mb: number, decimals = 1) {
return formatBytes(mb * 1024 * 1024, decimals);
}
function App() {
const [view, setView] = useState<'dashboard' | 'report'>('dashboard');
const [stats, setStats] = useState<SystemStats | null>(null);
@@ -420,11 +433,11 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
<div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{proc.peak_cpu.toFixed(1)}%</div>
<div className="text-mauve font-black text-sm text-right self-center tabular-nums">
{proc.inclusive_avg_memory_mb.toFixed(0)}MB
{proc.children.length > 0 && <span className="block text-[9px] text-overlay1 font-normal">({proc.avg_memory_mb.toFixed(0)}MB self)</span>}
{formatMB(proc.inclusive_avg_memory_mb)}
{proc.children.length > 0 && <span className="block text-[9px] text-overlay1 font-normal">({formatMB(proc.avg_memory_mb)} self)</span>}
</div>
<div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{proc.peak_memory_mb.toFixed(0)}MB</div>
<div className="text-subtext0 text-[11px] font-bold text-right self-center tabular-nums">{formatMB(proc.peak_memory_mb, 0)}</div>
<div className="flex flex-wrap gap-1.5 pl-4 items-center">
{proc.warnings.length > 0 ? proc.warnings.map((w, idx) => (
@@ -436,7 +449,10 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
)}
</div>
</div>
{hasChildren && isExpanded && renderTreeRows(proc.children, depth + 1)}
{hasChildren && isExpanded && renderTreeRows(
proc.children.filter(c => !hideProfiler || !c.is_syspulse),
depth + 1
)}
</Fragment>
);
});
@@ -521,6 +537,11 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
<Tooltip
contentStyle={{ background: 'var(--mantle)', border: '1px solid var(--surface1)', borderRadius: '12px', fontSize: '11px', fontWeight: 'bold' }}
itemStyle={{ color: 'var(--text)' }}
formatter={(value: number, name: string) => {
if (name === 'MEM GB') return [formatBytes(value * 1024 * 1024 * 1024), 'RAM'];
if (name === 'CPU %') return [`${value.toFixed(1)}%`, 'CPU'];
return [value, name];
}}
/>
<Area type="monotone" dataKey="avg_cpu" name="CPU %" stroke="var(--blue)" fill="url(#cpuReportGradient)" strokeWidth={3} isAnimationActive={true} />
<Area type="monotone" dataKey="memory_gb" name="MEM GB" stroke="var(--mauve)" fill="none" strokeWidth={2} />
@@ -590,7 +611,7 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
</div>
<div className="bg-surface0 p-6 rounded-2xl border border-surface1 shadow-lg">
<div className="text-[10px] font-black text-overlay2 uppercase tracking-widest mb-2">Total Avg RAM</div>
<div className="text-4xl font-black text-mauve tabular-nums">{selectedProcess.inclusive_avg_memory_mb.toFixed(0)}MB</div>
<div className="text-4xl font-black text-mauve tabular-nums">{formatMB(selectedProcess.inclusive_avg_memory_mb)}</div>
<p className="text-xs text-subtext1 mt-2">Combined RSS memory of the subtree.</p>
</div>
</div>
@@ -615,6 +636,11 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
<YAxis stroke="var(--subtext0)" tick={{fontSize: 9}} />
<Tooltip
contentStyle={{ background: 'var(--crust)', border: '1px solid var(--surface1)', borderRadius: '12px' }}
formatter={(value: number, name: string) => {
if (name === 'Self Mem (MB)') return [formatMB(value), 'RAM (Self)'];
if (name === 'Self CPU %') return [`${value.toFixed(1)}%`, 'CPU (Self)'];
return [value, name];
}}
/>
<Area type="monotone" dataKey="cpu_usage" name="Self CPU %" stroke="var(--blue)" fill="url(#procCpuGrad)" strokeWidth={3} />
<Area type="monotone" dataKey="memory_mb" name="Self Mem (MB)" stroke="var(--mauve)" fill="url(#procMemGrad)" strokeWidth={2} />
@@ -632,7 +658,7 @@ function ReportView({ report, onBack }: { report: ProfilingReport, onBack: () =>
</div>
<div className="flex justify-between text-sm">
<span className="text-subtext1">Peak Self RAM</span>
<span className="font-black text-mauve">{selectedProcess.peak_memory_mb.toFixed(0)}MB</span>
<span className="font-black text-mauve">{formatMB(selectedProcess.peak_memory_mb)}</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-subtext1">Child Process Count</span>