From deec86fab911d14da40d60e38b8a466854f64ed2 Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Fri, 23 Oct 2026 21:35:02 +0800 Subject: [PATCH] refactor(perf): Remove the Memory Usage settings page It was a live metrics view, not a setting, and duplicated the memory indicator's popup, its status bar toggle and Clear Caches. Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu --- src/features/index.ts | 3 +- src/features/perf/MemoryUsage.module.css | 85 -------------- src/features/perf/MemoryUsagePage.tsx | 143 ----------------------- src/features/perf/__tests__/perf.test.ts | 5 +- src/features/perf/format.ts | 6 - src/features/perf/index.ts | 16 +-- 6 files changed, 3 insertions(+), 255 deletions(-) delete mode 100644 src/features/perf/MemoryUsage.module.css delete mode 100644 src/features/perf/MemoryUsagePage.tsx diff --git a/src/features/index.ts b/src/features/index.ts index afd2361e..9112bbd5 100644 --- a/src/features/index.ts +++ b/src/features/index.ts @@ -21,7 +21,7 @@ import { activate as templates, activateSettingsPages as templatesPages } from " import { activate as todo, activateSettingsPages as todoPages } from "./todo"; import { activate as settings, activateSettingsWindow } from "./settings"; import { activate as app } from "./app"; -import { activate as perf, activateSettingsPages as perfPages } from "./perf"; +import { activate as perf } from "./perf"; import { activate as plugins, activateSettingsPages as pluginsPages } from "./plugins"; import { activate as tools, activateSettingsPages as toolsPages } from "./tools"; import { activate as scratch } from "./scratch"; @@ -90,7 +90,6 @@ export function activateSettingsWindowFeatures(parent: string): () => void { ["templates", templatesPages], ["todo", todoPages], ["plugins", pluginsPages], - ["perf", perfPages], ["tools", toolsPages], ]; const disposers: Array<() => void> = []; diff --git a/src/features/perf/MemoryUsage.module.css b/src/features/perf/MemoryUsage.module.css deleted file mode 100644 index 06d8cfa0..00000000 --- a/src/features/perf/MemoryUsage.module.css +++ /dev/null @@ -1,85 +0,0 @@ -.page { - display: flex; - flex-direction: column; - gap: 22px; - max-width: 680px; -} -.title { - display: flex; - align-items: center; - gap: 8px; - height: 22px; - margin-bottom: 6px; - color: var(--fg-strong); -} -.rule { - flex: 1; - height: 1px; - background: var(--border); -} -.body { - display: flex; - flex-direction: column; - padding-left: 18px; -} -.row { - display: flex; - align-items: center; - gap: 8px; - min-height: 26px; -} -.label { - color: var(--fg); - min-width: 220px; -} -.value { - min-width: 72px; - text-align: right; - font-family: var(--font-mono); - font-size: var(--fs-small); - font-variant-numeric: tabular-nums; - color: var(--fg-strong); -} -.meter { - position: relative; - height: 8px; - max-width: 420px; - margin: 4px 0 8px; - border-radius: var(--radius-small); - background: var(--bg-control); - overflow: hidden; -} -.fill { - position: absolute; - inset: 0 auto 0 0; - background: var(--accent); -} -.hint { - color: var(--fg-subtle); - font-size: var(--fs-small); -} -.actions { - display: flex; - align-items: center; - gap: 12px; - margin-top: 8px; -} -.error { - color: var(--danger); -} -.empty { - color: var(--fg-subtle); -} -.strong .label, -.strong .value { - color: var(--fg-strong); - font-weight: 600; -} -.indented .label { - padding-left: 16px; - min-width: 204px; -} -.group { - display: flex; - flex-direction: column; -} diff --git a/src/features/perf/MemoryUsagePage.tsx b/src/features/perf/MemoryUsagePage.tsx deleted file mode 100644 index 149239a1..00000000 --- a/src/features/perf/MemoryUsagePage.tsx +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Settings › Memory Usage: memory of OpenIDEA, its language servers and other - * processes, subsystem sizes, "Clear caches" and the status bar indicator toggle. - */ -import { useEffect, type ReactNode } from "react"; -import clsx from "clsx"; -import { Button, Checkbox } from "@/ui"; -import { executeAction } from "@/platform/actions"; -import { isTauri } from "@/platform/ipc"; -import { isStatusItemVisible, setStatusWidgetVisible, useStatusWidgetOverrides } from "@/workbench/statusBarWidgets"; -import { formatBytes, formatCount, formatMs, formatSize, formatUptime, memoryRatio } from "./format"; -import { memorySections, summarizeMemory } from "./memory"; -import { MEMORY_WIDGET } from "./MemoryStatus"; -import { startPolling } from "./poll"; -import { refreshMetrics, usePerf } from "./store"; -import styles from "./MemoryUsage.module.css"; - -function Row({ - label, - value, - strong, - indented, -}: { - label: string; - value: string; - strong?: boolean; - indented?: boolean; -}) { - return ( -
- {label}: - {value} -
- ); -} - -/** The same setting as the status bar context menu's "Memory Indicator". */ -function IndicatorToggle() { - const overrides = useStatusWidgetOverrides(); - const shown = isStatusItemVisible(MEMORY_WIDGET, overrides); - return ( - void setStatusWidgetVisible(MEMORY_WIDGET.id, on)} - label="Show memory indicator in the status bar" - /> - ); -} - -function Section({ title, children }: { title: string; children: ReactNode }) { - return ( -
-
- {title} - -
-
{children}
-
- ); -} - -export function MemoryUsagePage() { - const m = usePerf((s) => s.metrics); - const error = usePerf((s) => s.error); - useEffect(() => { - if (!isTauri()) return; - return startPolling(() => void refreshMetrics(), { intervalMs: 2000 }); - }, []); - - if (!isTauri()) return
Memory usage is available in the desktop app.
; - if (!m) return
Loading…
; - const summary = summarizeMemory(m); - const own = (summary.app ?? 0) + (summary.languageServers ?? 0); - const ratio = memoryRatio(own, m.totalMemoryBytes); - return ( -
-
- -
- 0 ? 1 : 0)}%` }} /> -
-
- OpenIDEA and its language servers use {formatSize(own)} ({Math.round(ratio * 100)}%) of{" "} - {formatSize(m.totalMemoryBytes)} physical memory. -
- {memorySections(m.memory ?? []).map((sec) => ( -
- - {sec.rows.map((r) => ( - - ))} -
- ))} - - {m.heapBytes != null && } -
- Memory as the OS reports it (macOS: Activity Monitor’s “Memory”; Linux: PSS; Windows: private bytes), - including child processes. -
-
-
- - - - - -
- - - Drops syntax trees and EditorConfig data and compacts the index; they are rebuilt on demand. - -
-
-
- - - - - -
- “Process → main” is spent before any OpenIDEA code runs: exec, code-signature checks and dynamic loading. macOS - scans a freshly built, unsigned debug binary for several seconds on its first launch. -
-
- {error &&
{error}
} -
- ); -} diff --git a/src/features/perf/__tests__/perf.test.ts b/src/features/perf/__tests__/perf.test.ts index c8eea98a..b0379864 100644 --- a/src/features/perf/__tests__/perf.test.ts +++ b/src/features/perf/__tests__/perf.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it, vi } from "vitest"; import type { ProcessMemory } from "@/platform/ipc"; -import { formatBytes, formatCount, formatMs, formatSize, formatUptime, memoryRatio } from "../format"; +import { formatBytes, formatCount, formatMs, formatSize, formatUptime } from "../format"; import { indicatorLabel, indicatorTooltip, memorySections, summarizeMemory } from "../memory"; import { RollingWindow, percentile } from "../stats"; import { isEditorTypingEntry, keystrokeLatencies, supportsEntryType } from "../events"; @@ -26,9 +26,6 @@ describe("format", () => { expect(formatSize(1.1 * GB)).toBe("1.1 GB"); expect(formatSize(12 * 1024)).toBe("12 KB"); expect(formatSize(null)).toBe("–"); - expect(memoryRatio(GB, 2 * GB)).toBe(0.5); - expect(memoryRatio(3 * GB, 2 * GB)).toBe(1); - expect(memoryRatio(null, 2 * GB)).toBe(0); }); it("formats durations and counts", () => { diff --git a/src/features/perf/format.ts b/src/features/perf/format.ts index 5169f1ce..307ead6b 100644 --- a/src/features/perf/format.ts +++ b/src/features/perf/format.ts @@ -29,12 +29,6 @@ export function formatSize(bytes: number | null | undefined): string { return `${trim(bytes / GB)} GB`; } -/** Share (0..1) of `total`, clamped. */ -export function memoryRatio(used: number | null | undefined, total: number | null | undefined): number { - if (!used || !total || total <= 0) return 0; - return Math.min(1, Math.max(0, used / total)); -} - /** `0.4 ms`, `16 ms`, `2.3 s`. */ export function formatMs(ms: number | null | undefined): string { if (ms == null || !Number.isFinite(ms)) return "–"; diff --git a/src/features/perf/index.ts b/src/features/perf/index.ts index 96cd6d62..90f89208 100644 --- a/src/features/perf/index.ts +++ b/src/features/perf/index.ts @@ -1,30 +1,16 @@ /** Memory indicator, "Clear caches" and the dev performance overlay. */ -import { lazyComponent } from "@/ui"; import { registerActions } from "@/platform/actions"; -import { registerOverlay, registerSettingsPage, registerStatusItem } from "@/workbench/contributions"; +import { registerOverlay, registerStatusItem } from "@/workbench/contributions"; import { perfActions } from "./actions"; import { MEMORY_WIDGET, MemoryStatus } from "./MemoryStatus"; import { PerfOverlay } from "./PerfOverlay"; -/** Settings › Memory Usage (also used by the Settings window). */ -export function activateSettingsPages(): () => void { - // Top level after Plugins, as in IDEA. - return registerSettingsPage({ - id: "memory", - title: "Memory Usage", - order: 950, - keywords: ["memory", "ram", "clear caches", "index"], - component: lazyComponent(() => import("./MemoryUsagePage").then((m) => m.MemoryUsagePage)), - }); -} - export function activate(): () => void { const disposers = [ registerActions(perfActions()), // Far right and hidden by default, like IDEA's memory indicator. registerStatusItem({ ...MEMORY_WIDGET, align: "right", priority: 100, component: MemoryStatus }), registerOverlay({ id: "perf.overlay", component: PerfOverlay }), - activateSettingsPages(), ]; return () => disposers.reverse().forEach((d) => d()); }