diff --git a/isolate.go b/isolate.go index 6e7f9de65..1f9b1f01a 100644 --- a/isolate.go +++ b/isolate.go @@ -44,6 +44,14 @@ type HeapStatistics struct { NumberOfDetachedContexts uint64 } +type HeapSpaceStatistics struct { + SpaceName string + SpaceSize uint64 + SpaceUsedSize uint64 + SpaceAvailableSize uint64 + PhysicalSpaceSize uint64 +} + // NewIsolate creates a new V8 isolate. Only one thread may access // a given isolate at a time, but different threads may access // different isolates simultaneously. @@ -119,6 +127,23 @@ func (i *Isolate) CompileUnboundScript(source, origin string, opts CompileOption }, nil } +// Returns heap statistics segmented by V8 heap spaces. +func (i *Isolate) GetHeapSpaceStatistics() []HeapSpaceStatistics { + spaceStats := []HeapSpaceStatistics{} + heapSpaces := int(C.NumberOfHeapSpaces(i.ptr)) + for space := 0; space < heapSpaces; space++ { + stats := C.IsolateGetHeapSpaceStatistics(i.ptr, (C.size_t)(space)) + spaceStats = append(spaceStats, HeapSpaceStatistics{ + SpaceName: C.GoString(stats.space_name), + SpaceSize: uint64(stats.space_size), + SpaceUsedSize: uint64(stats.space_used_size), + SpaceAvailableSize: uint64(stats.space_available_size), + PhysicalSpaceSize: uint64(stats.physical_space_size), + }) + } + return spaceStats +} + // GetHeapStatistics returns heap statistics for an isolate. func (i *Isolate) GetHeapStatistics() HeapStatistics { hs := C.IsolationGetHeapStatistics(i.ptr) diff --git a/isolate_test.go b/isolate_test.go index a6cca8e53..dbe7ce938 100644 --- a/isolate_test.go +++ b/isolate_test.go @@ -296,3 +296,29 @@ func makeObject() interface{} { "b": "AAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBB", } } + +func TestIsolateGetHeapSpaceStatistics(t *testing.T) { + t.Parallel() + iso := v8.NewIsolate() + defer iso.Dispose() + printfn := v8.NewFunctionTemplate(iso, func(info *v8.FunctionCallbackInfo) *v8.Value { + fmt.Printf("%v", info.Args()) + return nil + }) + global := v8.NewObjectTemplate(iso) + global.Set("print", printfn) + ctx := v8.NewContext(iso, global) + ctx.RunScript("print('foo')", "print.js") + + heapSpaceStats := iso.GetHeapSpaceStatistics() + + for _, stats := range heapSpaceStats { + if stats.SpaceName == "new_space" && (stats.SpaceSize <= 0 || stats.SpaceUsedSize <= 0) { + t.Errorf("expected non-zero size for heap space, got %d size for %s", stats.SpaceSize, stats.SpaceName) + } + if stats.SpaceName == "old_space" && (stats.SpaceSize <= 0 || stats.SpaceUsedSize <= 0) { + t.Errorf("expected non-zero size for heap space, got %d size for %s", stats.SpaceSize, stats.SpaceName) + } + } + +} diff --git a/v8go.cc b/v8go.cc index 86cdc8742..af1dc7ea6 100644 --- a/v8go.cc +++ b/v8go.cc @@ -193,6 +193,24 @@ int IsolateIsExecutionTerminating(IsolatePtr iso) { return iso->IsExecutionTerminating(); } +/********** Heap Statistics **********/ + +size_t NumberOfHeapSpaces(IsolatePtr iso) { + return iso->NumberOfHeapSpaces(); +} + +IsolateHeapSpaceStatistics IsolateGetHeapSpaceStatistics(IsolatePtr iso, + size_t index) { + if (iso == nullptr) { + return IsolateHeapSpaceStatistics{0}; + } + v8::HeapSpaceStatistics hs; + iso->GetHeapSpaceStatistics(&hs, index); + return IsolateHeapSpaceStatistics{ + hs.space_name(), hs.space_size(), hs.space_used_size(), + hs.space_available_size(), hs.physical_space_size()}; +} + IsolateHStatistics IsolationGetHeapStatistics(IsolatePtr iso) { if (iso == nullptr) { return IsolateHStatistics{0}; diff --git a/v8go.h b/v8go.h index b20daca4d..4d4d1a192 100644 --- a/v8go.h +++ b/v8go.h @@ -129,6 +129,14 @@ typedef struct { size_t number_of_detached_contexts; } IsolateHStatistics; +typedef struct { + const char* space_name; + size_t space_size; + size_t space_used_size; + size_t space_available_size; + size_t physical_space_size; +} IsolateHeapSpaceStatistics; + typedef struct { const uint64_t* word_array; int word_count; @@ -142,6 +150,9 @@ extern void IsolateDispose(IsolatePtr ptr); extern void IsolateTerminateExecution(IsolatePtr ptr); extern int IsolateIsExecutionTerminating(IsolatePtr ptr); extern IsolateHStatistics IsolationGetHeapStatistics(IsolatePtr ptr); +extern size_t NumberOfHeapSpaces(IsolatePtr ptr); +extern IsolateHeapSpaceStatistics IsolateGetHeapSpaceStatistics(IsolatePtr ptr, + size_t index); extern ValuePtr IsolateThrowException(IsolatePtr iso, ValuePtr value);