@ogygia/devtools 0.0.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +24 -1
- package/dist/client.d.ts +3 -0
- package/dist/client.js +24 -0
- package/dist/devtools/BoundaryOverlay.svelte +396 -0
- package/dist/devtools/BoundaryOverlay.svelte.d.ts +19 -0
- package/dist/devtools/Devtools.svelte +663 -0
- package/dist/devtools/Devtools.svelte.d.ts +15 -0
- package/dist/devtools/HubTab.svelte +206 -0
- package/dist/devtools/HubTab.svelte.d.ts +11 -0
- package/dist/devtools/HydrationTab.svelte +237 -0
- package/dist/devtools/HydrationTab.svelte.d.ts +13 -0
- package/dist/devtools/IslandDetail.svelte +615 -0
- package/dist/devtools/IslandDetail.svelte.d.ts +15 -0
- package/dist/devtools/LedgerTab.svelte +287 -0
- package/dist/devtools/LedgerTab.svelte.d.ts +11 -0
- package/dist/devtools/LensTab.svelte +290 -0
- package/dist/devtools/LensTab.svelte.d.ts +19 -0
- package/dist/devtools/NavTab.svelte +229 -0
- package/dist/devtools/NavTab.svelte.d.ts +11 -0
- package/dist/devtools/PageTab.svelte +1122 -0
- package/dist/devtools/PageTab.svelte.d.ts +15 -0
- package/dist/devtools/ProfilerTab.svelte +755 -0
- package/dist/devtools/ProfilerTab.svelte.d.ts +15 -0
- package/dist/devtools/PropsTree.svelte +155 -0
- package/dist/devtools/PropsTree.svelte.d.ts +15 -0
- package/dist/devtools/SessionTab.svelte +796 -0
- package/dist/devtools/SessionTab.svelte.d.ts +11 -0
- package/dist/devtools/TimelineTab.svelte +267 -0
- package/dist/devtools/TimelineTab.svelte.d.ts +11 -0
- package/dist/devtools/WireTab.svelte +149 -0
- package/dist/devtools/WireTab.svelte.d.ts +11 -0
- package/dist/devtools/bytes.d.ts +70 -0
- package/dist/devtools/bytes.js +82 -0
- package/dist/devtools/cache-headers.d.ts +20 -0
- package/dist/devtools/cache-headers.js +81 -0
- package/dist/devtools/highlight.d.ts +7 -0
- package/dist/devtools/highlight.js +83 -0
- package/dist/devtools/hydration.d.ts +48 -0
- package/dist/devtools/hydration.js +93 -0
- package/dist/devtools/index.d.ts +3 -0
- package/dist/devtools/index.js +3 -0
- package/dist/devtools/ledger-dom.d.ts +7 -0
- package/dist/devtools/ledger-dom.js +151 -0
- package/dist/devtools/leftovers.d.ts +77 -0
- package/dist/devtools/leftovers.js +319 -0
- package/dist/devtools/names.d.ts +1 -0
- package/dist/devtools/names.js +34 -0
- package/dist/devtools/page.d.ts +96 -0
- package/dist/devtools/page.js +957 -0
- package/dist/devtools/profile-anchors.d.ts +22 -0
- package/dist/devtools/profile-anchors.js +135 -0
- package/dist/devtools/profile-store.d.ts +175 -0
- package/dist/devtools/profile-store.js +239 -0
- package/dist/devtools/regions.d.ts +77 -0
- package/dist/devtools/regions.js +132 -0
- package/dist/devtools/session.d.ts +31 -0
- package/dist/devtools/session.js +455 -0
- package/dist/devtools/since-load.d.ts +50 -0
- package/dist/devtools/since-load.js +89 -0
- package/dist/devtools/source-lines.d.ts +24 -0
- package/dist/devtools/source-lines.js +106 -0
- package/dist/devtools/styles.d.ts +52 -0
- package/dist/devtools/styles.js +248 -0
- package/dist/devtools/testing-engine.d.ts +83 -0
- package/dist/devtools/testing-engine.js +220 -0
- package/dist/devtools/ui-app.d.ts +5 -0
- package/dist/devtools/ui-app.js +69 -0
- package/dist/devtools/ui.d.ts +50 -0
- package/dist/devtools/ui.js +175 -0
- package/dist/profiler/alloc.d.ts +75 -0
- package/dist/profiler/alloc.js +76 -0
- package/dist/profiler/analyze.d.ts +437 -0
- package/dist/profiler/analyze.js +1941 -0
- package/dist/profiler/app-path.d.ts +7 -0
- package/dist/profiler/app-path.js +26 -0
- package/dist/profiler/async-io.d.ts +58 -0
- package/dist/profiler/async-io.js +187 -0
- package/dist/profiler/beacon-standalone.d.ts +4 -0
- package/dist/profiler/beacon-standalone.js +409 -0
- package/dist/profiler/browser-findings.d.ts +25 -0
- package/dist/profiler/browser-findings.js +260 -0
- package/dist/profiler/byte-strip.d.ts +58 -0
- package/dist/profiler/byte-strip.js +228 -0
- package/dist/profiler/client-files.d.ts +16 -0
- package/dist/profiler/client-files.js +60 -0
- package/dist/profiler/client-windows.d.ts +49 -0
- package/dist/profiler/client-windows.js +95 -0
- package/dist/profiler/client.d.ts +40 -0
- package/dist/profiler/client.js +82 -0
- package/dist/profiler/compare.d.ts +308 -0
- package/dist/profiler/compare.js +733 -0
- package/dist/profiler/compress.d.ts +10 -0
- package/dist/profiler/compress.js +36 -0
- package/dist/profiler/contention.d.ts +60 -0
- package/dist/profiler/contention.js +86 -0
- package/dist/profiler/crypto.d.ts +19 -0
- package/dist/profiler/crypto.js +101 -0
- package/dist/profiler/doc-diff.d.ts +47 -0
- package/dist/profiler/doc-diff.js +214 -0
- package/dist/profiler/dom-diff.d.ts +43 -0
- package/dist/profiler/dom-diff.js +121 -0
- package/dist/profiler/drill.d.ts +89 -0
- package/dist/profiler/drill.js +553 -0
- package/dist/profiler/embedded-maps.d.ts +37 -0
- package/dist/profiler/embedded-maps.js +135 -0
- package/dist/profiler/env.d.ts +6 -0
- package/dist/profiler/env.js +10 -0
- package/dist/profiler/forecast.d.ts +76 -0
- package/dist/profiler/forecast.js +225 -0
- package/dist/profiler/frames.d.ts +11 -0
- package/dist/profiler/frames.js +42 -0
- package/dist/profiler/gc.d.ts +144 -0
- package/dist/profiler/gc.js +271 -0
- package/dist/profiler/hole-slots.d.ts +31 -0
- package/dist/profiler/hole-slots.js +90 -0
- package/dist/profiler/index.d.ts +288 -0
- package/dist/profiler/index.js +4921 -0
- package/dist/profiler/insights.d.ts +96 -0
- package/dist/profiler/insights.js +239 -0
- package/dist/profiler/ledger.d.ts +121 -0
- package/dist/profiler/ledger.js +440 -0
- package/dist/profiler/lineage.d.ts +81 -0
- package/dist/profiler/lineage.js +359 -0
- package/dist/profiler/module-map.d.ts +12 -0
- package/dist/profiler/module-map.js +94 -0
- package/dist/profiler/net.d.ts +169 -0
- package/dist/profiler/net.js +586 -0
- package/dist/profiler/on-demand.d.ts +11 -0
- package/dist/profiler/on-demand.js +15 -0
- package/dist/profiler/own-requests.d.ts +9 -0
- package/dist/profiler/own-requests.js +17 -0
- package/dist/profiler/patterns.d.ts +476 -0
- package/dist/profiler/patterns.js +2203 -0
- package/dist/profiler/profiler-router.d.ts +245 -0
- package/dist/profiler/profiler-router.js +113 -0
- package/dist/profiler/refresh-stub.d.ts +2 -0
- package/dist/profiler/refresh-stub.js +37 -0
- package/dist/profiler/report.d.ts +1404 -0
- package/dist/profiler/report.js +2638 -0
- package/dist/profiler/river.d.ts +65 -0
- package/dist/profiler/river.js +298 -0
- package/dist/profiler/route-files.d.ts +22 -0
- package/dist/profiler/route-files.js +55 -0
- package/dist/profiler/route-imports.d.ts +14 -0
- package/dist/profiler/route-imports.js +83 -0
- package/dist/profiler/saving.d.ts +22 -0
- package/dist/profiler/saving.js +42 -0
- package/dist/profiler/score.d.ts +109 -0
- package/dist/profiler/score.js +261 -0
- package/dist/profiler/session-cookie.d.ts +28 -0
- package/dist/profiler/session-cookie.js +45 -0
- package/dist/profiler/sink.d.ts +81 -0
- package/dist/profiler/sink.js +124 -0
- package/dist/profiler/site-fixes.d.ts +25 -0
- package/dist/profiler/site-fixes.js +62 -0
- package/dist/profiler/source-scan.d.ts +210 -0
- package/dist/profiler/source-scan.js +1724 -0
- package/dist/profiler/span.d.ts +90 -0
- package/dist/profiler/span.js +109 -0
- package/dist/profiler/stacks.d.ts +43 -0
- package/dist/profiler/stacks.js +107 -0
- package/dist/profiler/standalone.d.ts +27 -0
- package/dist/profiler/standalone.js +98 -0
- package/dist/profiler/steps.d.ts +39 -0
- package/dist/profiler/steps.js +74 -0
- package/dist/profiler/storage/index.d.ts +87 -0
- package/dist/profiler/storage/index.js +76 -0
- package/dist/profiler/storage/postgres.d.ts +12 -0
- package/dist/profiler/storage/postgres.js +94 -0
- package/dist/profiler/storage/redis.d.ts +19 -0
- package/dist/profiler/storage/redis.js +148 -0
- package/dist/profiler/storage/sqlite.d.ts +2 -0
- package/dist/profiler/storage/sqlite.js +85 -0
- package/dist/profiler/storage/visits.d.ts +4 -0
- package/dist/profiler/storage/visits.js +6 -0
- package/dist/profiler/stream-tail.d.ts +26 -0
- package/dist/profiler/stream-tail.js +74 -0
- package/dist/profiler/timeline.d.ts +279 -0
- package/dist/profiler/timeline.js +690 -0
- package/dist/profiler/ui/AllocStrip.svelte +146 -0
- package/dist/profiler/ui/AllocStrip.svelte.d.ts +17 -0
- package/dist/profiler/ui/Awaits.svelte +363 -0
- package/dist/profiler/ui/Awaits.svelte.d.ts +16 -0
- package/dist/profiler/ui/ByteStrip.svelte +182 -0
- package/dist/profiler/ui/ByteStrip.svelte.d.ts +18 -0
- package/dist/profiler/ui/Compare.svelte +24 -0
- package/dist/profiler/ui/Compare.svelte.d.ts +16 -0
- package/dist/profiler/ui/CompareBody.svelte +429 -0
- package/dist/profiler/ui/CompareBody.svelte.d.ts +8 -0
- package/dist/profiler/ui/ComponentsTable.svelte +265 -0
- package/dist/profiler/ui/ComponentsTable.svelte.d.ts +20 -0
- package/dist/profiler/ui/Dashboard.svelte +492 -0
- package/dist/profiler/ui/Dashboard.svelte.d.ts +31 -0
- package/dist/profiler/ui/DataRiver.svelte +206 -0
- package/dist/profiler/ui/DataRiver.svelte.d.ts +13 -0
- package/dist/profiler/ui/DomTravel.svelte +207 -0
- package/dist/profiler/ui/DomTravel.svelte.d.ts +9 -0
- package/dist/profiler/ui/DownloadHtml.svelte +52 -0
- package/dist/profiler/ui/DownloadHtml.svelte.d.ts +10 -0
- package/dist/profiler/ui/Drill.svelte +276 -0
- package/dist/profiler/ui/Drill.svelte.d.ts +12 -0
- package/dist/profiler/ui/ExportButton.svelte +59 -0
- package/dist/profiler/ui/ExportButton.svelte.d.ts +8 -0
- package/dist/profiler/ui/Flame.svelte +222 -0
- package/dist/profiler/ui/Flame.svelte.d.ts +12 -0
- package/dist/profiler/ui/FrameDetails.svelte +308 -0
- package/dist/profiler/ui/FrameDetails.svelte.d.ts +16 -0
- package/dist/profiler/ui/FunctionsTable.svelte +156 -0
- package/dist/profiler/ui/FunctionsTable.svelte.d.ts +17 -0
- package/dist/profiler/ui/IslandHeatmap.svelte +151 -0
- package/dist/profiler/ui/IslandHeatmap.svelte.d.ts +16 -0
- package/dist/profiler/ui/IslandsTable.svelte +448 -0
- package/dist/profiler/ui/IslandsTable.svelte.d.ts +16 -0
- package/dist/profiler/ui/KeepLocal.svelte +46 -0
- package/dist/profiler/ui/KeepLocal.svelte.d.ts +8 -0
- package/dist/profiler/ui/Ledger.svelte +196 -0
- package/dist/profiler/ui/Ledger.svelte.d.ts +18 -0
- package/dist/profiler/ui/LocalCompare.svelte +48 -0
- package/dist/profiler/ui/LocalCompare.svelte.d.ts +8 -0
- package/dist/profiler/ui/LocalReports.svelte +68 -0
- package/dist/profiler/ui/LocalReports.svelte.d.ts +7 -0
- package/dist/profiler/ui/Login.svelte +13 -0
- package/dist/profiler/ui/Login.svelte.d.ts +12 -0
- package/dist/profiler/ui/LoginForm.svelte +42 -0
- package/dist/profiler/ui/LoginForm.svelte.d.ts +7 -0
- package/dist/profiler/ui/Message.svelte +10 -0
- package/dist/profiler/ui/Message.svelte.d.ts +12 -0
- package/dist/profiler/ui/OnThisPage.svelte +137 -0
- package/dist/profiler/ui/OnThisPage.svelte.d.ts +3 -0
- package/dist/profiler/ui/OneClock.svelte +297 -0
- package/dist/profiler/ui/OneClock.svelte.d.ts +27 -0
- package/dist/profiler/ui/Panel.svelte +10 -0
- package/dist/profiler/ui/Panel.svelte.d.ts +16 -0
- package/dist/profiler/ui/Paths.svelte +269 -0
- package/dist/profiler/ui/Paths.svelte.d.ts +15 -0
- package/dist/profiler/ui/Patterns.svelte +364 -0
- package/dist/profiler/ui/Patterns.svelte.d.ts +15 -0
- package/dist/profiler/ui/PermalinkGate.svelte +143 -0
- package/dist/profiler/ui/PermalinkGate.svelte.d.ts +10 -0
- package/dist/profiler/ui/RenderSteps.svelte +218 -0
- package/dist/profiler/ui/RenderSteps.svelte.d.ts +13 -0
- package/dist/profiler/ui/Report.svelte +28 -0
- package/dist/profiler/ui/Report.svelte.d.ts +20 -0
- package/dist/profiler/ui/ReportBody.svelte +2592 -0
- package/dist/profiler/ui/ReportBody.svelte.d.ts +21 -0
- package/dist/profiler/ui/Run.svelte +17 -0
- package/dist/profiler/ui/Run.svelte.d.ts +14 -0
- package/dist/profiler/ui/RunView.svelte +146 -0
- package/dist/profiler/ui/RunView.svelte.d.ts +10 -0
- package/dist/profiler/ui/ScoreCard.svelte +197 -0
- package/dist/profiler/ui/ScoreCard.svelte.d.ts +7 -0
- package/dist/profiler/ui/Scrub.svelte +293 -0
- package/dist/profiler/ui/Scrub.svelte.d.ts +18 -0
- package/dist/profiler/ui/SeedExplainer.svelte +193 -0
- package/dist/profiler/ui/SeedExplainer.svelte.d.ts +16 -0
- package/dist/profiler/ui/ShareLink.svelte +148 -0
- package/dist/profiler/ui/ShareLink.svelte.d.ts +8 -0
- package/dist/profiler/ui/Shell.svelte +50 -0
- package/dist/profiler/ui/Shell.svelte.d.ts +27 -0
- package/dist/profiler/ui/Sidebar.svelte +312 -0
- package/dist/profiler/ui/Sidebar.svelte.d.ts +7 -0
- package/dist/profiler/ui/Site.svelte +20 -0
- package/dist/profiler/ui/Site.svelte.d.ts +23 -0
- package/dist/profiler/ui/SiteView.svelte +385 -0
- package/dist/profiler/ui/SiteView.svelte.d.ts +27 -0
- package/dist/profiler/ui/ThemeSwitch.svelte +78 -0
- package/dist/profiler/ui/ThemeSwitch.svelte.d.ts +3 -0
- package/dist/profiler/ui/Timeline.svelte +672 -0
- package/dist/profiler/ui/Timeline.svelte.d.ts +22 -0
- package/dist/profiler/ui/Treemap.svelte +278 -0
- package/dist/profiler/ui/Treemap.svelte.d.ts +20 -0
- package/dist/profiler/ui/Upload.svelte +19 -0
- package/dist/profiler/ui/Upload.svelte.d.ts +10 -0
- package/dist/profiler/ui/UploadForm.svelte +59 -0
- package/dist/profiler/ui/UploadForm.svelte.d.ts +6 -0
- package/dist/profiler/ui/WaitingTable.svelte +55 -0
- package/dist/profiler/ui/WaitingTable.svelte.d.ts +14 -0
- package/dist/profiler/ui/Waterfall.svelte +371 -0
- package/dist/profiler/ui/Waterfall.svelte.d.ts +7 -0
- package/dist/profiler/ui/WhatIf.svelte +87 -0
- package/dist/profiler/ui/WhatIf.svelte.d.ts +18 -0
- package/dist/profiler/ui/fake-progress.svelte.d.ts +15 -0
- package/dist/profiler/ui/fake-progress.svelte.js +38 -0
- package/dist/profiler/ui/format.d.ts +20 -0
- package/dist/profiler/ui/format.js +71 -0
- package/dist/profiler/ui/permalink.d.ts +9 -0
- package/dist/profiler/ui/permalink.js +108 -0
- package/dist/profiler/ui/press.d.ts +5 -0
- package/dist/profiler/ui/press.js +19 -0
- package/dist/profiler/ui/profiler.css +650 -0
- package/dist/profiler/ui/report-data.d.ts +189 -0
- package/dist/profiler/ui/report-data.js +393 -0
- package/dist/profiler/ui/report-request.d.ts +6 -0
- package/dist/profiler/ui/report-request.js +50 -0
- package/dist/profiler/ui/row-anchor.svelte.d.ts +12 -0
- package/dist/profiler/ui/row-anchor.svelte.js +44 -0
- package/dist/profiler/ui/sort.svelte.d.ts +14 -0
- package/dist/profiler/ui/sort.svelte.js +37 -0
- package/dist/profiler/ui/store.d.ts +45 -0
- package/dist/profiler/ui/store.js +92 -0
- package/dist/profiler/visit.d.ts +389 -0
- package/dist/profiler/visit.js +1002 -0
- package/dist/report.d.ts +5 -0
- package/dist/report.js +4 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +38 -0
- package/dist/vite.d.ts +12 -0
- package/dist/vite.js +78 -0
- package/package.json +105 -6
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import { DocDiff } from "./doc-diff.js";
|
|
2
|
+
import { FrameStat } from "./analyze.js";
|
|
3
|
+
import { LedgerLine } from "./ledger.js";
|
|
4
|
+
import { RetainedSite } from "./insights.js";
|
|
5
|
+
import { AwaitEdge, AwaitNode } from "./timeline.js";
|
|
6
|
+
import { SourceReader, tokens } from "./source-scan.js";
|
|
7
|
+
export type PatternKind = "formatter-per-call" | "rescan-in-loop" | "lookup-in-loop" | "table-per-call" | "regexp-per-call" | "slow-regex" | "deep-copy" | "spread-accumulate" | "string-build" | "sort-per-call" | "date-parse" | "sync-io" | "yield-per-item" | "scan-for-key" | "library-per-item" | "waits-in-a-row" | "repeat-request" | "same-answer" | "almost-same-answer" | "kept-per-render" | "seed-whole-read" | "cache-never-hits" | "same-every-request" | "render-per-item" | "late-island-wait" | "batch-straggler" | "same-document" | "almost-same-document";
|
|
8
|
+
/** a two-or-three-word tag for each kind, for a badge beside a line */
|
|
9
|
+
export declare const PATTERN_LABEL: Record<PatternKind, string>;
|
|
10
|
+
export interface PatternSite {
|
|
11
|
+
path: string;
|
|
12
|
+
file: string;
|
|
13
|
+
line: number;
|
|
14
|
+
/** a line of a built chunk: the source module it came from (see LedgerLine.module) */
|
|
15
|
+
module?: string;
|
|
16
|
+
code: string;
|
|
17
|
+
/** the function row this line belongs to (functions table key), when known */
|
|
18
|
+
fn?: string;
|
|
19
|
+
fn_name?: string;
|
|
20
|
+
/** same every request: every function the line calls — all of it leaves the request with the
|
|
21
|
+
* line (`injectBadges(sitemapHtml(PRODUCTS))` takes both) */
|
|
22
|
+
moves?: string[];
|
|
23
|
+
cpu_ms: number;
|
|
24
|
+
alloc_bytes: number;
|
|
25
|
+
gc_ms: number;
|
|
26
|
+
/** how many times the function ran, when V8 counted it */
|
|
27
|
+
calls?: number;
|
|
28
|
+
/** the site sits inside a loop (a `for`, a `.map(`, an `{#each}`) */
|
|
29
|
+
in_loop: boolean;
|
|
30
|
+
/** CPU inside the libraries this line called (ledger `lib_ms`) */
|
|
31
|
+
lib_ms?: number;
|
|
32
|
+
/** those library functions, `name (pkg)` */
|
|
33
|
+
libs?: string[];
|
|
34
|
+
/** the site is inside a thin wrapper: the lines in ITS callers that call it (the place a cache
|
|
35
|
+
* or a batch goes), each with whether that call runs in a loop */
|
|
36
|
+
via?: CallSite[];
|
|
37
|
+
/** a memory site: bytes it left alive after one more warm render */
|
|
38
|
+
kept_bytes?: number;
|
|
39
|
+
/** a memory site: some of it was kept INSIDE this package, which the line calls */
|
|
40
|
+
mem_via?: string;
|
|
41
|
+
/** a cache site: how many of the function's calls the cache answered */
|
|
42
|
+
hits?: number;
|
|
43
|
+
/** a same-answer site: the size of the answer that came back unchanged every render */
|
|
44
|
+
answer_bytes?: number;
|
|
45
|
+
/** a same-answer site whose requests carried who is asking (cookie / authorization): cache per user */
|
|
46
|
+
personal?: boolean;
|
|
47
|
+
/** a same-answer site: what the service's own Cache-Control allows (seconds to keep a copy; not to
|
|
48
|
+
* store it at all; one user's) */
|
|
49
|
+
upstream_cache?: CacheRules;
|
|
50
|
+
/** the change, written out: these exact lines, and what to put in their place (a waits-in-a-row
|
|
51
|
+
* chain of plain one-line awaits, proven independent, as one Promise.all) */
|
|
52
|
+
rewrite?: {
|
|
53
|
+
file: string;
|
|
54
|
+
line: number;
|
|
55
|
+
before: string;
|
|
56
|
+
after: string;
|
|
57
|
+
};
|
|
58
|
+
/** a memory site the growth check measured: still growing every render, or flat after one */
|
|
59
|
+
grows?: boolean;
|
|
60
|
+
/** a waiting site: the ms its calls waited in a row */
|
|
61
|
+
wait_ms?: number;
|
|
62
|
+
/** a waiting site: what it waited on (`GET api.shop.test/stock/:id`, `file read`) */
|
|
63
|
+
target?: string;
|
|
64
|
+
/** the code around the site (two lines each side), so the loop or the value it uses shows */
|
|
65
|
+
context?: {
|
|
66
|
+
start: number;
|
|
67
|
+
lines: string[];
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export interface CallSite {
|
|
71
|
+
path: string;
|
|
72
|
+
file: string;
|
|
73
|
+
line: number;
|
|
74
|
+
/** a line of a built chunk: the source module it came from (see LedgerLine.module) */
|
|
75
|
+
module?: string;
|
|
76
|
+
code: string;
|
|
77
|
+
/** the calling function (functions table key) */
|
|
78
|
+
fn?: string;
|
|
79
|
+
in_loop: boolean;
|
|
80
|
+
}
|
|
81
|
+
export interface Pattern {
|
|
82
|
+
kind: PatternKind;
|
|
83
|
+
/** what is happening, in plain words */
|
|
84
|
+
title: string;
|
|
85
|
+
/** what to do about it */
|
|
86
|
+
fix: string;
|
|
87
|
+
/** a tiny before → after, when one says it better than words */
|
|
88
|
+
example?: {
|
|
89
|
+
before: string;
|
|
90
|
+
after: string;
|
|
91
|
+
};
|
|
92
|
+
sites: PatternSite[];
|
|
93
|
+
/** the measured cost on the sites: CPU plus the GC their allocations caused */
|
|
94
|
+
cost_ms: number;
|
|
95
|
+
/** bytes the sites allocated */
|
|
96
|
+
alloc_bytes: number;
|
|
97
|
+
/** a rough estimate of the ms a fix gives back (a share of cost_ms that depends on the kind) */
|
|
98
|
+
save_ms: number;
|
|
99
|
+
/** the numbers behind it, one line */
|
|
100
|
+
evidence: string;
|
|
101
|
+
/** the cost is WAITING (calls in a row), not CPU: `cost_ms` / `save_ms` are wall-clock waits */
|
|
102
|
+
wait?: boolean;
|
|
103
|
+
/** the cost is MEMORY kept alive after a render: `kept_bytes` is it, and there is no time saving */
|
|
104
|
+
kept_bytes?: number;
|
|
105
|
+
/** a memory pattern: requests left before the heap is full at this rate (from the heap's room now) */
|
|
106
|
+
requests_left?: number;
|
|
107
|
+
/** a memory pattern the growth check measured: it kept climbing, or it levelled off */
|
|
108
|
+
growth?: "grows" | "levels-off";
|
|
109
|
+
/** a size pattern (ogygia's page seed): the bytes it makes ship with every page view */
|
|
110
|
+
seed_bytes?: number;
|
|
111
|
+
/** waits in a row: each site's chain, its calls in order on the recording's clock */
|
|
112
|
+
chains?: {
|
|
113
|
+
start: number;
|
|
114
|
+
ms: number;
|
|
115
|
+
}[][];
|
|
116
|
+
/** waits in a row: the saving the simple sum promised (every wait but the longest), kept when the
|
|
117
|
+
* critical-path check cut `save_ms` below it */
|
|
118
|
+
naive_save_ms?: number;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* THE CRITICAL PATH, not the sum: a chain of waits started together ends when its longest call
|
|
122
|
+
* does, but the render goes on only once whatever ran BESIDE the chain is done too (Kit waits for
|
|
123
|
+
* a layout load running alongside a page load; a Promise.all waits for all). So the time that
|
|
124
|
+
* really comes off is the chain's end minus the later of its new end and the end (up to the old
|
|
125
|
+
* chain end) of any call that overlapped it. Only calls that overlapped count: a call that started
|
|
126
|
+
* after the chain ended comes later and moves up with it, it is not beside it. Each chain call is
|
|
127
|
+
* found in the render's await graph by its start and length; undefined when the graph does not
|
|
128
|
+
* hold the chains (another window, a capped graph).
|
|
129
|
+
*/
|
|
130
|
+
export declare function wait_save_on_path(p: Pick<Pattern, "chains">, awaits: {
|
|
131
|
+
nodes: AwaitNode[];
|
|
132
|
+
edges: AwaitEdge[];
|
|
133
|
+
} | undefined, _window_ms: number, w0: number): {
|
|
134
|
+
save_ms: number;
|
|
135
|
+
bound_by?: string;
|
|
136
|
+
} | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* THE SAME ANSWER EVERY TIME: the GET calls that ran in EVERY profiled render and got the same bytes
|
|
139
|
+
* back each time (the body fingerprint net.ts takes). Across requests the render asks for data that
|
|
140
|
+
* did not change: an answer to cache (a CMS entry, a config, a price list, flags). Keyed like a
|
|
141
|
+
* wait's `exact` (`GET <url>`). Needs two renders or more; a call whose body was not read (no
|
|
142
|
+
* fingerprint) or that failed never counts.
|
|
143
|
+
*/
|
|
144
|
+
export declare function stable_answers(calls: readonly {
|
|
145
|
+
method: string;
|
|
146
|
+
url: string;
|
|
147
|
+
status: number;
|
|
148
|
+
start: number;
|
|
149
|
+
body_hash?: string;
|
|
150
|
+
}[], runs: readonly {
|
|
151
|
+
start: number;
|
|
152
|
+
end: number;
|
|
153
|
+
}[]): Set<string>;
|
|
154
|
+
/** the GETs made in EVERY render whose answers were NOT the same bytes each time (`GET <url>`):
|
|
155
|
+
* the candidates for "almost the same answer" (net.ts `answer_diff` says how little changed) */
|
|
156
|
+
export declare function varied_answers(calls: readonly {
|
|
157
|
+
method: string;
|
|
158
|
+
url: string;
|
|
159
|
+
status: number;
|
|
160
|
+
start: number;
|
|
161
|
+
body_hash?: string;
|
|
162
|
+
}[], runs: readonly {
|
|
163
|
+
start: number;
|
|
164
|
+
end: number;
|
|
165
|
+
}[]): Set<string>;
|
|
166
|
+
/**
|
|
167
|
+
* THE SAME ANSWER, EVERY RENDER — the pattern: the calls of one render whose exact request (`stable`,
|
|
168
|
+
* from `stable_answers`) answered the same bytes in every profiled render. Each place that makes one
|
|
169
|
+
* is listed with what it waits, how big the answer is, and the line to cache at. The saving is what
|
|
170
|
+
* comes off the render when the calls are answered from a cache: each one's end moves to its start,
|
|
171
|
+
* except where another call (not cached) overlapped it and still sets the end — read off the
|
|
172
|
+
* render's await graph when it holds the calls, else each call's own wait.
|
|
173
|
+
*/
|
|
174
|
+
export declare function find_same_answers(input: {
|
|
175
|
+
calls: readonly WaitCall[];
|
|
176
|
+
stable: ReadonlySet<string>;
|
|
177
|
+
source?: SourceReader;
|
|
178
|
+
awaits?: {
|
|
179
|
+
nodes: AwaitNode[];
|
|
180
|
+
edges: AwaitEdge[];
|
|
181
|
+
};
|
|
182
|
+
w0?: number;
|
|
183
|
+
/** ALMOST the same: the answers that differed between renders only in a small stretch, with that
|
|
184
|
+
* stretch (`GET <url>` → text): the same cache, minus the part that changes */
|
|
185
|
+
almost?: ReadonlyMap<string, string>;
|
|
186
|
+
}): Pattern | undefined;
|
|
187
|
+
export interface PatternInput {
|
|
188
|
+
ledger: readonly LedgerLine[];
|
|
189
|
+
functions: readonly FrameStat[];
|
|
190
|
+
/** lines `from`..`to` of a source file (1-based, inclusive), untrimmed */
|
|
191
|
+
source?: SourceReader;
|
|
192
|
+
/** how many renders the profile's CPU numbers add up (page mode's runs), for the wording */
|
|
193
|
+
renders?: number;
|
|
194
|
+
/** the V8 heap's limit and what is in use now, for a leak's countdown; `function`: the ceiling
|
|
195
|
+
* is the serverless function's memory size (AWS Lambda), smaller than the heap, and what is in
|
|
196
|
+
* use is the process's resident memory */
|
|
197
|
+
heap?: {
|
|
198
|
+
limit_bytes: number;
|
|
199
|
+
used_bytes: number;
|
|
200
|
+
function?: boolean;
|
|
201
|
+
};
|
|
202
|
+
/** a few more renders with a collection after each: confirms a leak, or shows it levels off */
|
|
203
|
+
growth?: HeapGrowth;
|
|
204
|
+
}
|
|
205
|
+
/** Where the LAST line of `lines` (a function's body, from its first line) runs in a loop: the
|
|
206
|
+
* token index on that line from which code is inside one. 0 when the whole line is (an enclosing
|
|
207
|
+
* loop body), the index after a loop header on the line itself (`for (…) x = f(x)`, `xs.map(`),
|
|
208
|
+
* -1 when none of it is. Tracks brace blocks: a block opened after a loop header (`for`, `while`,
|
|
209
|
+
* `do`, a `.map(` / `.forEach(` callback) is a loop body. A Svelte file counts `{#each}` too. */
|
|
210
|
+
export declare function loop_from(lines: readonly string[], svelte?: boolean): number;
|
|
211
|
+
/** Does any of the last line of `lines` run inside a loop? (`loop_from` ≥ 0) */
|
|
212
|
+
export declare const in_loop: (lines: readonly string[], svelte?: boolean) => boolean;
|
|
213
|
+
/**
|
|
214
|
+
* SYNC I/O TOO QUICK TO SAMPLE: a small file read on every request finishes under the CPU
|
|
215
|
+
* sampler's interval, so no sample lands on it, yet it blocks every other request on the server
|
|
216
|
+
* while the disk answers (a cold disk or a bigger file makes it long). V8's call counts (the
|
|
217
|
+
* coverage render) count Node's own `readFileSync` like any function: a *Sync call counted in the
|
|
218
|
+
* render, at a line of the route's own files inside a function the render ran (counted too), is
|
|
219
|
+
* one. Module top-level code runs once at start-up and is left out. Pure: the counts and the files'
|
|
220
|
+
* text in, the pattern out (undefined when nothing qualifies). No regex.
|
|
221
|
+
*/
|
|
222
|
+
export declare function counted_sync_io(counts: Readonly<Record<string, number>>, files: readonly {
|
|
223
|
+
path: string;
|
|
224
|
+
file: string;
|
|
225
|
+
text: string;
|
|
226
|
+
}[]): Pattern | undefined;
|
|
227
|
+
export declare function find_patterns(input: PatternInput): Pattern[];
|
|
228
|
+
/** one finished wait, from the network log or the I/O log */
|
|
229
|
+
export interface WaitCall {
|
|
230
|
+
start: number;
|
|
231
|
+
/** the whole wait: headers + body for a fetch, init → destroy for an I/O resource */
|
|
232
|
+
ms: number;
|
|
233
|
+
/** what it waited on, as a group label (`GET api.shop.test/stock/:id`, `file read`) */
|
|
234
|
+
target: string;
|
|
235
|
+
/** the app line that made the call */
|
|
236
|
+
at?: {
|
|
237
|
+
path: string;
|
|
238
|
+
line: number;
|
|
239
|
+
};
|
|
240
|
+
/** the line that called THAT function, when the call sits in a helper (`fetchStock`) */
|
|
241
|
+
outer?: {
|
|
242
|
+
path: string;
|
|
243
|
+
line: number;
|
|
244
|
+
};
|
|
245
|
+
/** the page it served (calls of different requests never chain) */
|
|
246
|
+
scope?: string | null;
|
|
247
|
+
/** the exact request, for a read (`GET https://api/session?x=1`): two with the same one in a render
|
|
248
|
+
* asked for the same answer. Absent for writes, whose repeats can be on purpose. */
|
|
249
|
+
exact?: string;
|
|
250
|
+
/** the decoded body size, when read */
|
|
251
|
+
bytes?: number;
|
|
252
|
+
/** the request carried a cookie or an authorization header (its answer may be per user) */
|
|
253
|
+
personal?: boolean;
|
|
254
|
+
/** the answer's own `Cache-Control`, as the service sent it */
|
|
255
|
+
cache?: string;
|
|
256
|
+
}
|
|
257
|
+
export type CacheRules = {
|
|
258
|
+
max_age?: number;
|
|
259
|
+
no_store?: boolean;
|
|
260
|
+
no_cache?: boolean;
|
|
261
|
+
private?: boolean;
|
|
262
|
+
};
|
|
263
|
+
/** What a service's `Cache-Control` allows: how long a copy may be kept (s-maxage over max-age, for
|
|
264
|
+
* a shared cache), whether it must not be stored, must be checked with the service before every
|
|
265
|
+
* reuse (`no-cache`, or a max-age of 0), or is one user's. Split by hand, no regex. */
|
|
266
|
+
export declare function cache_rules(header: string | undefined): CacheRules | undefined;
|
|
267
|
+
export interface WaitInput {
|
|
268
|
+
calls: readonly WaitCall[];
|
|
269
|
+
source?: SourceReader;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* THE WAITS IN A ROW: calls made from ONE line whose waits did not overlap — each started after
|
|
273
|
+
* the one before it ended — so the line waited for them one by one (`for (…) await fetch(…)`).
|
|
274
|
+
* Measured, not guessed: the sum of the waits is what the line cost in wall time, the longest
|
|
275
|
+
* one is about what it would cost if they ran together, and the difference is the saving.
|
|
276
|
+
*/
|
|
277
|
+
export declare function find_wait_patterns(input: WaitInput): Pattern[];
|
|
278
|
+
export interface FixImpact {
|
|
279
|
+
/** estimated CPU a fix of every pattern gives back, ms */
|
|
280
|
+
cpu_ms: number;
|
|
281
|
+
/** estimated waiting it gives back, ms */
|
|
282
|
+
wait_ms: number;
|
|
283
|
+
/** the render it is measured against (median of the runs), ms */
|
|
284
|
+
render_ms: number;
|
|
285
|
+
/** the render after the fixes, about; never below a tenth of today's */
|
|
286
|
+
after_ms: number;
|
|
287
|
+
/** share of the render the fixes take off, 0..90 */
|
|
288
|
+
pct: number;
|
|
289
|
+
}
|
|
290
|
+
/** "Fix these and the render goes from 754 ms to ~300 ms." Each costly line belongs to one pattern,
|
|
291
|
+
* so the savings add without counting a line twice; the sum is capped at 90 % of the render (an
|
|
292
|
+
* estimate never promises a free page). Undefined without a render to measure against.
|
|
293
|
+
*
|
|
294
|
+
* UNITS: a CPU pattern's numbers add up the whole recording — `renders` renders in page mode —
|
|
295
|
+
* while a waiting pattern is measured on ONE render (the network log is scoped to one run). CPU
|
|
296
|
+
* savings are divided by `renders` so both are per render, like `render_ms`. */
|
|
297
|
+
export declare function fix_impact(patterns: readonly Pick<Pattern, "save_ms" | "wait">[], render_ms: number, renders?: number, wait_ms?: number): FixImpact | undefined;
|
|
298
|
+
export interface HeapGrowth {
|
|
299
|
+
/** renders measured (each followed by a full collection) */
|
|
300
|
+
renders: number;
|
|
301
|
+
/** used heap after the first collection, and after the last render's */
|
|
302
|
+
start_bytes: number;
|
|
303
|
+
end_bytes: number;
|
|
304
|
+
/** average growth per render */
|
|
305
|
+
per_render_bytes: number;
|
|
306
|
+
/** the second half of the renders grew far less than the first: a bounded cache filling up */
|
|
307
|
+
levels_off: boolean;
|
|
308
|
+
/** the used heap after each collection, MB */
|
|
309
|
+
series_mb: number[];
|
|
310
|
+
/** what each allocation line still held after all the renders (a live sample across them) */
|
|
311
|
+
sites?: RetainedSite[];
|
|
312
|
+
/** the same sampler read halfway (after `half_renders`): a leaking line grows from it in step */
|
|
313
|
+
half_renders?: number;
|
|
314
|
+
half_sites?: RetainedSite[];
|
|
315
|
+
}
|
|
316
|
+
/** A leak grows the same every render; a cache with a size limit grows, then stops. The second
|
|
317
|
+
* half's rate against the first half's tells them apart; under 64 KB a render is flat either way. */
|
|
318
|
+
/** A growth series (the settled heap before, then after each render) that is FLAT: under 32 KB a
|
|
319
|
+
* render (half of `heap_growth`'s line), and every settled reading after the first render within
|
|
320
|
+
* 256 KB of the others — more renders could not make it grow, so the check may stop. */
|
|
321
|
+
export declare function is_flat(series: readonly number[]): boolean;
|
|
322
|
+
/** A LEAK PAST DOUBT after three renders: each kept 16 MB or more, the largest step at most half again
|
|
323
|
+
* the smallest — steady growth no further render can turn into "it levels off", and each more render
|
|
324
|
+
* takes that much of the measured server's heap (/hell: 70 MB a render, six renders, 9 s and 420 MB
|
|
325
|
+
* of the instance's memory for a verdict the first three gave). A smaller leak keeps the full check:
|
|
326
|
+
* its halfway read is what tells a growing line from a bounded cache still filling. */
|
|
327
|
+
export declare function is_clear_leak(series: readonly number[]): boolean;
|
|
328
|
+
export declare function heap_growth(series: readonly number[]): HeapGrowth | undefined;
|
|
329
|
+
export interface WholeReader {
|
|
330
|
+
/** the component, as the page names it */
|
|
331
|
+
name: string;
|
|
332
|
+
/** its file (for display and the row) */
|
|
333
|
+
file: string;
|
|
334
|
+
line: number;
|
|
335
|
+
code: string;
|
|
336
|
+
context?: {
|
|
337
|
+
start: number;
|
|
338
|
+
lines: string[];
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* THE SEED SHIPS WHOLE BECAUSE OF A LINE: an island that takes `page.data` whole (a spread, a
|
|
343
|
+
* pass-through, `const d = page.data`) makes every key ship to the browser, in every page view.
|
|
344
|
+
* The seed explainer knew WHICH islands; this points at the line in each that does it, with the
|
|
345
|
+
* bytes it costs. A size, not a time: no saving in ms is claimed.
|
|
346
|
+
*/
|
|
347
|
+
export declare function seed_whole_pattern(readers: readonly WholeReader[], seed_bytes: number, top?: {
|
|
348
|
+
key: string;
|
|
349
|
+
bytes: number;
|
|
350
|
+
}): Pattern | undefined;
|
|
351
|
+
export interface ConstantWork {
|
|
352
|
+
path: string;
|
|
353
|
+
file: string;
|
|
354
|
+
line: number;
|
|
355
|
+
code: string;
|
|
356
|
+
/** what the line names (`valid`) and the functions it runs */
|
|
357
|
+
names: string[];
|
|
358
|
+
calls: string[];
|
|
359
|
+
/** CPU the line and its functions took, over every profiled render (ms) */
|
|
360
|
+
cpu_ms: number;
|
|
361
|
+
context?: PatternSite["context"];
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* THE SAME WORK EVERY REQUEST: load lines whose value depends only on the module (source-scan
|
|
365
|
+
* `constant_work`), with the CPU they took. The CPU twin of `same-answer`: every request computes
|
|
366
|
+
* the same result again. Saving: all of it (computed once, at module load or on first use).
|
|
367
|
+
*/
|
|
368
|
+
export declare function same_work_pattern(work: readonly ConstantWork[], renders: number): Pattern | undefined;
|
|
369
|
+
export interface PerItemRender {
|
|
370
|
+
/** the component rendered once per item, its renders in one render of the page and its time
|
|
371
|
+
* over every profiled render */
|
|
372
|
+
component: string;
|
|
373
|
+
instances: number;
|
|
374
|
+
total_ms: number;
|
|
375
|
+
/** the `{#each}` that renders it */
|
|
376
|
+
each: {
|
|
377
|
+
path: string;
|
|
378
|
+
file: string;
|
|
379
|
+
line: number;
|
|
380
|
+
code: string;
|
|
381
|
+
context?: PatternSite["context"];
|
|
382
|
+
};
|
|
383
|
+
/** the page-data key the loop walks, and the load line that makes it */
|
|
384
|
+
key?: string;
|
|
385
|
+
made_at?: {
|
|
386
|
+
path: string;
|
|
387
|
+
file: string;
|
|
388
|
+
line: number;
|
|
389
|
+
code: string;
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* A COMPONENT RENDERED ONCE PER ITEM: its render count (V8's count of one render) comes from an
|
|
394
|
+
* `{#each}` over a page-data key, and that key is made on one load line (source). The chain says
|
|
395
|
+
* where its time is decided: render fewer items (a page of them, a smaller slice), or make each
|
|
396
|
+
* one cheaper. The cost scales with the count, so no saving is claimed: it is the lever, not a fix.
|
|
397
|
+
*/
|
|
398
|
+
export declare function render_per_item_pattern(items: readonly PerItemRender[], renders: number): Pattern | undefined;
|
|
399
|
+
/**
|
|
400
|
+
* THE SAME DOCUMENT EVERY REQUEST: every profiled render returned the same bytes, and nothing it
|
|
401
|
+
* reads is the visitor's (no load takes cookies, locals or the raw request; no outbound call carried
|
|
402
|
+
* a cookie or an authorization header). The whole render can be skipped: a CDN keeps the document
|
|
403
|
+
* (`Cache-Control: s-maxage`, keyed by its URL), or ogygia's postrender stores it. Saving: the
|
|
404
|
+
* render itself.
|
|
405
|
+
*/
|
|
406
|
+
export declare function same_document_pattern(input: {
|
|
407
|
+
file: string;
|
|
408
|
+
render_ms: number;
|
|
409
|
+
bytes: number;
|
|
410
|
+
code?: string;
|
|
411
|
+
/** what the response says that no shared cache accepts: a Set-Cookie, Cache-Control private / no-store */
|
|
412
|
+
blocked?: {
|
|
413
|
+
cookie?: boolean;
|
|
414
|
+
cache_control?: string;
|
|
415
|
+
};
|
|
416
|
+
}): Pattern;
|
|
417
|
+
/**
|
|
418
|
+
* THE SAME PAGE BUT FOR A FEW PARTS: the renders' documents differ only in a few small groups (an
|
|
419
|
+
* island's props, an id stamped per render, numbered comment markers) and nothing read is the
|
|
420
|
+
* visitor's. Those parts are all that stands between the page and a cached copy: make them stop
|
|
421
|
+
* changing (an id derived from the data, not a counter or a random; a live value fetched in the
|
|
422
|
+
* browser or in a deferred region) and the whole render comes off.
|
|
423
|
+
*/
|
|
424
|
+
export declare function almost_same_document_pattern(input: {
|
|
425
|
+
file: string;
|
|
426
|
+
render_ms: number;
|
|
427
|
+
diff: DocDiff;
|
|
428
|
+
code?: string;
|
|
429
|
+
}): Pattern;
|
|
430
|
+
export interface LateIslandWait {
|
|
431
|
+
/** the wait (`GET api/reviews`), one render: its ms and the part nothing else was in flight */
|
|
432
|
+
call: string;
|
|
433
|
+
ms: number;
|
|
434
|
+
alone: number;
|
|
435
|
+
/** the load line that made it */
|
|
436
|
+
at: {
|
|
437
|
+
path: string;
|
|
438
|
+
file: string;
|
|
439
|
+
line: number;
|
|
440
|
+
code: string;
|
|
441
|
+
};
|
|
442
|
+
/** the key it fills, and the late island that alone uses it (where) */
|
|
443
|
+
key: string;
|
|
444
|
+
island: string;
|
|
445
|
+
wake: string;
|
|
446
|
+
use: {
|
|
447
|
+
path: string;
|
|
448
|
+
file: string;
|
|
449
|
+
line: number;
|
|
450
|
+
code: string;
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* THE PAGE WAITS FOR A LATE ISLAND'S DATA: a call whose every key is used only as props of an island
|
|
455
|
+
* that wakes late (`visible`, `idle`, `interaction`). Every request waits for it before the first
|
|
456
|
+
* byte, for markup the visitor may never scroll to. Deferred (`render: 'deferred'`), the island
|
|
457
|
+
* renders on the server when it wakes, with its own call: the page stops waiting. Saving: the
|
|
458
|
+
* stretch the call held the render alone.
|
|
459
|
+
*/
|
|
460
|
+
export declare function late_island_pattern(items: readonly LateIslandWait[]): Pattern | undefined;
|
|
461
|
+
export interface ColdCacheInput {
|
|
462
|
+
functions: readonly FrameStat[];
|
|
463
|
+
/** V8's call counts from the coverage render: `<name>\0<script url>` → calls */
|
|
464
|
+
call_counts: Readonly<Record<string, number>>;
|
|
465
|
+
source: SourceReader;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* THE CACHE THAT NEVER HITS: an app function with a memo shape — a lookup (`M.get(k)`,
|
|
469
|
+
* `M.has(k)`), an early `return` of the hit, and a store (`M.set(k, …)`) after the work — whose
|
|
470
|
+
* MISS PATH ran about as often as the function itself. Measured from V8's call counts, which
|
|
471
|
+
* survive inlining: a helper the miss path calls once (not in a loop), and nothing else calls,
|
|
472
|
+
* ran once per miss; its count against the memo's is the miss rate. (Block counts would say it
|
|
473
|
+
* directly, but V8 only instruments functions compiled after they are switched on.)
|
|
474
|
+
*/
|
|
475
|
+
export declare function find_cold_caches(input: ColdCacheInput): Pattern | undefined;
|
|
476
|
+
export { tokens };
|