Bun 1.4.3 CompressionStream: ตั้งระดับบีบอัดให้ตรง latency budget
การบีบอัดไม่ใช่ปุ่มยิ่งสูงยิ่งดี response ที่สร้างสดอาจเสีย CPU และเพิ่ม latency มากกว่าขนาดที่ประหยัดได้ Bun 1.4.3 เพิ่มตัวเลือก level ให้ CompressionStream เพื่อกำหนดงบความเร็วกับอัตราบีบอัดตามงานครับ
WHY: แรงอัดต้องเหมาะกับของที่จะส่ง
เหมือนรีดผ้าห่มก่อนส่งพัสดุ แรงอัดสูงสุดทำให้กล่องเล็ก แต่ใช้เวลานาน สำหรับ response แบบ interactive เราอาจเลือก gzip ระดับกลาง ส่วน artifact ที่สร้างครั้งเดียวและดาวน์โหลดหลายครั้งค่อยยอมจ่าย CPU มากขึ้น การตั้งค่าเป็น decision ของ workload ไม่ใช่ค่าศักดิ์สิทธิ์ค่าเดียว
const source = new TextEncoder().encode("forest-data:".repeat(2_000));
async function compress(level: number): Promise<Uint8Array> {
const stream = new Blob([source])
.stream()
.pipeThrough(new CompressionStream("gzip", { level }));
return new Uint8Array(await new Response(stream).arrayBuffer());
}
const packed = await compress(4);
const restored = new Uint8Array(
await new Response(
new Blob([packed]).stream().pipeThrough(new DecompressionStream("gzip")),
).arrayBuffer(),
);
if (packed.length >= source.length) throw new Error("expected repetitive data to shrink");
if (!Bun.deepEquals(restored, source)) throw new Error("round-trip changed bytes");
console.log({ source: source.length, packed: packed.length });
HOW: benchmark ด้วย payload จริง
ระดับที่รองรับขึ้นกับ format: gzip/deflate ใช้ช่วง 0–9, Brotli 0–11 และ zstd 1–22 ตาม release note ค่าเกินช่วงจะ throw RangeError ส่วนการไม่ส่ง level รักษา default เดิม การเทียบควรวัดทั้ง p50/p95 latency, CPU time และขนาด output ด้วยข้อมูลจริง เพราะ JSON ซ้ำมากกับภาพที่บีบอัดมาแล้วให้ผลต่างกันมาก
อย่าบีบอัด secret กับ input ที่ผู้โจมตีควบคุมใน stream เดียวกันโดยไม่วิเคราะห์ compression side channel และอย่าบีบอัดซ้ำไฟล์ที่ format ทำ compression อยู่แล้ว ค่า level ไม่แก้ปัญหา memory backpressure; pipeline ยังต้องจัดการ cancellation และขีดจำกัดขนาด input
Recap
- เลือก level จาก latency และ CPU budget ไม่ใช่ขนาดอย่างเดียว
- วัดด้วย payload จริงและดู p95
- ทดสอบ decompress round-trip
- ไม่บีบอัด format ที่บีบอัดอยู่แล้วซ้ำโดยไม่วัด
- แยก secret ออกจาก input ที่ผู้โจมตีควบคุม