import { MemoryTestContiguousParams } from "upload-diagnostic-plugin/types/Params"; import { assertUnreachable } from "upload-diagnostic-plugin/common/TypeUtils"; const increments = [ {from: 0, increment: 1}, {from: 40, increment: 5}, {from: 100, increment: 10}, {from: 250, increment: 25}, {from: 500, increment: 50}, {from: 1000, increment: 100}, {from: 2000, increment: 250}, ] export class MemoryTestContiguous { private seed = 0 async run(params: MemoryTestContiguousParams): Promise { let mbToAllocate = 0 let data = "" let buffer: Buffer const allocateMemoryAndRepeat = (iteration: number): void => { const nextIncrement = increments.findIndex(x => iteration < x.from) const incrementIndex = Math.max(0, (nextIncrement === -1 ? increments.length : nextIncrement) - 1) const increment = increments[incrementIndex].increment mbToAllocate += increment let used: number switch (params.allocate) { case "buffer": { const bufferSize = mbToAllocate * 1024 * 1024 buffer = Buffer.alloc(bufferSize) let bytesWritten = 0 while (bytesWritten < bufferSize) { const input = this.fastRandom().toString() const inputSize = input.length buffer.write(input, Math.min(bytesWritten, bufferSize - inputSize)) bytesWritten += inputSize } used = Math.round(process.memoryUsage().arrayBuffers / Math.pow(1024, 2)); break; } case "string": for (let i = 0; i < increment * 1024 * 20; i++) { data += this.fastRandom().toString() } used = Math.round(process.memoryUsage().heapUsed / Math.pow(1024, 2)); break; default: assertUnreachable(params.allocate); } console.log(`Memory usage: ${used}MB`) continueAllocatingMemory(iteration + 1) } const continueAllocatingMemory = (iteration: number): void => { setTimeout(() => allocateMemoryAndRepeat(iteration), 100); } continueAllocatingMemory(1) await new Promise(() => {}) // Program ends when it OOMs. console.log(data) // Prevents ESLint error. } private fastRandom(): number { this.seed = this.seed * 48271 % 2147483647 // https://en.wikipedia.org/wiki/Lehmer_random_number_generator return this.seed } }