New TLSF, see #15

This commit is contained in:
dcodeIO
2018-02-01 17:35:51 +01:00
parent 3924aa96ae
commit a8da04404a
10 changed files with 628 additions and 828 deletions

View File

@ -1,61 +1,28 @@
var fs = require("fs");
function test(file) {
console.log("Testing '" + file + "' ...");
var runner = require("./runner");
var tlsf = new WebAssembly.Instance(WebAssembly.Module(fs.readFileSync(__dirname + "/../" + file)), {
function test(file) {
console.log("Testing '" + file + "' ...\n");
var exports = new WebAssembly.Instance(WebAssembly.Module(fs.readFileSync(__dirname + "/../" + file)), {
env: {
log_i: function(i) { i == -1 ? console.log("---") : console.log("log_i -> " + i); }
abort: function(msg, file, line, column) {
throw Error("Assertion failed: " + (msg ? "'" + getString(msg) + "' " : "") + "at " + getString(file) + ":" + line + ":" + column);
},
log: function(ptr) { console.log(getString(ptr)); },
logi: function(i) { console.log(i); }
}
}).exports;
try {
var memSize = 0;
var ptr = 0;
for (var j = 0; j < 10000; ++j) {
if (!j || !((j + 1) % 1000))
console.log("run #" + (j + 1));
ptr;
var ptrs = [];
// allocate some blocks of unusual sizes
for (var i = 0; i < 2048; ++i) {
var size = i * 61;
ptr = tlsf.allocate_memory(size);
if (tlsf.set_memory)
tlsf.set_memory(ptr, ptr % 256, size); // slow
// immediately free every 4th
if (!(i % 4)) {
tlsf.free_memory(ptr);
} else {
ptrs.push(ptr);
// randomly free random blocks (if not the first run that determines max memory)
if (j && Math.random() < 0.25) {
ptr = ptrs.splice((Math.random() * ptrs.length)|0, 1)[0];
tlsf.free_memory(ptr);
}
}
}
if (tlsf.check)
tlsf.check();
if (tlsf.check_pool)
tlsf.check_pool(0);
// clean up by randomly freeing all blocks
while (ptrs.length) {
ptr = ptrs.splice((Math.random() * ptrs.length)|0, 1)[0];
tlsf.free_memory(ptr);
}
if (memSize && memSize != tlsf.memory.buffer.byteLength)
throw new Error("memory should not grow multiple times: " + memSize + " != " + tlsf.memory.buffer.byteLength);
memSize = tlsf.memory.buffer.byteLength;
if (tlsf.check)
tlsf.check();
if (tlsf.check_pool)
tlsf.check_pool(0);
}
} finally {
// mem(tlsf.memory, 0, 4096);
console.log("memSize=" + memSize);
function getString(ptr) {
var len = new Uint32Array(exports.memory.buffer, ptr)[0];
var str = new Uint16Array(exports.memory.buffer, ptr + 4).subarray(0, len);
return String.fromCharCode.apply(String, str);
}
runner(exports, 10, 20000); // picked so I/O isn't the bottleneck
console.log("mem final: " + exports.memory.buffer.byteLength);
console.log();
}

View File

@ -0,0 +1,91 @@
function runner(tlsf, runs, allocs) {
var ptrs = [];
function randomAlloc(maxSize) {
if (!maxSize) maxSize = 8192;
var size = ((Math.random() * maxSize) >>> 0) + 1;
size = (size + 3) & ~3;
var ptr = tlsf.allocate_memory(size);
if (!ptr) throw Error();
if (ptrs.indexOf(ptr) >= 0) throw Error();
if (tlsf.set_memory)
tlsf.set_memory(ptr, 0xdc, size);
ptrs.push(ptr);
return ptr;
}
function preciseFree(ptr) {
var idx = ptrs.indexOf(ptr);
if (idx < 0) throw Error();
var ptr = ptrs[idx];
ptrs.splice(idx, 1);
if (typeof ptr !== "number") throw Error();
tlsf.free_memory(ptr);
}
function randomFree() {
var idx = (Math.random() * ptrs.length) >>> 0;
var ptr = ptrs[idx];
if (typeof ptr !== "number") throw Error();
ptrs.splice(idx, 1);
tlsf.free_memory(ptr);
}
// remember the smallest possible memory address
var base = tlsf.allocate_memory(64);
console.log("base: " + base);
tlsf.free_memory(base);
console.log("mem initial: " + tlsf.memory.buffer.byteLength);
for (var j = 0; j < runs; ++j) {
console.log("run " + (j + 1) + " (" + allocs + " allocations) ...");
for (var i = 0; i < allocs; ++i) {
var ptr = randomAlloc();
// immediately free every 4th
if (!(i % 4)) preciseFree(ptr);
// occasionally free random blocks
else if (ptrs.length && Math.random() < 0.33) randomFree();
// ^ sums up to clearing about half the blocks half-way
}
// free the rest, randomly
while (ptrs.length) randomFree();
// should now be possible to reuse the entire first page (remember: sl+1)
// e.g. with base 3088 (3048 optimized due to static memory):
var size = 0x10000 - base - 4 - 1008;
// 61436 (1110111111111100b) -> fl = 15, sl = 27
// 61437 (61440 aligned, 1111000000000000b) -> fl = 15, sl = 28
// NOTE that this calculation will be different if static memory changes
var ptr = tlsf.allocate_memory(size);
tlsf.set_memory(ptr, 0xac, size);
if (ptr !== base) throw Error("expected " + base + " but got " + ptr);
tlsf.free_memory(ptr);
}
mem(tlsf.memory, 0, 0x10000); // should end in 02 00 00 00 (tail LEFT_FREE)
}
function mem(memory, offset, count) {
if (!offset) offset = 0;
if (!count) count = 1024;
var mem = new Uint8Array(memory.buffer, offset);
var stackTop = new Uint32Array(memory.buffer, 4, 1)[0];
var hex = [];
for (var i = 0; i < count; ++i) {
var o = (offset + i).toString(16);
while (o.length < 4) o = "0" + o;
if ((i & 15) === 0) {
hex.push("\n" + o + ":");
}
var h = mem[i].toString(16);
if (h.length < 2) h = "0" + h;
hex.push(h);
}
console.log(hex.join(" ") + " ...");
}
if (typeof module === "object" && typeof exports === "object")
module.exports = runner;