ผมเปลี่ยนจาก JSON มาใช้รูปแบบ Binary แบบกำหนดเองใน PHP

เราจำเป็นต้องจัดเก็บ rich text สำหรับเว็บและแอปมือถือ

เป็นเวลาหลายปีที่เราใช้ HTML เพียวๆ ในฐานข้อมูล ต่อมาเราได้เปลี่ยนไปใช้ JSON เพื่อแยกส่วนการแก้ไขออกจากส่วนการพิมพ์

JSON กลายเป็นปัญหาเมื่อข้อมูลของเราเพิ่มมากขึ้น การจะเปลี่ยนลิงก์เพียงลิงก์เดียว เราต้องทำการ parse, rebuild และ stringify อาร์เรย์ทั้งหมด กระบวนการนี้ทั้งช้าและไม่มีประสิทธิภาพ

ผมจึงตัดสินใจสร้างรูปแบบ binary แบบกำหนดเอง (custom binary format) โดยใช้ PHP

นี่คือเหตุผลที่ผมตัดสินใจเปลี่ยน:

  • ความเร็ว: การ parse และการค้นหาทำได้เร็วขึ้นมาก
  • การควบคุม: ผมสามารถจัดการกับ byte เฉพาะเจาะจงได้โดยไม่ต้องโหลดข้อมูลทั้งหมดลงในหน่วยความจำ
  • โครงสร้าง: ผมเปลี่ยนจากโครงสร้างแบบต้นไม้ซ้อนกัน (nested tree) มาเป็นรายการขององค์ประกอบแบบเรียบ (flat list of elements)

งาน rich text ส่วนใหญ่ไม่จำเป็นต้องใช้โครงสร้างต้นไม้ที่ซับซ้อน บ่อยครั้งที่คุณแค่ต้องการค้นหาข้อความหรือแท็กที่เฉพาะเจาะจง โครงสร้างแบบ flat ขององค์ประกอบต่างๆ พร้อมกับต้นไม้ของ offset แบบง่ายๆ นั้นทำงานได้ดีกว่า

PHP ไม่ใช่ภาษา low-level และไม่ได้ถูกปรับแต่งมาเพื่อการจัดการ byte เหมือนกับ Zig หรือ C อย่างไรก็ตาม PHP มีเครื่องมือที่เหมาะสม:

  • pack() เปลี่ยนตัวเลขหรือสตริงให้เป็น raw bytes
  • unpack() เปลี่ยน byte เหล่านั้นกลับมาเป็นข้อมูลที่ใช้งานได้

ผมเลิกใช้ฟังก์ชัน multibyte string แต่เปลี่ยนมาอ่าน byte เป็นส่วนๆ (chunks) แทน ตัวอย่างเช่น unsigned 64-bit integer จะต้องใช้ 8 bytes พอดี

ผลลัพธ์หลังจากรัน 10,000 รอบ:

การเข้ารหัส JSON แบบเก่า: 2.18s การถอดรหัส JSON แบบเก่า: 0.86s การเข้ารหัส Binary แบบใหม่: 1.19s การถอดรหัส Binary แบบใหม่: 0.67s

รูปแบบ binary นั้นเร็วกว่า แต่ก็มีขนาดใหญ่กว่าด้วย โดยมีขนาดเป็น 2 เท่าของ JSON และ 3 เท่าของ HTML แต่เนื่องจากเราใช้การเรนเดอร์ฝั่งเซิร์ฟเวอร์ (server-side rendering) เรื่องนี้จึงไม่ใช่ปัญหาสำหรับเรา

หากคุณจะสร้างรูปแบบแบบกำหนดเอง ให้ทำตามกฎข้อหนึ่งคือ: เขียนข้อกำหนด (specification) ขึ้นมา จงทำเอกสารประกอบรูปแบบของคุณให้ชัดเจน มิฉะนั้นคุณจะต้องเสียใจภายหลัง

ผมใช้เวลาทำงานหนึ่งสัปดาห์ แต่มันคุ้มค่ามาก

แหล่งที่มา: https://dev.to/tomj/i-replaced-json-with-a-custom-binary-format-in-php-mok