bitburner-official / bitburner-src

Bitburner source code.
Other
774 stars 256 forks source link

NETSCRIPT PORTS: Too many ports makes NetscriptPorts exceed Map's size limit #1189

Closed User670 closed 5 months ago

User670 commented 5 months ago

Scripts to reproduce: test.js:

/** @param {NS} ns */
export async function main(ns) {
    const ProcessesPerBatch=100_000
    let processesSpawned=0
    while(true){
        for(let i=0; i<ProcessesPerBatch; i++){
            ns.exec("worker.js","home")
        }
        processesSpawned+=ProcessesPerBatch
        ns.tprint(processesSpawned)
        await ns.sleep(0)
    }
}

worker.js:

/** @param {NS} ns */
export async function main(ns) {
    await ns.sleep(0)
    ns.writePort(ns.pid, 1)
}

Steps to reproduce:

Traceback:

RUNTIME ERROR
worker.js@home (PID - 16777218)

Map maximum size exceeded
stack:
RangeError: Map maximum size exceeded
    at Map.set (<anonymous>)
    at getPort (webpack-internal:///./src/NetscriptPort.ts:28:64)
    at writePort (webpack-internal:///./src/NetscriptPort.ts:56:16)
    at eval (webpack-internal:///./src/NetscriptFunctions.ts:1267:70)
    at Proxy.wrappedFunction (webpack-internal:///./src/Netscript/APIWrapper.ts:67:16)
    at Module.main (home/worker.js:4:8)
    at async startNetscript2Script (webpack-internal:///./src/NetscriptWorker.ts:82:3)

The test was done on a fork of the dev version (v2.6.1dev, closest main repo commit is 6aaeb6b , I added console.log's in places that don't concern this bug for something else but nothing that affects the game's logic. If needed I'll test on a clean dev version or the stable version), but the issue also happened on my stable version game (Bitburner v2.6.0 (8154a4613))

In case you wonder "why the heck do you have 16M ports" - the answer is batching for overnight sessions.

LJNeon commented 5 months ago

Batching overnight shouldn't create that many ports unless there's an issue with your code that causes ports to leak. Ports should be cleaned up (removed from that Map) immediately after write if you're using nextWrite to read from it.

I'm tempted to say this isn't a bug because there's no use case for that many concurrent ports. There are countless ways to break the game if you do something dumb (like the Number.isNaN = null; guy in the discord bug reports channel).

EDIT: Here's exactly where read deletes the port from that Map.

User670 commented 5 months ago

Converted it into a feature request. Closing this one.

d0sboots commented 5 months ago

To add on to what LJ said: The problem here is that you wrote to each of these ports, but never read from them. As a result, all the data for them can never be cleaned up or reclaimed. If you fix that (which should be possible for any conceivable scenario), the issue goes away.