-
Notifications
You must be signed in to change notification settings - Fork 27k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'canary' into sam/fix-fetch-cache-tags
- Loading branch information
Showing
36 changed files
with
792 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Debug Memory Usage | ||
|
||
This directory contains a number of utilities to help in debugging | ||
memory usage. | ||
|
||
When enabled, code in this directory will: | ||
|
||
- Periodically print out memory usage statistics | ||
- Print a report with a summary of memory usage and suggestions for how to | ||
improve. | ||
- Generate heap snapshots automatically when too much memory is being consumed | ||
- Monitor garbage collection events for long running GCs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { PerformanceObserver } from 'perf_hooks' | ||
import { warn } from '../../build/output/log' | ||
import { bold } from '../picocolors' | ||
|
||
const LONG_RUNNING_GC_THRESHOLD_MS = 15 | ||
|
||
const gcEvents: PerformanceEntry[] = [] | ||
const obs = new PerformanceObserver((list) => { | ||
const entry = list.getEntries()[0] | ||
gcEvents.push(entry) | ||
|
||
if (entry.duration > LONG_RUNNING_GC_THRESHOLD_MS) { | ||
warn(bold(`Long running GC detected: ${entry.duration.toFixed(2)}ms`)) | ||
} | ||
}) | ||
|
||
/** | ||
* Starts recording garbage collection events in the process and warn on long | ||
* running GCs. To disable, call `stopObservingGc`. | ||
*/ | ||
export function startObservingGc() { | ||
obs.observe({ entryTypes: ['gc'] }) | ||
} | ||
|
||
export function stopObservingGc() { | ||
obs.disconnect() | ||
} | ||
|
||
/** | ||
* Returns all recorded garbage collection events. This function will only | ||
* return information from when `startObservingGc` was enabled and before | ||
* `stopObservingGc` was called. | ||
*/ | ||
export function getGcEvents() { | ||
return gcEvents | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { info } from '../../build/output/log' | ||
import { bold } from '../picocolors' | ||
import { getGcEvents, stopObservingGc } from './gc-observer' | ||
import { getAllMemoryUsageSpans, stopPeriodicMemoryUsageTracing } from './trace' | ||
|
||
export function disableMemoryDebuggingMode(): void { | ||
stopPeriodicMemoryUsageTracing() | ||
stopObservingGc() | ||
|
||
info(bold('Memory usage report:')) | ||
|
||
const gcEvents = getGcEvents() | ||
const totalTimeInGcMs = gcEvents.reduce( | ||
(acc, event) => acc + event.duration, | ||
0 | ||
) | ||
info(` - Total time spent in GC: ${totalTimeInGcMs.toFixed(2)}ms`) | ||
|
||
const allMemoryUsage = getAllMemoryUsageSpans() | ||
const peakHeapUsage = Math.max( | ||
...allMemoryUsage.map((usage) => usage['memory.heapUsed']) | ||
) | ||
const peakRssUsage = Math.max( | ||
...allMemoryUsage.map((usage) => usage['memory.rss']) | ||
) | ||
info(` - Peak heap usage: ${(peakHeapUsage / 1024 / 1024).toFixed(2)} MB`) | ||
info(` - Peak RSS usage: ${(peakRssUsage / 1024 / 1024).toFixed(2)} MB`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import v8 from 'v8' | ||
import { info, warn } from '../../build/output/log' | ||
import { italic } from '../picocolors' | ||
import { startObservingGc } from './gc-observer' | ||
import { startPeriodicMemoryUsageTracing } from './trace' | ||
|
||
export function enableMemoryDebuggingMode(): void { | ||
// This will generate a heap snapshot when the program is close to the | ||
// memory limit. It does not give any warning to the user though which | ||
// can be jarring. If memory is large, this may take a long time. | ||
if ('setHeapSnapshotNearHeapLimit' in v8) { | ||
// @ts-expect-error - this method exists since Node 16. | ||
v8.setHeapSnapshotNearHeapLimit(1) | ||
} | ||
|
||
// This flag will kill the process when it starts to GC thrash when it's | ||
// close to the memory limit rather than continuing to try to collect | ||
// memory ineffectively. | ||
v8.setFlagsFromString('--detect-ineffective-gcs-near-heap-limit') | ||
|
||
// This allows users to generate a heap snapshot on demand just by sending | ||
// a signal to the process. | ||
process.on('SIGUSR2', () => { | ||
warn( | ||
`Received SIGUSR2 signal. Generating heap snapshot. ${italic( | ||
'Note: this will take some time.' | ||
)}` | ||
) | ||
v8.writeHeapSnapshot() | ||
}) | ||
|
||
startObservingGc() | ||
startPeriodicMemoryUsageTracing() | ||
|
||
warn( | ||
`Memory debugging mode is enabled. ${italic( | ||
'Note: This will affect performance.' | ||
)}` | ||
) | ||
info( | ||
' - Heap snapshots will be automatically generated when the process reaches more than 70% of the memory limit and again when the process is just about to run out of memory.' | ||
) | ||
info( | ||
` - To manually generate a heap snapshot, send the process a SIGUSR2 signal: \`kill -SIGUSR2 ${process.pid}\`` | ||
) | ||
info( | ||
' - Heap snapshots when there is high memory will take a very long time to complete and may be difficult to analyze in tools.' | ||
) | ||
info( | ||
' - See https://nextjs.org/docs/app/building-your-application/optimizing/memory-usage for more information.' | ||
) | ||
} |
Oops, something went wrong.