scp() and write() are very slow, because they have to recalculate ram costs.
In the course of investigating a typo, I realized that there's no need for ns.scp() and ns.write() to calculate ram at all. They can defer the work until when the script is executed. The only visible artifact is that RAM costs will be incorrect until the script is run; however, they were already wrong for scp anyway, when it overwrites files. (Check the diff carefully)
benchmark:
/** @param {NS} ns */
export async function main(ns) {
const perf = globalThis.performance;
let speedMax = 0;
for (let i = 0; i < Number(ns.args[0]); ++i) {
const start = perf.now();
let end, cycles;
for (cycles = 0; (end = perf.now()) - start < 1000; cycles++) {
ns.write("scpdata.js", "export function main() {}", "w");
}
const speed = (cycles * 1000) / (end - start);
speedMax = speed > speedMax ? speed : speedMax;
ns.tprintf("Iter %2d: %.3f/sec", i, speed);
await new Promise(resolve => setTimeout(resolve));
}
ns.tprintf("Best: %.3f/sec", speedMax);
}
Before:
[home ~/]> run benchmark.js 20
Running script with 1 thread(s), pid 66553 and args: [20].
Iter 0: 1464.707/sec
Iter 1: 1722.828/sec
Iter 2: 1836.449/sec
Iter 3: 1989.602/sec
Iter 4: 2137.359/sec
Iter 5: 1888.245/sec
Iter 6: 1694.831/sec
Iter 7: 1734.480/sec
Iter 8: 1933.420/sec
Iter 9: 2327.767/sec
Iter 10: 2209.779/sec
Iter 11: 2060.588/sec
Iter 12: 2266.773/sec
Iter 13: 1991.000/sec
Iter 14: 2030.594/sec
Iter 15: 2214.557/sec
Iter 16: 2169.915/sec
Iter 17: 2079.376/sec
Iter 18: 2131.000/sec
Iter 19: 2058.794/sec
Best: 2327.767/sec
After:
[home ~/]> run benchmark.js 20
Running script with 1 thread(s), pid 1 and args: [20].
Iter 0: 355124.000/sec
Iter 1: 360699.000/sec
Iter 2: 360630.000/sec
Iter 3: 336384.000/sec
Iter 4: 367969.000/sec
Iter 5: 307557.244/sec
Iter 6: 339932.000/sec
Iter 7: 335873.000/sec
Iter 8: 350184.000/sec
Iter 9: 330100.000/sec
Iter 10: 349447.276/sec
Iter 11: 334633.000/sec
Iter 12: 337402.000/sec
Iter 13: 333241.000/sec
Iter 14: 365532.000/sec
Iter 15: 342055.000/sec
Iter 16: 305680.000/sec
Iter 17: 314308.000/sec
Iter 18: 364318.000/sec
Iter 19: 304195.000/sec
Best: 367969.000/sec
Test script showing the typo issue, and new behavior:
/** @param {NS} ns */
export async function main(ns) {
ns.rm("scpdata.js");
ns.write("scpdata.js", `export function main(ns) {}`, "w");
ns.tprint("Size of base scpdata: " + ns.getScriptRam("scpdata.js"));
ns.rm("scpdata.js", "n00dles");
ns.scp("scpdata.js", "n00dles");
ns.write("scpdata.js", `export function main(ns) {
ns.tprint("I like " + ns.getServer("n00dles").hostname);
}`, "w");
ns.tprint("Size of new scpdata: " + ns.getScriptRam("scpdata.js"));
ns.scp("scpdata.js", "n00dles");
ns.tprint("Size of new on n00dles: " + ns.getScriptRam("scpdata.js", "n00dles"));
ns.exec("scpdata.js", "n00dles");
await ns.sleep(0);
ns.tprint("Size on n00dles after exec: " + ns.getScriptRam("scpdata.js", "n00dles"));
}
Before:
[home ~/]> run scp.js
Running script with 1 thread(s), pid 66558 and args: [].
scp.js: Size of base scpdata: 1.6
scp.js: Size of new scpdata: 3.6
scp.js: Size of new on n00dles: 1.6
scp.js: Size on n00dles after exec: 3.6
scpdata.js: I like n00dles
After:
[home ~/]> run scp.js
Running script with 1 thread(s), pid 2 and args: [].
scp.js: Size of base scpdata: 0
scp.js: Size of new scpdata: 0
scp.js: Size of new on n00dles: 0
scp.js: Size on n00dles after exec: 3.6
scpdata.js: I like n00dles