Add analytics tracking for CPU profiling and heap snapshots (#25053)

## Summary

- Add `cpu_profile` and `heap_snapshot` counters to `Analytics.Features`
- Export `heap_snapshot` to C++ as `Bun__Feature__heap_snapshot`
- Increment `cpu_profile` when `--cpu-prof` flag is used
- Increment `heap_snapshot` in all heap snapshot creation locations:
  - `Bun.generateHeapSnapshot()`
  - `bun:jsc` `generateHeapSnapshotForDebugging()`
  - `console.takeHeapSnapshot()`
  - Internal `JSC__JSGlobalObject__generateHeapSnapshot()`

## Test plan

- [x] Build succeeds
- [x] Heap snapshot generation works
- [x] CPU profiling works with `--cpu-prof`
- [x] Existing tests pass: `test/js/bun/util/v8-heap-snapshot.test.ts`
- [x] Existing tests pass: `test/cli/run/cpu-prof.test.ts`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
robobun
2025-11-26 00:02:43 -08:00
committed by GitHub
parent d50c5a385f
commit 85e0a723f3
5 changed files with 17 additions and 0 deletions

View File

@@ -89,10 +89,13 @@ pub const Features = struct {
pub var yarn_migration: usize = 0;
pub var pnpm_migration: usize = 0;
pub var yaml_parse: usize = 0;
pub var cpu_profile: usize = 0;
pub var heap_snapshot: usize = 0;
comptime {
@export(&napi_module_register, .{ .name = "Bun__napi_module_register_count" });
@export(&process_dlopen, .{ .name = "Bun__process_dlopen_count" });
@export(&heap_snapshot, .{ .name = "Bun__Feature__heap_snapshot" });
}
pub fn formatter() Formatter {

View File

@@ -280,6 +280,7 @@ pub const Run = struct {
.dir = cpu_prof_opts.dir,
};
CPUProfiler.startCPUProfiler(vm.jsc_vm);
bun.analytics.Features.cpu_profile += 1;
}
this.addConditionalGlobals();

View File

@@ -48,6 +48,8 @@
#include <netdb.h>
#endif
extern "C" size_t Bun__Feature__heap_snapshot;
BUN_DECLARE_HOST_FUNCTION(Bun__DNS__lookup);
BUN_DECLARE_HOST_FUNCTION(Bun__DNS__resolve);
BUN_DECLARE_HOST_FUNCTION(Bun__DNS__resolveSrv);
@@ -598,6 +600,8 @@ JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshot, (JSC::JSGlobalObject * gl
auto& heapProfiler = *vm.heapProfiler();
heapProfiler.clearSnapshots();
Bun__Feature__heap_snapshot += 1;
JSValue arg0 = callFrame->argument(0);
auto throwScope = DECLARE_THROW_SCOPE(vm);
bool useV8 = false;

View File

@@ -152,6 +152,8 @@
#include <JavaScriptCore/IntegrityInlines.h>
#endif
extern "C" size_t Bun__Feature__heap_snapshot;
#if OS(DARWIN)
#if ASSERT_ENABLED
#if !__has_feature(address_sanitizer)
@@ -3659,6 +3661,8 @@ JSC::EncodedJSValue JSC__JSGlobalObject__generateHeapSnapshot(JSC::JSGlobalObjec
// JSC::DeferTermination deferScope(vm);
auto scope = DECLARE_THROW_SCOPE(vm);
Bun__Feature__heap_snapshot += 1;
JSC::HeapSnapshotBuilder snapshotBuilder(vm.ensureHeapProfiler());
snapshotBuilder.buildSnapshot();

View File

@@ -58,6 +58,8 @@
#endif
#endif
extern "C" size_t Bun__Feature__heap_snapshot;
using namespace JSC;
using namespace WTF;
using namespace WebCore;
@@ -732,6 +734,9 @@ JSC_DEFINE_HOST_FUNCTION(functionGenerateHeapSnapshotForDebugging,
JSLockHolder lock(vm);
DeferTermination deferScope(vm);
auto scope = DECLARE_THROW_SCOPE(vm);
Bun__Feature__heap_snapshot += 1;
String jsonString;
{
DeferGCForAWhile deferGC(vm); // Prevent concurrent GC from interfering with