| <html> |
| <head> |
| <title>ArrayBuffer External Memory test</title> |
| <script> |
| |
| var log; |
| function print(message, color) |
| { |
| var paragraph = document.createElement("div"); |
| paragraph.appendChild(document.createTextNode(message)); |
| paragraph.style.fontFamily = "monospace"; |
| if (color) |
| paragraph.style.color = color; |
| log.appendChild(paragraph); |
| } |
| |
| function pass(msg) |
| { |
| print("PASS: " + msg, "green"); |
| } |
| |
| function fail(msg) |
| { |
| print("FAIL: " + msg, "red"); |
| } |
| |
| var KB = 1024; |
| var MB = KB * KB; |
| var noise = KB; |
| |
| function externalMemory() { |
| return getV8Statistics().amount_of_external_allocated_memory; |
| } |
| |
| function collectGarbage() { |
| for (var i = 0; i < 10; i++) gc(); |
| } |
| |
| function allocationsThatIncreaseExternalMemory() { |
| function test(expression) { |
| var before = externalMemory(); |
| (function () { eval(expression); }) (); |
| var now = externalMemory(); |
| if (now < before + MB - noise) { |
| fail(expression + " did not increase the amount of external memory (" + |
| before + ", " + now + ")."); |
| } else { |
| pass(expression + " increased the amount of external memory."); |
| } |
| collectGarbage(); |
| var after = externalMemory(); |
| if (after > now + noise) { |
| fail("Garbage collection after " + expression + |
| " did not return the amount of external memory to the initial value (" + |
| now + ", " + after + ")."); |
| } else { |
| pass("Garbage collection after " + expression + |
| " returned the amount of external memory to the initial value."); |
| } |
| } |
| |
| test("(new ArrayBuffer(MB))"); |
| test("(new Float32Array(MB))"); |
| test("(new Float64Array(MB))"); |
| test("(new Int8Array(MB))"); |
| test("(new Int16Array(MB))"); |
| test("(new Int32Array(MB))"); |
| test("(new Uint8Array(MB))"); |
| test("(new Uint16Array(MB))"); |
| test("(new Uint32Array(MB))"); |
| var largeJSArray = []; |
| for (var i = 0; i < MB; i++) largeJSArray.push(i); |
| test("(new Float32Array(largeJSArray))"); |
| test("(new Float64Array(largeJSArray))"); |
| test("(new Int8Array(largeJSArray))"); |
| test("(new Int16Array(largeJSArray))"); |
| test("(new Int32Array(largeJSArray))"); |
| test("(new Uint8Array(largeJSArray))"); |
| test("(new Uint16Array(largeJSArray))"); |
| test("(new Uint32Array(largeJSArray))"); |
| var int8Array = new Int8Array(MB); |
| test("(new Float32Array(int8Array))"); |
| test("(new Float64Array(int8Array))"); |
| test("(new Int8Array(int8Array))"); |
| test("(new Int16Array(int8Array))"); |
| test("(new Int32Array(int8Array))"); |
| test("(new Uint8Array(int8Array))"); |
| test("(new Uint16Array(int8Array))"); |
| test("(new Uint32Array(int8Array))"); |
| } |
| |
| |
| function allocationsThatDoNotChangeExternalMemory() { |
| function test(expression) { |
| var before = externalMemory(); |
| (function () { eval(expression); }) (); |
| var now = externalMemory(); |
| if (now > before + noise) { |
| fail(expression + " increased the amount of external memory (" + before + ", " + now + ")."); |
| } else { |
| pass(expression + " did not increase the amount of external memory."); |
| } |
| collectGarbage(); |
| var after = externalMemory(); |
| if (after < now - noise) { |
| fail("Garbage collection after " + expression + " decreased the amount of external memory (" + |
| now + ", " + after + ")."); |
| } else { |
| pass("Garbage collection after " + expression + |
| " did not decrease the amount of external memory."); |
| } |
| } |
| var arrayBuffer = new ArrayBuffer(MB); |
| test("(new Float32Array(arrayBuffer))"); |
| test("(new Float64Array(arrayBuffer))"); |
| test("(new Int8Array(arrayBuffer))"); |
| test("(new Int16Array(arrayBuffer))"); |
| test("(new Int32Array(arrayBuffer))"); |
| test("(new Uint8Array(arrayBuffer))"); |
| test("(new Uint16Array(arrayBuffer))"); |
| test("(new Uint32Array(arrayBuffer))"); |
| var int8Array = new Int8Array(MB); |
| test("(new Float32Array(int8Array.buffer))"); |
| test("(new Float64Array(int8Array.buffer))"); |
| test("(new Int8Array(int8Array.buffer))"); |
| test("(new Int16Array(int8Array.buffer))"); |
| test("(new Int32Array(int8Array.buffer))"); |
| test("(new Uint8Array(int8Array.buffer))"); |
| test("(new Uint16Array(int8Array.buffer))"); |
| test("(new Uint32Array(int8Array.buffer))"); |
| } |
| |
| |
| function transfersThatDecreaseExternalMemory() { |
| var workerSource = |
| "function externalMemory() {\n" + |
| " return getV8Statistics().amount_of_external_allocated_memory;\n" + |
| "}\n" + |
| "var KB = 1024;\n" + |
| "var MB = KB * KB;\n" + |
| "var noise = KB;\n" + |
| "self.onmessage = function(e) {\n" + |
| " var before = externalMemory();\n" + |
| " e.data;\n" + |
| " var after = externalMemory();\n" + |
| " if (after > before + MB - noise) {\n" + |
| " self.postMessage('PASS: Amount of external memory increased.');\n" + |
| " } else {\n" + |
| " self.postMessage('FAIL: Amount of external memory did not increase.');\n" + |
| " }\n" + |
| "}\n"; |
| |
| var blob = new Blob([workerSource]); |
| var worker = new Worker(window.webkitURL.createObjectURL(blob)); |
| worker.onmessage = function (e) { |
| print("message from worker: " + e.data, "blue"); |
| } |
| function test(expression) |
| { |
| var buffer = eval(expression); |
| try { |
| var before = externalMemory(); |
| worker.postMessage(buffer, [buffer]); |
| var now = externalMemory(); |
| if (now > before - MB + noise) { |
| fail("Transfer of " + expression + " did not decrease the amount of external memory (" + |
| before + ", " + now + ")."); |
| } else { |
| pass("Transfer of " + expression + " decreased the amount of external memory."); |
| } |
| collectGarbage(); |
| var after = externalMemory(); |
| if (after < now - noise) { |
| fail("Garbage collection after transfer of " + expression + |
| " decreased the amount of external memory (" + now + ", " + after + ")."); |
| } else { |
| pass("Garbage collection after transfer of " + expression + |
| " did not decrease the amount of external memory."); |
| } |
| } catch (e) { |
| fail("Transfer of " + name + ": could not webkitPostMessage: " + e); |
| return false; |
| } |
| return true; |
| } |
| test("(new ArrayBuffer(MB))"); |
| test("(new Float32Array(MB)).buffer"); |
| test("(new Float64Array(MB)).buffer"); |
| test("(new Int8Array(MB)).buffer"); |
| test("(new Int16Array(MB)).buffer"); |
| test("(new Int32Array(MB)).buffer"); |
| test("(new Uint8Array(MB)).buffer"); |
| test("(new Uint16Array(MB)).buffer"); |
| test("(new Uint32Array(MB)).buffer"); |
| } |
| |
| |
| function runAll() { |
| log = document.getElementById("log1"); |
| if (typeof gc == "undefined" || typeof getV8Statistics == "undefined") { |
| print("Run chrome browser with --js-flags='--expose_gc --track_gc_object_stats'", "red"); |
| } else { |
| allocationsThatIncreaseExternalMemory(); |
| collectGarbage(); |
| allocationsThatDoNotChangeExternalMemory(); |
| collectGarbage(); |
| log = document.getElementById("log2"); |
| transfersThatDecreaseExternalMemory(); |
| collectGarbage(); |
| } |
| } |
| |
| </script> |
| </head> |
| <body onload="runAll()"> |
| <p>This test checks that allocation and deallocation of typed arrays correctly |
| adjusts the amount of external memory in V8.</p> |
| <div id='log1'></div> |
| <p>This test checks that transfer of an array buffer to worker decreases amount of |
| external memory in the main V8 isolate.</p> |
| <div id='log2'></div> |
| </body> |
| </html> |