diff --git a/array.go b/array.go index feb74fd0..dffc6922 100644 --- a/array.go +++ b/array.go @@ -618,7 +618,7 @@ func (a *arrayObject) MemUsage(ctx *MemUsageContext) (memUsage uint64, newMemUsa // slice overhead from a.values if a.values != nil { - memUsage += 0 + memUsage += SizeEmptySlice newMemUsage += SizeEmptySlice } diff --git a/array_sparse_test.go b/array_sparse_test.go index 7192a02d..fe663d4a 100644 --- a/array_sparse_test.go +++ b/array_sparse_test.go @@ -264,6 +264,7 @@ func TestSparseArrayExportToSlice(t *testing.T) { } func TestSparseArrayObjectMemUsage(t *testing.T) { + vm := New() tests := []struct { name string mu *MemUsageContext @@ -274,24 +275,24 @@ func TestSparseArrayObjectMemUsage(t *testing.T) { }{ { name: "mem below threshold", - mu: NewMemUsageContext(New(), 88, 5000, 50, 50, TestNativeMemUsageChecker{}), + mu: NewMemUsageContext(vm, 88, 5000, 50, 50, TestNativeMemUsageChecker{}), sao: &sparseArrayObject{ items: []sparseArrayItem{ { idx: 1, - value: New()._newString(newStringValue("key"), nil), + value: vm.ToValue("key"), }, }, }, - // array overhead + index size + stringObject + sparseArray baseObject - expected: SizeEmptyStruct + SizeInt32 + 25 + SizeEmptyStruct, - // array overhead + index size + stringObject + sparseArray baseObject - newExpected: SizeEmptyStruct + SizeInt32 + 57 + SizeEmptyStruct, + // array overhead + index size + (string len + overhead) + sparseArray baseObject + expected: SizeEmptyStruct + SizeInt32 + (3 + SizeString) + SizeEmptyStruct, + // array overhead + index size + (string len + overhead) + sparseArray baseObject + newExpected: SizeEmptyStruct + SizeInt32 + (3 + SizeString) + SizeEmptyStruct, errExpected: nil, }, { name: "mem is SizeEmptyStruct for nil sparse array", - mu: NewMemUsageContext(New(), 88, 5000, 50, 50, TestNativeMemUsageChecker{}), + mu: NewMemUsageContext(vm, 88, 5000, 50, 50, TestNativeMemUsageChecker{}), sao: nil, expected: SizeEmptyStruct, newExpected: SizeEmptyStruct, @@ -299,39 +300,39 @@ func TestSparseArrayObjectMemUsage(t *testing.T) { }, { name: "mem way above threshold returns first crossing of threshold", - mu: NewMemUsageContext(New(), 88, 100, 50, 50, TestNativeMemUsageChecker{}), + mu: NewMemUsageContext(vm, 88, 100, 50, 50, TestNativeMemUsageChecker{}), sao: &sparseArrayObject{ items: []sparseArrayItem{ { idx: 1, - value: New()._newString(newStringValue("key0"), nil), + value: vm.ToValue("key0"), }, { idx: 2, - value: New()._newString(newStringValue("key1"), nil), + value: vm.ToValue("key1"), }, { idx: 3, - value: New()._newString(newStringValue("key2"), nil), + value: vm.ToValue("key2"), }, { idx: 4, - value: New()._newString(newStringValue("key3"), nil), + value: vm.ToValue("key3"), }, { idx: 5, - value: New()._newString(newStringValue("key4"), nil), + value: vm.ToValue("key4"), }, { idx: 6, - value: New()._newString(newStringValue("key5"), nil), + value: vm.ToValue("key5"), }, }, }, - // array overhead + index size + stringObject (we reach the limit at 4) - expected: SizeEmptyStruct + (SizeInt32+26)*4, - // index size + stringObject (we reach the limit at 4) - newExpected: SizeEmptyStruct + (SizeInt32+58)*4, + // array overhead + index size + (string len + overhead) (we reach the limit at 4) + expected: SizeEmptyStruct + (SizeInt32+(4+SizeString))*4, + // array overhead + index size + (string len + overhead) (we reach the limit at 4) + newExpected: SizeEmptyStruct + (SizeInt32+(4+SizeString))*4, errExpected: nil, }, } diff --git a/array_test.go b/array_test.go index 095c6cc9..36a31f52 100644 --- a/array_test.go +++ b/array_test.go @@ -157,8 +157,8 @@ func TestArrayObjectMemUsage(t *testing.T) { name: "mem below threshold given empty slice of values", mu: NewMemUsageContext(vm, 88, 5000, 50, 50, TestNativeMemUsageChecker{}), ao: &arrayObject{values: []Value{}}, - // array overhead + array baseObject - expectedMem: SizeEmptyStruct + SizeEmptyStruct, + // array overhead + array baseObject + values slice overhead + expectedMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptySlice, // array overhead + array baseObject + values slice overhead expectedNewMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptySlice, errExpected: nil, @@ -168,24 +168,20 @@ func TestArrayObjectMemUsage(t *testing.T) { mu: NewMemUsageContext(vm, 88, 100, 50, 50, TestNativeMemUsageChecker{}), ao: &arrayObject{ values: []Value{ - vm._newString(newStringValue("key0"), nil), - vm._newString(newStringValue("key1"), nil), - vm._newString(newStringValue("key2"), nil), - vm._newString(newStringValue("key3"), nil), - vm._newString(newStringValue("key4"), nil), - vm._newString(newStringValue("key5"), nil), + vm.ToValue("key0"), + vm.ToValue("key1"), + vm.ToValue("key2"), + vm.ToValue("key3"), + vm.ToValue("key4"), + vm.ToValue("key5"), }, }, - // array overhead + array baseObject - expectedMem: SizeEmptyStruct + SizeEmptyStruct + - // (stringObject + baseObject + prop "length") * entries (at 4 we reach the limit) - (SizeEmptyStruct+SizeEmptyStruct+6)*4 + - // len("keyN") * entries (at 4 we reach the limit) - 4*4, + // array overhead + array baseObject + values slice overhead + expectedMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptySlice + + // len("keyN") with string overhead * entries (at 4 we reach the limit) + (4+SizeString)*4, // array overhead + array baseObject + values slice overhead expectedNewMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptySlice + - // (stringObject + baseObject + prop "length" with string overhead) * entries (at 4 we reach the limit) - (SizeEmptyStruct+SizeEmptyStruct+(6+SizeString))*4 + // len("keyN") with string overhead * entries (at 4 we reach the limit) (4+SizeString)*4, errExpected: nil, diff --git a/builtin_map_test.go b/builtin_map_test.go index c68c87cb..e8b61bba 100644 --- a/builtin_map_test.go +++ b/builtin_map_test.go @@ -244,6 +244,7 @@ func BenchmarkMapDeleteJS(b *testing.B) { } func TestMapObjectMemUsage(t *testing.T) { + vm := New() tests := []struct { name string mu *MemUsageContext @@ -254,26 +255,26 @@ func TestMapObjectMemUsage(t *testing.T) { }{ { name: "mem below threshold", - mu: NewMemUsageContext(New(), 88, 5000, 50, 50, TestNativeMemUsageChecker{}), + mu: NewMemUsageContext(vm, 88, 5000, 50, 50, TestNativeMemUsageChecker{}), mo: &mapObject{ m: &orderedMap{ hashTable: map[uint64]*mapEntry{ 1: { - key: New()._newString(newStringValue("key"), nil), - value: New()._newString(newStringValue("value"), nil), + key: vm.ToValue("key"), + value: vm.ToValue("value"), }, }, }, }, - // baseObject + stringObject + len(key) + stringObject + len(key) - expectedMem: SizeEmptyStruct + 22 + 3 + 22 + 5, - // baseObject + stringObject + (len(key) + overhead) + stringObject + (len(key) + overhead) - expectedNewMem: SizeEmptyStruct + 38 + (3 + SizeString) + 38 + (5 + SizeString), + // baseObject + (len(key) + overhead) + (len(value) + overhead) + expectedMem: SizeEmptyStruct + (3 + SizeString) + (5 + SizeString), + // baseObject + (len(key) + overhead) + (len(value) + overhead) + expectedNewMem: SizeEmptyStruct + (3 + SizeString) + (5 + SizeString), errExpected: nil, }, { name: "mem is SizeEmptyStruct given a nil map object", - mu: NewMemUsageContext(New(), 88, 5000, 50, 50, TestNativeMemUsageChecker{}), + mu: NewMemUsageContext(vm, 88, 5000, 50, 50, TestNativeMemUsageChecker{}), mo: nil, expectedMem: SizeEmptyStruct, expectedNewMem: SizeEmptyStruct, @@ -281,41 +282,41 @@ func TestMapObjectMemUsage(t *testing.T) { }, { name: "mem way above threshold returns first crossing of threshold", - mu: NewMemUsageContext(New(), 88, 100, 50, 50, TestNativeMemUsageChecker{}), + mu: NewMemUsageContext(vm, 88, 100, 50, 50, TestNativeMemUsageChecker{}), mo: &mapObject{ m: &orderedMap{ hashTable: map[uint64]*mapEntry{ 1: { - key: New()._newString(newStringValue("key"), nil), - value: New()._newString(newStringValue("value"), nil), + key: vm.ToValue("key"), + value: vm.ToValue("value"), }, 2: { - key: New()._newString(newStringValue("key"), nil), - value: New()._newString(newStringValue("value"), nil), + key: vm.ToValue("key"), + value: vm.ToValue("value"), }, 3: { - key: New()._newString(newStringValue("key"), nil), - value: New()._newString(newStringValue("value"), nil), + key: vm.ToValue("key"), + value: vm.ToValue("value"), }, 4: { - key: New()._newString(newStringValue("key"), nil), - value: New()._newString(newStringValue("value"), nil), + key: vm.ToValue("key"), + value: vm.ToValue("value"), }, }, }, }, // baseObject expectedMem: SizeEmptyStruct + - // stringObject + len(key) (we reach the limit after 2) - (22+3)*2 + - // stringObject + len(value) (we reach the limit after 2) - (22+5)*2, + // len(key) + overhead (we reach the limit after 3) + (3+SizeString)*3 + + // len(value) + overhead (we reach the limit after 3) + (5+SizeString)*3, // baseObject expectedNewMem: SizeEmptyStruct + - // stringObject + len(key) + overhead (we reach the limit after 2) - (38+(3+SizeString))*2 + - // stringObject + len(value) + overhead (we reach the limit after 2) - (38+(5+SizeString))*2, + // len(key) + overhead (we reach the limit after 3) + (3+SizeString)*3 + + // len(value) + overhead (we reach the limit after 3) + (5+SizeString)*3, errExpected: nil, }, } diff --git a/date_test.go b/date_test.go index a19cc838..53bf6f2a 100644 --- a/date_test.go +++ b/date_test.go @@ -338,8 +338,8 @@ func TestDateMemUsage(t *testing.T) { }, // msec value expectedMem: SizeNumber + - // baseObject overhead + len("test") + value - SizeEmptyStruct + 4 + SizeInt, + // baseObject overhead + len("test") with string overhead + value + SizeEmptyStruct + (4 + SizeString) + SizeInt, // msec value expectedNewMem: SizeNumber + // baseObject overhead + len("test") with string overhead + value diff --git a/memory_test.go b/memory_test.go index d240af15..4e4829da 100644 --- a/memory_test.go +++ b/memory_test.go @@ -85,7 +85,7 @@ func TestMemCheck(t *testing.T) { checkMem() x.push("12345") checkMem()`, - expectedSizeDiff: 5, + expectedSizeDiff: 5 + SizeString, expectedNewSizeDiff: 5 + SizeString, }, { @@ -95,7 +95,7 @@ func TestMemCheck(t *testing.T) { checkMem() x.push("\u2318") checkMem()`, - expectedSizeDiff: 3, // single char with 3-byte width + expectedSizeDiff: 3 + SizeString, // single char with 3-byte width expectedNewSizeDiff: 3 + SizeString, }, { @@ -106,9 +106,9 @@ func TestMemCheck(t *testing.T) { y.push({"a":10, "b":"1234", "c":{}}) checkMem()`, expectedSizeDiff: SizeEmptyStruct + SizeEmptyStruct + // outer object + reference to its prototype - 1 + SizeNumber + // "a" and number 10 - 1 + 4 + // "b" and string "1234" - 1 + SizeEmptyStruct + SizeEmptyStruct + // "c" (object + prototype reference) + (1 + SizeString) + SizeNumber + // "a" and number 10 + (1 + SizeString) + (4 + SizeString) + // "b" and string "1234" + (1 + SizeString) + SizeEmptyStruct + SizeEmptyStruct + // "c" (object + prototype reference) SizeEmptyStruct, // stack difference from popping null(8) and then adding outer obj(8) + "c" obj (8) expectedNewSizeDiff: SizeEmptyStruct + SizeEmptyStruct + // outer object + reference to its prototype (1 + SizeString) + SizeNumber + // "a" and number 10 @@ -139,7 +139,9 @@ func TestMemCheck(t *testing.T) { })();`, // over expectedSizeDiff: emptyFunctionScopeOverhead + functionStackOverhead + // anonymous function on stack - SizeEmptyStruct, // undefined return on stack + SizeString + // empty string for anon function name + SizeString + SizeString + // overhead of "name" and "length" props on function object + SizeEmptyStruct, // undefined return on stack, expectedNewSizeDiff: emptyFunctionScopeOverhead + functionStackOverhead + // anonymous function on stack SizeString + // empty string for anon function name @@ -174,6 +176,8 @@ func TestMemCheck(t *testing.T) { })(); })();`, expectedSizeDiff: (6 * functionStackOverhead) + // anonymous functions on stack + (6 * SizeString) + // empty string for anon function name + (6 * (SizeString + SizeString)) + // overhead of "name" and "length" props on function object (6 * SizeEmptyStruct) + // undefined return value for each function on stack (6 * emptyFunctionScopeOverhead), expectedNewSizeDiff: (6 * functionStackOverhead) + // anonymous functions on stack @@ -191,10 +195,12 @@ func TestMemCheck(t *testing.T) { })();`, // function overhead plus the number value of the "zzzx" property and its string name expectedSizeDiff: emptyFunctionScopeOverhead + SizeNumber + functionStackOverhead + + SizeString + // empty string for anon function name + SizeString + SizeString + // overhead of "name" and "length" props on function object SizeEmptyStruct + // undefined return value on stack - SizeNumber, // number 10 on stack - expectedNewSizeDiff: // function overhead plus the number value of the "zzzx" property and its string name - emptyFunctionScopeOverhead + SizeNumber + functionStackOverhead + + SizeNumber, // number 10 on stack, + // function overhead plus the number value of the "zzzx" property and its string name + expectedNewSizeDiff: emptyFunctionScopeOverhead + SizeNumber + functionStackOverhead + SizeString + // empty string for anon function name SizeString + SizeString + // overhead of "name" and "length" props on function object SizeEmptyStruct + // undefined return value on stack @@ -211,8 +217,8 @@ func TestMemCheck(t *testing.T) { zzza.y = zzzb zzzb.x = zzza checkMem()`, - expectedSizeDiff: 1 + SizeEmptyStruct + // "x" property name + references to object - 1 + SizeEmptyStruct, // "y" property names + references to object + expectedSizeDiff: (1 + SizeString) + SizeEmptyStruct + // "x" property name + references to object + (1 + SizeString) + SizeEmptyStruct, // "y" property names + references to object, expectedNewSizeDiff: (1 + SizeString) + SizeEmptyStruct + // "x" property name + references to object (1 + SizeString) + SizeEmptyStruct, // "y" property names + references to object, }, @@ -223,7 +229,7 @@ func TestMemCheck(t *testing.T) { checkMem() x[10] = "abc"; checkMem()`, - expectedSizeDiff: 2, // 3 -> "abc" added to global memory | -1 difference on stack between "abc" and "abcd" + expectedSizeDiff: 2 + SizeString, // 3 -> "abc" added to global memory | -1 difference on stack between "abc" and "abcd" expectedNewSizeDiff: 2 + SizeString, // 3 -> "abc" added to global memory | -1 difference on stack between "abc" and "abcd", }, { @@ -234,9 +240,9 @@ func TestMemCheck(t *testing.T) { x[5001] = "abc"; checkMem()`, expectedSizeDiff: SizeInt32 + - 2, // 3 -> "abc" added to global memory | -1 difference on stack between "abc" and "abcd" + 2 + SizeString, // 3 -> "abc" added to global memory | -1 difference on stack between "abc" and "abcd" expectedNewSizeDiff: SizeInt32 + - 2 + SizeString, // 3 -> "abc" added to global memory | -1 difference on stack between "abc" and "abcd", + 2 + SizeString, // 3 -> "abc" added to global memory | -1 difference on stack between "abc" and "abcd" }, { desc: "array with non-numeric keys", @@ -247,9 +253,9 @@ func TestMemCheck(t *testing.T) { x[1] = 3; checkMem() `, - expectedSizeDiff: 1 + // len("a") - 3 + // len("abc") - SizeNumber, // number 3 + expectedSizeDiff: 1 + SizeString + // len("a") + 3 + SizeString + // len("abc") + SizeNumber, // number 3, expectedNewSizeDiff: 1 + SizeString + // len("a") 3 + SizeString + // len("abc") SizeNumber, // number 3, @@ -263,7 +269,7 @@ func TestMemCheck(t *testing.T) { y = x; checkMem()`, // len("y") + reference to array - expectedSizeDiff: 1 + SizeEmptyStruct, + expectedSizeDiff: (1 + SizeString) + SizeEmptyStruct, // len("y") + reference to array expectedNewSizeDiff: (1 + SizeString) + SizeEmptyStruct, }, @@ -276,7 +282,7 @@ func TestMemCheck(t *testing.T) { y = x; // len("y") + reference to array checkMem()`, - expectedSizeDiff: 1 + SizeEmptyStruct, + expectedSizeDiff: (1 + SizeString) + SizeEmptyStruct, expectedNewSizeDiff: (1 + SizeString) + SizeEmptyStruct, }, { @@ -288,7 +294,7 @@ func TestMemCheck(t *testing.T) { checkMem() `, // len("d2") + size of msec + reference to visited base object + base object prototype reference - expectedSizeDiff: 2 + SizeNumber + SizeEmptyStruct + SizeEmptyStruct, + expectedSizeDiff: (2 + SizeString) + SizeNumber + SizeEmptyStruct + SizeEmptyStruct, // len("d2") + size of msec + reference to visited base object + base object prototype reference expectedNewSizeDiff: (2 + SizeString) + SizeNumber + SizeEmptyStruct + SizeEmptyStruct, }, @@ -300,7 +306,7 @@ func TestMemCheck(t *testing.T) { checkMem() `, // len("o") + object's starting size + reference to prototype - expectedSizeDiff: 1 + SizeEmptyStruct + SizeNumber, + expectedSizeDiff: (1 + SizeString) + SizeEmptyStruct + SizeNumber, // len("o") + object's starting size + reference to prototype expectedNewSizeDiff: (1 + SizeString) + SizeEmptyStruct + SizeNumber, }, @@ -311,15 +317,15 @@ func TestMemCheck(t *testing.T) { checkMem(); m.set("abc", {"a":10, "b":"1234"}); checkMem();`, - expectedSizeDiff: 3 + // "abc" + expectedSizeDiff: 3 + SizeString + // "abc" SizeEmptyStruct + SizeEmptyStruct + // outer object + reference to its prototype - 1 + SizeNumber + // "a" and number - 1 + 4 + // "b" and "1234" string + (1 + SizeString) + SizeNumber + // "a" and number + (1 + SizeString) + (4 + SizeString) + // "b" and "1234" string // stack difference in going from // [..other, first, 1] // to // [..other, abc, [object Object], 1234] - 2, + 18, expectedNewSizeDiff: 3 + SizeString + // "abc" SizeEmptyStruct + SizeEmptyStruct + // outer object + reference to its prototype (1 + SizeString) + SizeNumber + // "a" and number @@ -348,11 +354,11 @@ func TestMemCheck(t *testing.T) { proxy2 = new Proxy(target, handler); checkMem(); `, - expectedSizeDiff: 6 + // "proxy2" + expectedSizeDiff: (6 + SizeString) + // "proxy2" SizeEmptyStruct + // proxy overhead SizeEmptyStruct + SizeEmptyStruct + // base object + prototype SizeEmptyStruct + // target object reference - SizeEmptyStruct, // handler object reference + SizeEmptyStruct, // handler object reference, expectedNewSizeDiff: (6 + SizeString) + // "proxy2" SizeEmptyStruct + // proxy overhead SizeEmptyStruct + SizeEmptyStruct + // base object + prototype @@ -367,10 +373,10 @@ func TestMemCheck(t *testing.T) { str2 = new String("hello") checkMem(); `, - expectedSizeDiff: 4 + // "str2" - 5 + // "hello" + expectedSizeDiff: (4 + SizeString) + // "str2" + (5 + SizeString) + // "hello" SizeEmptyStruct + SizeEmptyStruct + // base object + prototype - 6 + SizeNumber, // "length" + number + (6 + SizeString) + SizeNumber, // "length" + number, expectedNewSizeDiff: (4 + SizeString) + // "str2" (5 + SizeString) + // "hello" SizeEmptyStruct + SizeEmptyStruct + // base object + prototype @@ -383,12 +389,12 @@ func TestMemCheck(t *testing.T) { ta2 = new Uint8Array([1, 2, 3, 4]); checkMem(); `, - expectedSizeDiff: 3 + // "ta2" + expectedSizeDiff: (3 + SizeString) + // "ta2" SizeEmptyStruct + // typed array overhead SizeEmptyStruct + SizeEmptyStruct + // base object + prototype 4 + SizeEmptyStruct + SizeEmptyStruct + // array buffer data + base object + prototype SizeEmptyStruct + // default constructor - SizeInt, // last element (4) on stack + SizeInt, // last element (4) on stack, expectedNewSizeDiff: (3 + SizeString) + // "ta2" SizeEmptyStruct + // typed array overhead SizeEmptyStruct + SizeEmptyStruct + // base object + prototype @@ -403,9 +409,9 @@ func TestMemCheck(t *testing.T) { checkMem(); buffer2 = new ArrayBuffer(16); checkMem();`, - expectedSizeDiff: 7 + // "buffer2" + expectedSizeDiff: (7 + SizeString) + // "buffer2" 16 + // data size - SizeEmptyStruct + SizeEmptyStruct, // base object + prototype + SizeEmptyStruct + SizeEmptyStruct, // base object + prototype, expectedNewSizeDiff: (7 + SizeString) + // "buffer2" 16 + // data size SizeEmptyStruct + SizeEmptyStruct, // base object + prototype, @@ -419,10 +425,10 @@ func TestMemCheck(t *testing.T) { checkMem(); view2 = new DataView(buffer2, 0); checkMem();`, - expectedSizeDiff: 5 + // "view2" + expectedSizeDiff: (5 + SizeString) + // "view2" SizeEmptyStruct + // DataView overhead SizeEmptyStruct + SizeEmptyStruct + // base object + prototype - SizeEmptyStruct, // array buffer reference + SizeEmptyStruct, // array buffer reference, expectedNewSizeDiff: (5 + SizeString) + // "view2" SizeEmptyStruct + // DataView overhead SizeEmptyStruct + SizeEmptyStruct + // base object + prototype @@ -435,9 +441,9 @@ func TestMemCheck(t *testing.T) { checkMem(); num2 = new Number("2") checkMem();`, - expectedSizeDiff: 4 + // "num2" + expectedSizeDiff: (4 + SizeString) + // "num2" SizeNumber + - SizeEmptyStruct + SizeEmptyStruct, // base object + prototype + SizeEmptyStruct + SizeEmptyStruct, // base object + prototype, expectedNewSizeDiff: (4 + SizeString) + // "num2" SizeNumber + SizeEmptyStruct + SizeEmptyStruct, // base object + prototype, @@ -452,9 +458,9 @@ func TestMemCheck(t *testing.T) { checkMem(); } `, - expectedSizeDiff: 7 + 3 + // Error "message" field + len("abc") - 4 + 5 + // Error "name" field + len("Error") - SizeEmptyStruct + SizeEmptyStruct, // base object + prototype + expectedSizeDiff: (7 + SizeString) + (3 + SizeString) + // Error "message" field + len("abc") + (4 + SizeString) + (5 + SizeString) + // Error "name" field + len("Error") + SizeEmptyStruct + SizeEmptyStruct, // base object + prototype, expectedNewSizeDiff: (7 + SizeString) + (3 + SizeString) + // Error "message" field + len("abc") (4 + SizeString) + (5 + SizeString) + // Error "name" field + len("Error") SizeEmptyStruct + SizeEmptyStruct, // base object + prototype, @@ -465,7 +471,7 @@ func TestMemCheck(t *testing.T) { nv = new MyNativeVal() checkMem();`, expectedSizeDiff: testNativeValueMemUsage + - 2, // "nv" + (2 + SizeString), // "nv", expectedNewSizeDiff: testNativeValueMemUsage + (2 + SizeString), // "nv", }, @@ -653,8 +659,7 @@ func TestMemArraysWithLenThreshold(t *testing.T) { }; checkMem()`, threshold: 200, - // baseObject is 38 + 3*SizeNumber = 62, so at 60 we expect to exceed the limit - memLimit: 60, + memLimit: 100, // Array overhead, size of property values, only 3 values before we hit the mem limit expectedSizeDiff: SizeEmptyStruct + (3 * SizeNumber), expectedNewSizeDiff: SizeEmptyStruct + (3 * SizeNumber), @@ -780,7 +785,7 @@ func TestMemObjectsWithPropsLenThreshold(t *testing.T) { threshold: 100, memLimit: memUsageLimit, // object overhead + len("i0") + value i - expectedSizeDiff: SizeEmptyStruct + 10*2 + 10*SizeNumber, + expectedSizeDiff: SizeEmptyStruct + 10*(2+SizeString) + 10*SizeNumber, // object overhead + len("i0") + value i expectedNewSizeDiff: SizeEmptyStruct + 10*(2+SizeString) + 10*SizeNumber, }, @@ -796,7 +801,7 @@ func TestMemObjectsWithPropsLenThreshold(t *testing.T) { threshold: 100, memLimit: 40, // object overhead + len("i0") + value i - expectedSizeDiff: SizeEmptyStruct + 10*2 + 10*SizeNumber, + expectedSizeDiff: SizeEmptyStruct + 10*(2+SizeString) + 10*SizeNumber, // object overhead + len("i0") + value i expectedNewSizeDiff: SizeEmptyStruct + 10*(2+SizeString) + 10*SizeNumber, }, @@ -812,7 +817,7 @@ func TestMemObjectsWithPropsLenThreshold(t *testing.T) { threshold: 75, memLimit: memUsageLimit, // object overhead + len("i100") + value i - expectedSizeDiff: SizeEmptyStruct + 100*4 + 100*SizeNumber, + expectedSizeDiff: SizeEmptyStruct + 100*(4+SizeString) + 100*SizeNumber, // object overhead + len("i100") + value i expectedNewSizeDiff: SizeEmptyStruct + 100*(4+SizeString) + 100*SizeNumber, }, @@ -828,11 +833,11 @@ func TestMemObjectsWithPropsLenThreshold(t *testing.T) { threshold: 200, memLimit: memUsageLimit, // object overhead + key len("i100") + value i for the items 100 to 149 - expectedSizeDiff: SizeEmptyStruct + 50*4 + 50*SizeNumber + + expectedSizeDiff: SizeEmptyStruct + 50*(4+SizeString) + 50*SizeNumber + // len("i150") + len("i150") for the items 150 to 199 - 50*4 + 50*4 + + 50*(4+SizeString) + 50*(4+SizeString) + // 150 number + len("i") in "i"+i expression - 3 + 1, + 3 + (1 + SizeString), // object overhead + key len("i100") + value i for the items 100 to 149 expectedNewSizeDiff: SizeEmptyStruct + 50*(4+SizeString) + 50*SizeNumber + // len("i150") + len("i150") for the items 150 to 199 diff --git a/object.go b/object.go index 4b172f13..e5f3428b 100644 --- a/object.go +++ b/object.go @@ -1941,7 +1941,7 @@ func (o *baseObject) estimateMemUsage(ctx *MemUsageContext) (estimate uint64, ne // memory usage across function executions for i := 0; i < totalProps; i += sampleSize { k := o.propNames[i] - memUsage += uint64(len(k)) + memUsage += uint64(len(k)) + SizeString newMemUsage += uint64(len(k)) + SizeString v := o.values[k] if v == nil { @@ -1982,7 +1982,7 @@ func (o *baseObject) MemUsage(ctx *MemUsageContext) (memUsage uint64, newMemUsag } else { for _, k := range o.propNames { v := o.values[k] - memUsage += uint64(len(k)) + memUsage += uint64(len(k)) + SizeString newMemUsage += uint64(len(k)) + SizeString if v == nil { diff --git a/object_dynamic_test.go b/object_dynamic_test.go index c83d2f56..d813ca17 100644 --- a/object_dynamic_test.go +++ b/object_dynamic_test.go @@ -457,7 +457,7 @@ func TestBaseDynamicObjectMemUsage(t *testing.T) { self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - expectedMem: SizeEmptyStruct + (4 + SizeInt), + expectedMem: SizeEmptyStruct + (4 + SizeString + SizeInt), expectedNewMem: SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, }, diff --git a/object_gomap.go b/object_gomap.go index b320d5df..4b7b7677 100644 --- a/object_gomap.go +++ b/object_gomap.go @@ -181,7 +181,7 @@ func (o *objectGoMapSimple) MemUsage(ctx *MemUsageContext) (uint64, uint64, erro return 0, 0, err } for key := range o.data { - mem += uint64(len(key)) + mem += uint64(len(key)) + SizeString newMem += uint64(len(key)) + SizeString memValue, newMemValue, err := o._getStr(key).MemUsage(ctx) mem += memValue diff --git a/object_gomap_test.go b/object_gomap_test.go index d93dd655..d0564acf 100644 --- a/object_gomap_test.go +++ b/object_gomap_test.go @@ -365,8 +365,8 @@ func TestGoMapMemUsage(t *testing.T) { "test1": valueInt(99), }, }, - // baseObject overhead + len("testN") + value - expectedMem: SizeEmptyStruct + (5+SizeInt)*2, + // baseObject overhead + len("testN") with string overhead + value + expectedMem: SizeEmptyStruct + ((5+SizeString)+SizeInt)*2, // baseObject overhead + len("testN") with string overhead + value expectedNewMem: SizeEmptyStruct + ((5+SizeString)+SizeInt)*2, errExpected: nil, @@ -382,8 +382,8 @@ func TestGoMapMemUsage(t *testing.T) { "test1": 99, }, }, - // baseObject overhead + len("testN") + value - expectedMem: SizeEmptyStruct + (5+SizeInt)*2, + // baseObject overhead + len("testN") with string overhead + value + expectedMem: SizeEmptyStruct + ((5+SizeString)+SizeInt)*2, // baseObject overhead + len("testN") with string overhead + value expectedNewMem: SizeEmptyStruct + ((5+SizeString)+SizeInt)*2, errExpected: nil, @@ -398,8 +398,8 @@ func TestGoMapMemUsage(t *testing.T) { "test": nil, }, }, - // overhead + len("test") + null - expectedMem: SizeEmptyStruct + 4 + SizeEmptyStruct, + // overhead + len("test") with string overhead + null + expectedMem: SizeEmptyStruct + (4 + SizeString) + SizeEmptyStruct, // overhead + len("test") with string overhead + null expectedNewMem: SizeEmptyStruct + (4 + SizeString) + SizeEmptyStruct, errExpected: nil, @@ -414,8 +414,8 @@ func TestGoMapMemUsage(t *testing.T) { "test": nestedMap, }, }, - // overhead + len("test") + (Object prototype + values) - expectedMem: SizeEmptyStruct + 4 + nestedMapMemUsage, + // overhead + len("testN") with string overhead + (Object prototype with overhead + values with string overhead) + expectedMem: SizeEmptyStruct + (4 + SizeString) + nestedMapMemUsage, // overhead + len("testN") with string overhead + (Object prototype with overhead + values with string overhead) expectedNewMem: SizeEmptyStruct + (4 + SizeString) + nestedMapNewMemUsage, errExpected: nil, @@ -430,8 +430,8 @@ func TestGoMapMemUsage(t *testing.T) { "test": &nestedMap, }, }, - // overhead + len("test") + nested overhead - expectedMem: SizeEmptyStruct + 4 + SizeEmptyStruct, + // overhead + len("testN") with string overhead + nested overhead + expectedMem: SizeEmptyStruct + (4 + SizeString) + SizeEmptyStruct, // overhead + len("testN") with string overhead + nested overhead expectedNewMem: SizeEmptyStruct + (4 + SizeString) + SizeEmptyStruct, errExpected: nil, diff --git a/object_goslice_test.go b/object_goslice_test.go index 38bc9cd4..c191f1b2 100644 --- a/object_goslice_test.go +++ b/object_goslice_test.go @@ -298,6 +298,19 @@ func TestGoSliceMemUsage(t *testing.T) { expectedNewMem: SizeEmptyStruct + SizeInt*2, errExpected: nil, }, + { + name: "should account for baseObject only given a nil data field", + val: &objectGoSlice{ + baseObject: baseObject{ + val: &Object{runtime: vm}, + }, + }, + // overhead + expectedMem: SizeEmptyStruct, + // overhead + expectedNewMem: SizeEmptyStruct, + errExpected: nil, + }, { name: "should account for each value given a slice with go ints", val: &objectGoSlice{ @@ -342,8 +355,8 @@ func TestGoSliceMemUsage(t *testing.T) { }, }, }, - // overhead + (value + len("length") + "length".value + prototype + ints) - expectedMem: SizeEmptyStruct + (SizeEmptyStruct + 6 + SizeEmptyStruct + (SizeEmptyStruct + SizeEmptyStruct) + SizeNumber*2), + // default + default since we don't account for objectGoSlice in (*Object).MemUsage + expectedMem: SizeEmptyStruct + SizeEmptyStruct, // overhead + (value + len("length") with string overhead + "length".value + prototype + ints) expectedNewMem: SizeEmptyStruct + (SizeEmptyStruct + (6 + SizeString) + SizeEmptyStruct + (SizeEmptyStruct + SizeEmptyStruct) + SizeNumber*2), errExpected: nil, @@ -361,8 +374,8 @@ func TestGoSliceMemUsage(t *testing.T) { }, }, }, - // overhead + (value + len("length") + "length".value + prototype + ints) - expectedMem: SizeEmptyStruct + (SizeEmptyStruct + 6 + SizeEmptyStruct + (SizeEmptyStruct + SizeEmptyStruct) + SizeNumber*2), + // default + default since we don't account for objectGoSlice in (*Object).MemUsage + expectedMem: SizeEmptyStruct + SizeEmptyStruct, // overhead + (value + len("length") with string overhead + "length".value + prototype + ints) expectedNewMem: SizeEmptyStruct + (SizeEmptyStruct + (6 + SizeString) + SizeEmptyStruct + (SizeEmptyStruct + SizeEmptyStruct) + SizeNumber*2), errExpected: nil, @@ -371,7 +384,7 @@ func TestGoSliceMemUsage(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - total, newTotal, err := tc.val.MemUsage(NewMemUsageContext(vm, 100, 100, 100, 100, nil)) + total, newTotal, err := tc.val.MemUsage(NewMemUsageContext(vm, 100, 100000, 100, 100, nil)) if err != tc.errExpected { t.Fatalf("Unexpected error. Actual: %v Expected: %v", err, tc.errExpected) } diff --git a/object_test.go b/object_test.go index ee557009..139008eb 100644 --- a/object_test.go +++ b/object_test.go @@ -675,8 +675,8 @@ func TestBaseObjectMemUsage(t *testing.T) { name: "should account for each key value pair given a non-empty object", threshold: 100, val: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, - // overhead + len("test") + value - expectedMem: SizeEmptyStruct + 4 + SizeInt, + // overhead + len("test") with string overhead + value + expectedMem: SizeEmptyStruct + (4 + SizeString) + SizeInt, // overhead + len("test") with string overhead + value expectedNewMem: SizeEmptyStruct + (4 + SizeString) + SizeInt, errExpected: nil, @@ -685,8 +685,8 @@ func TestBaseObjectMemUsage(t *testing.T) { name: "should account for each key value pair given a non-empty object with a nil value", threshold: 100, val: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": nil}}, - // overhead + len("test") - expectedMem: SizeEmptyStruct + 4, + // overhead + len("test") with string overhead + expectedMem: SizeEmptyStruct + (4 + SizeString), // overhead + len("test") with string overhead expectedNewMem: SizeEmptyStruct + (4 + SizeString), errExpected: nil, @@ -708,8 +708,8 @@ func TestBaseObjectMemUsage(t *testing.T) { "test3": valueInt(99), }, }, - // overhead + len("testN") + value - expectedMem: SizeEmptyStruct + (5+SizeInt)*4, + // overhead + len("testN") with string overhead + value + expectedMem: SizeEmptyStruct + ((5+SizeString)+SizeInt)*4, // overhead + len("testN") with string overhead + value expectedNewMem: SizeEmptyStruct + ((5+SizeString)+SizeInt)*4, errExpected: nil, @@ -779,8 +779,8 @@ func TestPrimitiveValueObjectMemUsage(t *testing.T) { { name: "should account for overehead and each key value pair given a primitive value object with non-empty object", val: &primitiveValueObject{baseObject: baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}}, - // baseObject overhead + len("test") + value - expectedMem: SizeEmptyStruct + 4 + SizeInt, + // baseObject overhead + len("test") with string overhead + value + expectedMem: SizeEmptyStruct + (4 + SizeString) + SizeInt, // baseObject overhead + len("test") with string overhead + value expectedNewMem: SizeEmptyStruct + (4 + SizeString) + SizeInt, errExpected: nil, diff --git a/proxy_test.go b/proxy_test.go index 24aacdb1..6d808b67 100644 --- a/proxy_test.go +++ b/proxy_test.go @@ -46,8 +46,8 @@ func TestProxyMemUsage(t *testing.T) { self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - // proxy overhead + baseObject overhead + target overhead + key/value pair - expectedMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeInt), + // proxy overhead + baseObject overhead + target overhead + key/value pair with string overhead + expectedMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), // proxy overhead + baseObject overhead + target overhead + key/value pair with string overhead expectedNewMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, @@ -70,8 +70,8 @@ func TestProxyMemUsage(t *testing.T) { }, }, }, - // proxy overhead + baseObject overhead + target overhead + key/value pair - expectedMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeInt), + // proxy overhead + baseObject overhead + target overhead + key/value pair with string overhead + expectedMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), // proxy overhead + baseObject overhead + target overhead + key/value pair with string overhead expectedNewMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, @@ -126,8 +126,8 @@ func TestJSProxyHandlerMemUsage(t *testing.T) { self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - // baseObject overhead + key/value pair - expectedMem: SizeEmptyStruct + (4 + SizeInt), + // baseObject overhead + key/value pair with string overhead + expectedMem: SizeEmptyStruct + (4 + SizeString + SizeInt), // baseObject overhead + key/value pair with string overhead expectedNewMem: SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, diff --git a/runtime_test.go b/runtime_test.go index 2dec6e80..ac2f7ab6 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -3001,8 +3001,8 @@ func TestRuntimeMemUsage(t *testing.T) { self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - // baseObject overhead + key/value pair - expectedMem: SizeEmptyStruct + (4 + SizeInt), + // baseObject overhead + key/value pair with string overhead + expectedMem: SizeEmptyStruct + (4 + SizeString + SizeInt), // baseObject overhead + key/value pair with string overhead expectedNewMem: SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, diff --git a/string.go b/string.go index bf27cebe..626b8b20 100644 --- a/string.go +++ b/string.go @@ -334,7 +334,7 @@ func (s *stringObject) MemUsage(ctx *MemUsageContext) (memUsage uint64, newMemUs } ctx.VisitObj(s) - memUsage = uint64(s.length) + memUsage = uint64(s.length) + SizeString newMemUsage = uint64(s.length) + SizeString inc, newInc, err := s.baseObject.MemUsage(ctx) diff --git a/string_ascii.go b/string_ascii.go index 77e78d23..2fefb39d 100644 --- a/string_ascii.go +++ b/string_ascii.go @@ -333,7 +333,7 @@ func (s asciiString) ExportType() reflect.Type { } func (s asciiString) MemUsage(ctx *MemUsageContext) (memUsage uint64, newMemUsage uint64, err error) { - return uint64(s.length()), uint64(s.length()) + SizeString, err + return uint64(s.length()) + SizeString, uint64(s.length()) + SizeString, err } func (s asciiString) ToInt() int { diff --git a/string_ascii_test.go b/string_ascii_test.go index 4ba3b949..41064007 100644 --- a/string_ascii_test.go +++ b/string_ascii_test.go @@ -15,14 +15,14 @@ func TestStringAsciiMemUsage(t *testing.T) { { name: "should have a value of 0/SizeString given an empty string", val: asciiString(""), - expectedMem: 0, + expectedMem: SizeString, // string overhead expectedNewMem: SizeString, // string overhead errExpected: nil, }, { name: "should have a value given the length of the string", val: asciiString("yo"), - expectedMem: 2, + expectedMem: 2 + SizeString, // length with string overhead expectedNewMem: 2 + SizeString, // length with string overhead errExpected: nil, }, diff --git a/string_imported.go b/string_imported.go index 286eee9e..7288a750 100644 --- a/string_imported.go +++ b/string_imported.go @@ -351,5 +351,5 @@ func (i *importedString) toTrimmedUTF8() string { } func (i *importedString) MemUsage(ctx *MemUsageContext) (memUsage uint64, newMemUsage uint64, err error) { - return uint64(len(i.String())), uint64(len(i.String())) + SizeString, err + return uint64(len(i.String())) + SizeString, uint64(len(i.String())) + SizeString, err } diff --git a/string_imported_test.go b/string_imported_test.go index 5a128f8f..20c03a4f 100644 --- a/string_imported_test.go +++ b/string_imported_test.go @@ -15,14 +15,14 @@ func TestStringImportedMemUsage(t *testing.T) { { name: "should have a value of 0/SizeString given an empty string", val: &importedString{s: ""}, - expectedMem: 0, + expectedMem: SizeString, // string overhead expectedNewMem: SizeString, // string overhead errExpected: nil, }, { name: "should have a value given the length of the string", val: &importedString{s: "yo"}, - expectedMem: 2, + expectedMem: 2 + SizeString, // length with string overhead expectedNewMem: 2 + SizeString, // length with string overhead errExpected: nil, }, diff --git a/string_test.go b/string_test.go index 2b8790a3..57a46f57 100644 --- a/string_test.go +++ b/string_test.go @@ -183,8 +183,8 @@ func TestStringObjectMemUsage(t *testing.T) { { "should account for base object and data given a non-empty stringObject", &stringObject{value: newStringValue("yo"), length: 2}, - // baseObject + len("yo") - SizeEmptyStruct + 2, + // baseObject + len("yo") and string overhead + SizeEmptyStruct + (2 + SizeString), // baseObject + len("yo") and string overhead SizeEmptyStruct + (2 + SizeString), }, diff --git a/string_unicode.go b/string_unicode.go index b067ed34..d43f58df 100644 --- a/string_unicode.go +++ b/string_unicode.go @@ -560,7 +560,7 @@ func (s unicodeString) string() unistring.String { } func (s unicodeString) MemUsage(ctx *MemUsageContext) (memUsage uint64, newMemUsage uint64, err error) { - return uint64(len(s.String())), uint64(len(s.String())) + SizeString, err + return uint64(len(s.String())) + SizeString, uint64(len(s.String())) + SizeString, err } func (s unicodeString) ToInt() int { return 0 diff --git a/string_unicode_test.go b/string_unicode_test.go index 41c4b400..d8fc089d 100644 --- a/string_unicode_test.go +++ b/string_unicode_test.go @@ -15,14 +15,14 @@ func TestStringUnicodeMemUsage(t *testing.T) { { name: "should have a value of 0/SizeString given an empty string", val: unicodeString{' '}, - expectedMem: 0, + expectedMem: SizeString, // string overhead expectedNewMem: SizeString, // string overhead errExpected: nil, }, { name: "should have a value given the length of the string", val: unicodeString{' ', 'y', 'o'}, - expectedMem: 2, + expectedMem: 2 + SizeString, // length with string overhead expectedNewMem: 2 + SizeString, // length with string overhead errExpected: nil, }, diff --git a/typedarrays_test.go b/typedarrays_test.go index 034f2caf..6705ceb2 100644 --- a/typedarrays_test.go +++ b/typedarrays_test.go @@ -383,8 +383,8 @@ func TestArrayBufferObjectMemUsage(t *testing.T) { val: &arrayBufferObject{ baseObject: baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, - // baseObject overhead + key/value pair - expected: SizeEmptyStruct + (4 + SizeInt), + // baseObject overhead + key/value pair with string overhead + expected: SizeEmptyStruct + (4 + SizeString + SizeInt), // baseObject overhead + key/value pair with string overhead newExpected: SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, @@ -450,8 +450,8 @@ func TestTypedArrayObjectMemUsage(t *testing.T) { val: &typedArrayObject{ baseObject: baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, - // typedArrayObject overhead + baseObject overhead + key/value pair - expected: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeInt), + // typedArrayObject overhead + baseObject overhead + key/value pair with string overhead + expected: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), // typedArrayObject overhead + baseObject overhead + key/value pair with string overhead newExpected: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, @@ -463,8 +463,8 @@ func TestTypedArrayObjectMemUsage(t *testing.T) { baseObject: baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - // typedArrayObject overhead + nil baseObject overhead + arrayBufferObject overhead + key/value pair - expected: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeInt), + // typedArrayObject overhead + nil baseObject overhead + arrayBufferObject overhead + key/value pair with string overhead + expected: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), // typedArrayObject overhead + nil baseObject overhead + arrayBufferObject overhead + key/value pair with string overhead newExpected: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, @@ -485,8 +485,8 @@ func TestTypedArrayObjectMemUsage(t *testing.T) { self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - // typedArrayObject overhead + nil baseObject overhead + defaultCtor overhead + key/value pair - expected: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeInt), + // typedArrayObject overhead + nil baseObject overhead + defaultCtor overhead + key/value pair with string overhead + expected: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), // typedArrayObject overhead + nil baseObject overhead + defaultCtor overhead + key/value pair with string overhead newExpected: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, @@ -552,8 +552,8 @@ func TestDataViewObjectMemUsage(t *testing.T) { val: &dataViewObject{ baseObject: baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, - // typedArrayObject overhead + baseObject overhead + key/value pair - expectedMem: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeInt), + // typedArrayObject overhead + baseObject overhead + key/value pair with string overhead + expectedMem: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), // typedArrayObject overhead + baseObject overhead + key/value pair with string overhead expectedNewMem: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, @@ -565,8 +565,8 @@ func TestDataViewObjectMemUsage(t *testing.T) { baseObject: baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - // typedArrayObject overhead + nil baseObject overhead + arrayBufferObject overhead + key/value pair - expectedMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeInt), + // typedArrayObject overhead + nil baseObject overhead + arrayBufferObject overhead + key/value pair with string overhead + expectedMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), // typedArrayObject overhead + nil baseObject overhead + arrayBufferObject overhead + key/value pair with string overhead expectedNewMem: SizeEmptyStruct + SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, diff --git a/value.go b/value.go index 8274769e..8a41c8fb 100644 --- a/value.go +++ b/value.go @@ -1182,6 +1182,12 @@ func (o *Object) MemUsage(ctx *MemUsageContext) (memUsage uint64, newMemUsage ui return SizeEmptyStruct, SizeEmptyStruct, nil case *objectGoSliceReflect: return SizeEmptyStruct, SizeEmptyStruct, nil + case *objectGoMapSimple: + _, newMemUsage, err := x.MemUsage(ctx) + return SizeEmptyStruct, newMemUsage, err + case *objectGoSlice: + _, newMemUsage, err := x.MemUsage(ctx) + return SizeEmptyStruct, newMemUsage, err default: r, ok := x.(MemUsageReporter) if !ok { @@ -1474,7 +1480,7 @@ func (o valueUnresolved) hash(*maphash.Hash) uint64 { } func (o valueUnresolved) MemUsage(ctx *MemUsageContext) (memUsage uint64, newMemUsage uint64, err error) { - return uint64(len(o.ref)), uint64(len(o.ref)) + SizeString, nil + return uint64(len(o.ref)) + SizeString, uint64(len(o.ref)) + SizeString, nil } func (o valueUnresolved) ToInt() int { diff --git a/value_test.go b/value_test.go index 8ab14c50..604dce1e 100644 --- a/value_test.go +++ b/value_test.go @@ -96,14 +96,14 @@ func TestValueMemUsage(t *testing.T) { { name: "should account for ref given a valueUnresolved", val: valueUnresolved{ref: "test"}, - expectedMem: 4, + expectedMem: 4 + SizeString, expectedNewMem: 4 + SizeString, errExpected: nil, }, { name: "should account for desc given a Symbol", val: &Symbol{desc: newStringValue("test")}, - expectedMem: 4, + expectedMem: 4 + SizeString, expectedNewMem: 4 + SizeString, errExpected: nil, }, @@ -164,7 +164,7 @@ func TestValuePropertyMemUsage(t *testing.T) { self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - expectedMem: SizeEmptyStruct + SizeEmptyStruct + 4, + expectedMem: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString), expectedNewMem: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString), errExpected: nil, }, @@ -175,7 +175,7 @@ func TestValuePropertyMemUsage(t *testing.T) { self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - expectedMem: SizeEmptyStruct + SizeEmptyStruct + 4, + expectedMem: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString), expectedNewMem: SizeEmptyStruct + SizeEmptyStruct + (4 + SizeString), errExpected: nil, }, @@ -201,6 +201,7 @@ func TestValuePropertyMemUsage(t *testing.T) { } func TestObjectMemUsage(t *testing.T) { + vm := New() tests := []struct { name string val *Object @@ -244,19 +245,49 @@ func TestObjectMemUsage(t *testing.T) { errExpected: nil, }, { - name: "should have a value of SizeEmptyStruct given an Object with self of type objectGoMapSimple", + name: "should have a value of SizeEmptyStruct given an Object with self of type objectGoMapSimple empty", val: &Object{self: &objectGoMapSimple{}}, expectedMem: SizeEmptyStruct, expectedNewMem: SizeEmptyStruct, errExpected: nil, }, { - name: "should have a value of SizeEmptyStruct given an Object with self of type objectGoSlice", + name: "should have different values given an Object with self of type objectGoMapSimple non empty", + val: &Object{self: &objectGoMapSimple{ + baseObject: baseObject{ + val: &Object{runtime: vm}, + }, + data: map[string]interface{}{ + "test0": valueInt(99), + "test1": valueInt(99), + }, + }}, + expectedMem: SizeEmptyStruct, + expectedNewMem: SizeEmptyStruct + ((5+SizeString)+SizeInt)*2, + errExpected: nil, + }, + { + name: "should have a value of SizeEmptyStruct given an Object with self of type objectGoSlice empty", val: &Object{self: &objectGoSlice{}}, expectedMem: SizeEmptyStruct, expectedNewMem: SizeEmptyStruct, errExpected: nil, }, + { + name: "should have different values given an Object with self of type objectGoSlice non empty", + val: &Object{self: &objectGoSlice{ + baseObject: baseObject{ + val: &Object{runtime: vm}, + }, + data: &[]interface{}{ + valueInt(99), + valueInt(99), + }, + }}, + expectedMem: SizeEmptyStruct, + expectedNewMem: SizeEmptyStruct + SizeInt*2, + errExpected: nil, + }, { name: "should have a value of SizeEmptyStruct given an Object with self of type objectGoSliceReflect", val: &Object{self: &objectGoSliceReflect{}}, @@ -269,8 +300,8 @@ func TestObjectMemUsage(t *testing.T) { val: &Object{ self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, - // baseObject overhead + value - expectedMem: SizeEmptyStruct + (4 + SizeInt), + // baseObject overhead + value with string overhead + expectedMem: SizeEmptyStruct + (4 + SizeString + SizeInt), // baseObject overhead + value with string overhead expectedNewMem: SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil, diff --git a/vm_test.go b/vm_test.go index b67ff017..3ebc9f4a 100644 --- a/vm_test.go +++ b/vm_test.go @@ -487,8 +487,8 @@ func TestStashMemUsage(t *testing.T) { self: &baseObject{propNames: []unistring.String{"test"}, values: map[unistring.String]Value{"test": valueInt(99)}}, }, }, - // baseObject overhead + obj value - expectedMem: SizeEmptyStruct + (4 + SizeInt), + // baseObject overhead + obj value with string overhead + expectedMem: SizeEmptyStruct + (4 + SizeString + SizeInt), // baseObject overhead + obj value with string overhead expectedNewMem: SizeEmptyStruct + (4 + SizeString + SizeInt), errExpected: nil,