基于多线程的一个Node补环境框架(踩坑1)
基于多线程的一个Node补环境框架(踩坑1)
背景
原本想统一使用vm2沙箱取执行算法/补环境,但是上线后,遇到了这样一个工作量证明算法,是一个CPU密集型任务,很容易把cpu打满,导致服务崩溃无法接收任务。
工作量证明算法:找到一个数值,使得该数值与特定数据组合后的哈希值满足特定条件(这个数值一般当成sign);但是这个算法是一个cpu密集型任务。
案例
Node执行脚本以及结果验证
=== 开始执行 ===
初始内存使用: { rss: '25 MB', heapUsed: '4 MB', heapTotal: '4 MB' }
=== Node执行完成 ===
执行时间: 456.38 ms
最终内存使用: { rss: '33 MB', heapUsed: '5 MB', heapTotal: '6 MB', external: '2 MB' }
内存变化: { rss: '8 MB', heapUsed: '1 MB', heapTotal: '2 MB', external: '0 MB' }
CPU 使用时间: { user: '438.00 ms', system: '110.00 ms' }
Result: W3siand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDYW5wSWRubzVlUzh6YUVORlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LmlzUncyTFZnVlQxYzBpMUZ0a2RCWTZYb2p3NjdLS2E3aEQtbHEtNnhqUFEiLCJzb2x1dGlvbiI6IlFnRUFBQUFBQUFBPSJ9LHsiand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDY0hwR2JGRlVjM1p4Wm5sRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LkxCc0VBem1yZ2ktZTk2Zk1lVEctTU1wY0p2QVgyU0VXdTlDdUJ0eGRCZzgiLCJzb2x1dGlvbiI6IjNnOEFBQUFBQUFBPSJ9LHsiand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZFTjNOa1MyaHBUMDQwZFdsRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5Lm5OUm00WEdtdGRGTDNmQ0RhMC1WbVcxSVgwSXFBQ3ctVzBSeE80Z3dvTFkiLCJzb2x1dGlvbiI6Ilcza0FBQUFBQUFBPSJ9XQ==
Performance: {
executionTime: '456.38 ms',
memoryUsage: {
rss: '8 MB',
heapUsed: '1 MB',
heapTotal: '2 MB',
external: '0 MB'
},
cpuUsage: { user: '438.00 ms', system: '110.00 ms' }
}const crypto = require('crypto');
//#region 改写 sha256 方法, 原方法使用的浏览器 sha256 方法在 node 不适用
async function sha256(input) {
const hash = crypto.createHash('sha256');
const buffer = input instanceof Buffer ? input : Buffer.from(input);
hash.update(buffer);
return hash.digest();
}
//#endregion
//#region 原始加密代码
async function t(t) {
const e = function (t, n) {
const r = BigInt(8 * (t - 3))
, e = BigInt(2);
let o = e;
for (let t = 1; t < r; t++)
o *= e;
return BigInt(n) * o
}(t[13], t[14]);
return o = await async function (t, e) {
let o = 0;
const startTime = Date.now();
const MAX_ITERATIONS = 50000;
const MAX_TIME = 8000;
do {
const a = r(o);
if (await n(a, t) < e)
return a
if (o % 1000 === 0) {
if (o > MAX_ITERATIONS) {
break;
}
if (Date.now() - startTime > MAX_TIME) {
break;
}
await new Promise(resolve => setTimeout(resolve, 0));
}
} while (++o <= Number.MAX_VALUE);
return new Int8Array(0)
}(t, e),
btoa(String.fromCharCode(...new Uint8Array(o)));
var o
}
async function n(t, n) {
const r = function (t, n) {
const r = new Int8Array(40);
for (let n = 0; n < 32; n++)
r[n] = t[n];
for (let t = 32; t < 40; t++)
r[t] = n[t - 32];
return r
}(n, t)
, e = await sha256(Buffer.from(r))
, o = await sha256(Buffer.from(e));
return function (t) {
let n = BigInt(0);
for (let r = t.length - 1; r >= 0; r--)
n = BigInt(n) * BigInt(256),
n += BigInt(t[r]);
return n
}
(new Uint8Array(o))
}
function r(t) {
const n = new Int8Array(8);
for (let r = 0; r < n.length; r++) {
const e = 255 & t;
n[r] = e,
t = (t - e) / 256
}
return n
}
//#endregion
//#region 封装输出
async function execute(body) {
const b = await Promise.all(atob(body).split(",").map(s => {
const m = JSON.parse(atob(s.split(".")[1]));
return {
jwt: s,
puzzle: Int8Array.from(atob(m.puzzle), F => F.charCodeAt(0))
}
}).map(async (s) => { return { jwt: s.jwt, solution: await t(s.puzzle) } }))
return btoa(JSON.stringify(b))
}
//#endregion
// Node.js 性能监控
async function measurePerformance(body) {
const startTime = process.hrtime.bigint();
const initialMemory = process.memoryUsage();
const initialCpuUsage = process.cpuUsage();
console.log('=== 开始执行 ===');
console.log('初始内存使用:', {
rss: Math.round(initialMemory.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(initialMemory.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(initialMemory.heapTotal / 1024 / 1024) + ' MB'
});
const result = await execute(body);
const endTime = process.hrtime.bigint();
const finalMemory = process.memoryUsage();
const finalCpuUsage = process.cpuUsage(initialCpuUsage);
const executionTime = Number(endTime - startTime) / 1000000; // 转换为毫秒
console.log('=== Node执行完成 ===');
console.log('执行时间:', executionTime.toFixed(2) + ' ms');
console.log('最终内存使用:', {
rss: Math.round(finalMemory.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(finalMemory.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(finalMemory.heapTotal / 1024 / 1024) + ' MB',
external: Math.round(finalMemory.external / 1024 / 1024) + ' MB'
});
console.log('内存变化:', {
rss: Math.round((finalMemory.rss - initialMemory.rss) / 1024 / 1024) + ' MB',
heapUsed: Math.round((finalMemory.heapUsed - initialMemory.heapUsed) / 1024 / 1024) + ' MB',
heapTotal: Math.round((finalMemory.heapTotal - initialMemory.heapTotal) / 1024 / 1024) + ' MB',
external: Math.round((finalMemory.external - initialMemory.external) / 1024 / 1024) + ' MB'
});
console.log('CPU 使用时间:', {
user: (finalCpuUsage.user / 1000).toFixed(2) + ' ms',
system: (finalCpuUsage.system / 1000).toFixed(2) + ' ms'
});
return {
result: result,
performance: {
executionTime: executionTime.toFixed(2) + ' ms',
memoryUsage: {
rss: Math.round((finalMemory.rss - initialMemory.rss) / 1024 / 1024) + ' MB',
heapUsed: Math.round((finalMemory.heapUsed - initialMemory.heapUsed) / 1024 / 1024) + ' MB',
heapTotal: Math.round((finalMemory.heapTotal - initialMemory.heapTotal) / 1024 / 1024) + ' MB',
external: Math.round((finalMemory.external - initialMemory.external) / 1024 / 1024) + ' MB'
},
cpuUsage: {
user: (finalCpuUsage.user / 1000).toFixed(2) + ' ms',
system: (finalCpuUsage.system / 1000).toFixed(2) + ' ms'
}
}
};
}
// 测试数据
const bbb = 'ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDYW5wSWRubzVlUzh6YUVORlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LmlzUncyTFZnVlQxYzBpMUZ0a2RCWTZYb2p3NjdLS2E3aEQtbHEtNnhqUFEsZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDY0hwR2JGRlVjM1p4Wm5sRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LkxCc0VBem1yZ2ktZTk2Zk1lVEctTU1wY0p2QVgyU0VXdTlDdUJ0eGRCZzgsZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZFTjNOa1MyaHBUMDQwZFdsRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5Lm5OUm00WEdtdGRGTDNmQ0RhMC1WbVcxSVgwSXFBQ3ctVzBSeE80Z3dvTFk=';
measurePerformance(bbb).then(result => {
console.log('Result:', result.result);
console.log('Performance:', result.performance);
}).catch(error => {
console.error('执行错误:', error);
});VM执行脚本以及结果验证
=== VM执行完成 ===
执行时间: 699.10 ms
最终内存使用: { rss: '32 MB', heapUsed: '4 MB', heapTotal: '6 MB', external: '1 MB' }
内存变化: { rss: '7 MB', heapUsed: '0 MB', heapTotal: '2 MB', external: '0 MB' }
CPU 使用时间: { user: '563.00 ms', system: '47.00 ms' }
Result: W3siand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDYW5wSWRubzVlUzh6YUVORlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LmlzUncyTFZnVlQxYzBpMUZ0a2RCWTZYb2p3NjdLS2E3aEQtbHEtNnhqUFEiLCJzb2x1dGlvbiI6IlFnRUFBQUFBQUFBPSJ9LHsiand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDY0hwR2JGRlVjM1p4Wm5sRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LkxCc0VBem1yZ2ktZTk2Zk1lVEctTU1wY0p2QVgyU0VXdTlDdUJ0eGRCZzgiLCJzb2x1dGlvbiI6IjNnOEFBQUFBQUFBPSJ9LHsiand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZFTjNOa1MyaHBUMDQwZFdsRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5Lm5OUm00WEdtdGRGTDNmQ0RhMC1WbVcxSVgwSXFBQ3ctVzBSeE80Z3dvTFkiLCJzb2x1dGlvbiI6Ilcza0FBQUFBQUFBPSJ9XQ==
Performance: {
executionTime: '699.10 ms',
memoryUsage: {
rss: '7 MB',
heapUsed: '0 MB',
heapTotal: '2 MB',
external: '0 MB'
},
cpuUsage: { user: '563.00 ms', system: '47.00 ms' }
}const vm = require('vm');
const crypto = require('crypto');
// 监控函数
async function measurePerformance(body, timeout = 30000) {
const startTime = process.hrtime.bigint();
const startMemory = process.memoryUsage();
const startCpuUsage = process.cpuUsage();
// 创建沙盒环境
const sandbox = {
crypto,
console,
Buffer,
Promise,
setTimeout,
Date,
BigInt,
Int8Array,
Uint8Array,
atob: (str) => Buffer.from(str, 'base64').toString('binary'),
btoa: (str) => Buffer.from(str, 'binary').toString('base64'),
JSON,
process: {
hrtime: process.hrtime,
memoryUsage: process.memoryUsage,
cpuUsage: process.cpuUsage
},
__result: null
};
const context = vm.createContext(sandbox);
const code = `
//#region 改写 sha256 方法, 原方法使用的浏览器 sha256 方法在 node 不适用
async function sha256(input) {
const hash = crypto.createHash('sha256');
const buffer = input instanceof Buffer ? input : Buffer.from(input);
hash.update(buffer);
return hash.digest();
}
//#endregion
//#region 原始加密代码
async function t(t) {
const e = function (t, n) {
const r = BigInt(8 * (t - 3))
, e = BigInt(2);
let o = e;
for (let t = 1; t < r; t++)
o *= e;
return BigInt(n) * o
}(t[13], t[14]);
return o = await async function (t, e) {
let o = 0;
const startTime = Date.now();
const MAX_ITERATIONS = 50000;
const MAX_TIME = 8000;
do {
const a = r(o);
if (await n(a, t) < e)
return a
if (o % 1000 === 0) {
if (o > MAX_ITERATIONS) {
break;
}
if (Date.now() - startTime > MAX_TIME) {
break;
}
await new Promise(resolve => setTimeout(resolve, 0));
}
} while (++o <= Number.MAX_VALUE);
return new Int8Array(0)
}(t, e),
btoa(String.fromCharCode(...new Uint8Array(o)));
var o
}
async function n(t, n) {
const r = function (t, n) {
const r = new Int8Array(40);
for (let n = 0; n < 32; n++)
r[n] = t[n];
for (let t = 32; t < 40; t++)
r[t] = n[t - 32];
return r
}(n, t)
, e = await sha256(Buffer.from(r))
, o = await sha256(Buffer.from(e));
return function (t) {
let n = BigInt(0);
for (let r = t.length - 1; r >= 0; r--)
n = BigInt(n) * BigInt(256),
n += BigInt(t[r]);
return n
}
(new Uint8Array(o))
}
function r(t) {
const n = new Int8Array(8);
for (let r = 0; r < n.length; r++) {
const e = 255 & t;
n[r] = e,
t = (t - e) / 256
}
return n
}
//#endregion
//#region 封装输出
async function execute(body) {
const b = await Promise.all(atob(body).split(",").map(s => {
const m = JSON.parse(atob(s.split(".")[1]));
return {
jwt: s,
puzzle: Int8Array.from(atob(m.puzzle), F => F.charCodeAt(0))
}
}).map(async (s) => { return { jwt: s.jwt, solution: await t(s.puzzle) } }))
return btoa(JSON.stringify(b))
}
//#endregion
(async () => {
return await execute('${body}');
})();
`;
try {
// 执行代码并等待完成
const result = await vm.runInContext(code, context, { timeout });
// 计算性能指标
const endTime = process.hrtime.bigint();
const endMemory = process.memoryUsage();
const endCpuUsage = process.cpuUsage(startCpuUsage);
const executionTime = Number(endTime - startTime) / 1000000; // 转换为毫秒
const memoryDelta = {
rss: endMemory.rss - startMemory.rss,
heapUsed: endMemory.heapUsed - startMemory.heapUsed,
heapTotal: endMemory.heapTotal - startMemory.heapTotal,
external: endMemory.external - startMemory.external
};
console.log('=== VM执行完成 ===');
console.log('执行时间:', executionTime.toFixed(2) + ' ms');
console.log('最终内存使用:', {
rss: Math.round(endMemory.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(endMemory.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(endMemory.heapTotal / 1024 / 1024) + ' MB',
external: Math.round(endMemory.external / 1024 / 1024) + ' MB'
});
console.log('内存变化:', {
rss: Math.round(memoryDelta.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(memoryDelta.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(memoryDelta.heapTotal / 1024 / 1024) + ' MB',
external: Math.round(memoryDelta.external / 1024 / 1024) + ' MB'
});
console.log('CPU 使用时间:', {
user: (endCpuUsage.user / 1000).toFixed(2) + ' ms',
system: (endCpuUsage.system / 1000).toFixed(2) + ' ms'
});
return {
result: result,
performance: {
executionTime: executionTime.toFixed(2) + ' ms',
memoryUsage: {
rss: Math.round(memoryDelta.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(memoryDelta.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(memoryDelta.heapTotal / 1024 / 1024) + ' MB',
external: Math.round(memoryDelta.external / 1024 / 1024) + ' MB'
},
cpuUsage: {
user: (endCpuUsage.user / 1000).toFixed(2) + ' ms',
system: (endCpuUsage.system / 1000).toFixed(2) + ' ms'
}
}
};
} catch (error) {
console.error('VM执行错误:', error.message);
return {
error: error.message,
performance: {
executionTime: `${Number(process.hrtime.bigint() - startTime) / 1000000}ms`,
memoryUsage: process.memoryUsage(),
cpuUsage: process.cpuUsage(startCpuUsage)
}
};
}
}
// 使用示例
const bbb = 'ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDYW5wSWRubzVlUzh6YUVORlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LmlzUncyTFZnVlQxYzBpMUZ0a2RCWTZYb2p3NjdLS2E3aEQtbHEtNnhqUFEsZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDY0hwR2JGRlVjM1p4Wm5sRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LkxCc0VBem1yZ2ktZTk2Zk1lVEctTU1wY0p2QVgyU0VXdTlDdUJ0eGRCZzgsZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZFTjNOa1MyaHBUMDQwZFdsRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5Lm5OUm00WEdtdGRGTDNmQ0RhMC1WbVcxSVgwSXFBQ3ctVzBSeE80Z3dvTFk=';
measurePerformance(bbb).then(result => {
console.log('Result:', result.result);
console.log('Performance:', result.performance);
});VM2执行脚本以及结果验证
=== 开始执行 ===
初始内存使用: { rss: '31 MB', heapUsed: '5 MB', heapTotal: '6 MB' }
=== VM2执行完成 ===
执行时间: 5334.72 ms
最终内存使用: {
rss: '116 MB',
heapUsed: '48 MB',
heapTotal: '75 MB',
external: '3 MB'
}
内存变化: {
rss: '86 MB',
heapUsed: '42 MB',
heapTotal: '69 MB',
external: '1 MB'
}
CPU 使用时间: { user: '5281.00 ms', system: '219.00 ms' }
Result: W3siand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDYW5wSWRubzVlUzh6YUVORlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LmlzUncyTFZnVlQxYzBpMUZ0a2RCWTZYb2p3NjdLS2E3aEQtbHEtNnhqUFEiLCJzb2x1dGlvbiI6IlFnRUFBQUFBQUFBPSJ9LHsiand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDY0hwR2JGRlVjM1p4Wm5sRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LkxCc0VBem1yZ2ktZTk2Zk1lVEctTU1wY0p2QVgyU0VXdTlDdUJ0eGRCZzgiLCJzb2x1dGlvbiI6IjNnOEFBQUFBQUFBPSJ9LHsiand0IjoiZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZFTjNOa1MyaHBUMDQwZFdsRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5Lm5OUm00WEdtdGRGTDNmQ0RhMC1WbVcxSVgwSXFBQ3ctVzBSeE80Z3dvTFkiLCJzb2x1dGlvbiI6Ilcza0FBQUFBQUFBPSJ9XQ==
Performance: {
executionTime: '5334.72 ms',
memoryUsage: {
rss: '86 MB',
heapUsed: '42 MB',
heapTotal: '69 MB',
external: '1 MB'
},
cpuUsage: { user: '5281.00 ms', system: '219.00 ms' }
}
const { VM } = require('vm2');
const crypto = require('crypto');
async function measurePerformance(body) {
const startTime = process.hrtime.bigint();
const initialMemory = process.memoryUsage();
const initialCpuUsage = process.cpuUsage();
console.log('=== 开始执行 ===');
console.log('初始内存使用:', {
rss: Math.round(initialMemory.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(initialMemory.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(initialMemory.heapTotal / 1024 / 1024) + ' MB'
});
const vm = new VM({
timeout: 20000,
sandbox: {
crypto: crypto,
console: console,
Buffer: Buffer,
btoa: (str) => Buffer.from(str, 'binary').toString('base64'),
atob: (str) => Buffer.from(str, 'base64').toString('binary'),
setTimeout: setTimeout,
Promise: Promise,
Date: Date,
JSON: JSON,
Int8Array: Int8Array,
Uint8Array: Uint8Array,
BigInt: BigInt,
Number: Number,
String: String
}
});
const code = `
//#region 改写 sha256 方法, 原方法使用的浏览器 sha256 方法在 node 不适用
async function sha256(input) {
const hash = crypto.createHash('sha256');
const buffer = input instanceof Buffer ? input : Buffer.from(input);
hash.update(buffer);
return hash.digest();
}
//#endregion
//#region 原始加密代码
async function t(t) {
const e = function (t, n) {
const r = BigInt(8 * (t - 3))
, e = BigInt(2);
let o = e;
for (let t = 1; t < r; t++)
o *= e;
return BigInt(n) * o
}(t[13], t[14]);
return o = await async function (t, e) {
let o = 0;
const startTime = Date.now();
const MAX_ITERATIONS = 50000;
const MAX_TIME = 8000;
do {
const a = r(o);
if (await n(a, t) < e)
return a
if (o % 1000 === 0) {
if (o > MAX_ITERATIONS) {
break;
}
if (Date.now() - startTime > MAX_TIME) {
break;
}
await new Promise(resolve => setTimeout(resolve, 0));
}
} while (++o <= Number.MAX_VALUE);
return new Int8Array(0)
}(t, e),
btoa(String.fromCharCode(...new Uint8Array(o)));
var o
}
async function n(t, n) {
const r = function (t, n) {
const r = new Int8Array(40);
for (let n = 0; n < 32; n++)
r[n] = t[n];
for (let t = 32; t < 40; t++)
r[t] = n[t - 32];
return r
}(n, t)
, e = await sha256(Buffer.from(r))
, o = await sha256(Buffer.from(e));
return function (t) {
let n = BigInt(0);
for (let r = t.length - 1; r >= 0; r--)
n = BigInt(n) * BigInt(256),
n += BigInt(t[r]);
return n
}
(new Uint8Array(o))
}
function r(t) {
const n = new Int8Array(8);
for (let r = 0; r < n.length; r++) {
const e = 255 & t;
n[r] = e,
t = (t - e) / 256
}
return n
}
//#endregion
//#region 封装输出
async function execute(body) {
const b = await Promise.all(atob(body).split(",").map(s => {
const m = JSON.parse(atob(s.split(".")[1]));
return {
jwt: s,
puzzle: Int8Array.from(atob(m.puzzle), F => F.charCodeAt(0))
}
}).map(async (s) => { return { jwt: s.jwt, solution: await t(s.puzzle) } }))
return btoa(JSON.stringify(b))
}
//#endregion
(async () => {
return await execute('${body}');
})();
`;
try {
const result = await vm.run(code);
const endTime = process.hrtime.bigint();
const finalMemory = process.memoryUsage();
const finalCpuUsage = process.cpuUsage(initialCpuUsage);
const executionTime = Number(endTime - startTime) / 1000000; // 转换为毫秒
const memoryUsed = {
rss: finalMemory.rss - initialMemory.rss,
heapUsed: finalMemory.heapUsed - initialMemory.heapUsed,
heapTotal: finalMemory.heapTotal - initialMemory.heapTotal,
external: finalMemory.external - initialMemory.external
};
console.log('=== VM2执行完成 ===');
console.log('执行时间:', executionTime.toFixed(2) + ' ms');
console.log('最终内存使用:', {
rss: Math.round(finalMemory.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(finalMemory.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(finalMemory.heapTotal / 1024 / 1024) + ' MB',
external: Math.round(finalMemory.external / 1024 / 1024) + ' MB'
});
console.log('内存变化:', {
rss: Math.round(memoryUsed.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(memoryUsed.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(memoryUsed.heapTotal / 1024 / 1024) + ' MB',
external: Math.round(memoryUsed.external / 1024 / 1024) + ' MB'
});
console.log('CPU 使用时间:', {
user: (finalCpuUsage.user / 1000).toFixed(2) + ' ms',
system: (finalCpuUsage.system / 1000).toFixed(2) + ' ms'
});
return {
result: result,
performance: {
executionTime: executionTime.toFixed(2) + ' ms',
memoryUsage: {
rss: Math.round(memoryUsed.rss / 1024 / 1024) + ' MB',
heapUsed: Math.round(memoryUsed.heapUsed / 1024 / 1024) + ' MB',
heapTotal: Math.round(memoryUsed.heapTotal / 1024 / 1024) + ' MB',
external: Math.round(memoryUsed.external / 1024 / 1024) + ' MB'
},
cpuUsage: {
user: (finalCpuUsage.user / 1000).toFixed(2) + ' ms',
system: (finalCpuUsage.system / 1000).toFixed(2) + ' ms'
}
}
};
} catch (error) {
const errorTime = Number(process.hrtime.bigint() - startTime) / 1000000;
console.log('=== VM2执行错误 ===');
console.log('执行时间:', errorTime.toFixed(2) + ' ms');
console.log('错误:', error.message);
return {
error: error.message,
performance: {
executionTime: errorTime.toFixed(2) + ' ms',
memoryUsage: process.memoryUsage(),
cpuUsage: process.cpuUsage(initialCpuUsage)
}
};
}
}
// 使用示例
const bbb = 'ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDYW5wSWRubzVlUzh6YUVORlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LmlzUncyTFZnVlQxYzBpMUZ0a2RCWTZYb2p3NjdLS2E3aEQtbHEtNnhqUFEsZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZDY0hwR2JGRlVjM1p4Wm5sRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5LkxCc0VBem1yZ2ktZTk2Zk1lVEctTU1wY0p2QVgyU0VXdTlDdUJ0eGRCZzgsZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKd2RYcDZiR1VpT2lKQlFVRkJRVUZFTjNOa1MyaHBUMDQwZFdsRlMwRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZDUkV0WFowdDRjMDlaYUN0VU5tMXFSR001WTI0eGRXOXdUblpPZUVrMGEwOTJVekpzSzI1dllsTlRRVDA5SWl3aWFXRjBJam94TnpZek5UVTVPRGM0TENKbGVIQWlPakUzTmpNMU5UazVNemg5Lm5OUm00WEdtdGRGTDNmQ0RhMC1WbVcxSVgwSXFBQ3ctVzBSeE80Z3dvTFk=';
measurePerformance(bbb).then(result => {
console.log('Result:', result.result);
console.log('Performance:', result.performance);
});
总结
所以在做一个通用的补环境框架的时候,尽量不用使用VM2。
执行时间
Node: 456.38 ms
VM: 699.10 ms (+53%)
VM2: 5334.72 ms (+1069%)
内存
环境 RSS增长 Heap增长
Node +8 MB +1 MB
VM +7 MB +0 MB
VM2 +86 MB +42 MB
CPU
环境 用户CPU 系统CPU
Node 438 ms 110 ms
VM 563 ms 47 ms
VM2 5281 ms 219 ms
本文是原创文章,采用 CC 4.0 协议,完整转载请注明来自 http://www.1997.pro/
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果