slimjson 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +8 -0
- package/README.md +142 -39
- package/README_EN.md +350 -0
- package/compress-test.js +51 -25
- package/compress.js +423 -410
- package/data/searchGroup.json +96365 -0
- package/package.json +1 -1
- package/test.js +473 -384
package/compress-test.js
CHANGED
|
@@ -294,31 +294,39 @@ function generateDeepNested(orgCount = 2, deptPerOrg = 3, teamPerDept = 4, membe
|
|
|
294
294
|
* - compress → decompress → compress 应该得到相同结果(roundtrip)
|
|
295
295
|
* - 缺失字段会被填充为 null,这是预期的规范化行为
|
|
296
296
|
*/
|
|
297
|
-
function verifyRoundtrip(original, compressed) {
|
|
297
|
+
function verifyRoundtrip(original, compressed, opts) {
|
|
298
298
|
const decompressed = decompress(compressed);
|
|
299
|
-
const recompressed = compress(decompressed);
|
|
299
|
+
const recompressed = compress(decompressed, opts);
|
|
300
300
|
// 二次压缩后结构应该完全一致
|
|
301
301
|
return JSON.stringify(compressed) === JSON.stringify(recompressed);
|
|
302
302
|
}
|
|
303
303
|
|
|
304
304
|
function runTest(name, data) {
|
|
305
305
|
const originalSize = getByteSize(data);
|
|
306
|
+
|
|
307
|
+
// 默认(不 trim)
|
|
306
308
|
const compressed = compress(data);
|
|
307
309
|
const compressedSize = Buffer.byteLength(stringify(compressed), 'utf8');
|
|
308
|
-
|
|
309
|
-
// 验证解压正确性(roundtrip: compress→decompress→compress 结果一致)
|
|
310
310
|
const isCorrect = verifyRoundtrip(data, compressed);
|
|
311
|
-
|
|
312
311
|
const ratio = ((originalSize - compressedSize) / originalSize * 100).toFixed(2);
|
|
313
|
-
const savings = originalSize - compressedSize;
|
|
314
312
|
|
|
315
|
-
|
|
313
|
+
// trimTrailingNulls
|
|
314
|
+
const compressedTrim = compress(data, { trimTrailingNulls: true });
|
|
315
|
+
const compressedTrimSize = Buffer.byteLength(stringify(compressedTrim), 'utf8');
|
|
316
|
+
const isCorrectTrim = verifyRoundtrip(data, compressedTrim, { trimTrailingNulls: true });
|
|
317
|
+
const ratioTrim = ((originalSize - compressedTrimSize) / originalSize * 100).toFixed(2);
|
|
318
|
+
|
|
319
|
+
const diff = compressedSize - compressedTrimSize;
|
|
320
|
+
const diffStr = diff > 0 ? `-${formatBytes(diff)}` : diff === 0 ? '—' : `+${formatBytes(-diff)}`;
|
|
321
|
+
|
|
322
|
+
console.log(`\n${'='.repeat(72)}`);
|
|
316
323
|
console.log(`测试: ${name}`);
|
|
317
|
-
console.log('-'.repeat(
|
|
324
|
+
console.log('-'.repeat(72));
|
|
318
325
|
console.log(`对象数量: ${data.length}`);
|
|
319
326
|
console.log(`原始大小: ${formatBytes(originalSize)}`);
|
|
320
|
-
console.log(
|
|
321
|
-
console.log(
|
|
327
|
+
console.log(`不 trim: ${formatBytes(compressedSize).padStart(10)} (${ratio}%) ${isCorrect ? '✓' : '✗'}`);
|
|
328
|
+
console.log(`trim: ${formatBytes(compressedTrimSize).padStart(10)} (${ratioTrim}%) ${isCorrectTrim ? '✓' : '✗'}`);
|
|
329
|
+
console.log(`差值: ${diffStr}`);
|
|
322
330
|
|
|
323
331
|
return {
|
|
324
332
|
name,
|
|
@@ -326,6 +334,9 @@ function runTest(name, data) {
|
|
|
326
334
|
originalSize,
|
|
327
335
|
compressedSize,
|
|
328
336
|
ratio: parseFloat(ratio),
|
|
337
|
+
compressedTrimSize,
|
|
338
|
+
ratioTrim: parseFloat(ratioTrim),
|
|
339
|
+
diff,
|
|
329
340
|
isCorrect
|
|
330
341
|
};
|
|
331
342
|
}
|
|
@@ -375,26 +386,41 @@ function main() {
|
|
|
375
386
|
|
|
376
387
|
// 汇总
|
|
377
388
|
console.log('\n\n');
|
|
378
|
-
console.log('
|
|
379
|
-
console.log('║
|
|
380
|
-
console.log('
|
|
389
|
+
console.log('╔══════════════════════════════════════════════════════════════════════════╗');
|
|
390
|
+
console.log('║ 测试结果汇总 ║');
|
|
391
|
+
console.log('╚══════════════════════════════════════════════════════════════════════════╝');
|
|
381
392
|
console.log('\n');
|
|
382
|
-
|
|
393
|
+
|
|
383
394
|
const avgRatio = results.reduce((sum, r) => sum + r.ratio, 0) / results.length;
|
|
384
|
-
const
|
|
385
|
-
const
|
|
386
|
-
|
|
395
|
+
const avgRatioTrim = results.reduce((sum, r) => sum + r.ratioTrim, 0) / results.length;
|
|
396
|
+
const totalDiff = results.reduce((sum, r) => sum + r.diff, 0);
|
|
397
|
+
const bestCase = results.reduce((best, r) => r.ratioTrim > best.ratioTrim ? r : best);
|
|
398
|
+
const worstCase = results.reduce((worst, r) => r.ratioTrim < worst.ratioTrim ? r : worst);
|
|
399
|
+
|
|
387
400
|
console.log(`总测试数: ${results.length}`);
|
|
388
|
-
console.log(
|
|
389
|
-
console.log(
|
|
390
|
-
console.log(
|
|
391
|
-
|
|
401
|
+
console.log(`平均压缩率(不 trim): ${avgRatio.toFixed(2)}%`);
|
|
402
|
+
console.log(`平均压缩率(trim): ${avgRatioTrim.toFixed(2)}%`);
|
|
403
|
+
console.log(`总节省: ${formatBytes(totalDiff)}`);
|
|
404
|
+
console.log(`最佳压缩: ${bestCase.name} (trim ${bestCase.ratioTrim}%)`);
|
|
405
|
+
console.log(`最差压缩: ${worstCase.name} (trim ${worstCase.ratioTrim}%)`);
|
|
406
|
+
|
|
392
407
|
console.log('\n详细结果:');
|
|
393
|
-
console.log('-'.repeat(
|
|
394
|
-
console.log(
|
|
395
|
-
|
|
408
|
+
console.log('-'.repeat(100));
|
|
409
|
+
console.log(
|
|
410
|
+
`${'测试名称'.padEnd(34)} ${'数量'.padStart(6)}` +
|
|
411
|
+
`${'原始'.padStart(12)} ${'不 trim'.padStart(12)} ${'压缩率'.padStart(7)}` +
|
|
412
|
+
`${'trim'.padStart(12)} ${'压缩率'.padStart(7)} ${'差值'.padStart(12)}`
|
|
413
|
+
);
|
|
414
|
+
console.log('-'.repeat(100));
|
|
396
415
|
for (const r of results) {
|
|
397
|
-
|
|
416
|
+
const diffStr = r.diff > 0 ? `-${formatBytes(r.diff)}` : r.diff === 0 ? '—' : `+${formatBytes(-r.diff)}`;
|
|
417
|
+
console.log(
|
|
418
|
+
`${r.name.padEnd(34)} ${r.count.toString().padStart(6)}` +
|
|
419
|
+
`${formatBytes(r.originalSize).padStart(12)}` +
|
|
420
|
+
`${formatBytes(r.compressedSize).padStart(12)} ${r.ratio.toString().padStart(6)}%` +
|
|
421
|
+
`${formatBytes(r.compressedTrimSize).padStart(12)} ${r.ratioTrim.toString().padStart(6)}%` +
|
|
422
|
+
`${diffStr.padStart(12)}`
|
|
423
|
+
);
|
|
398
424
|
}
|
|
399
425
|
|
|
400
426
|
console.log('\n结论:');
|