กระรอก Go สีฟ้าเขียวทดลองจัดข้อมูลบนโต๊ะทำงาน โทนสว่างสีมิ้นต์และครีม

Go Serialization 01: สร้าง JSON baseline ที่เปรียบเทียบได้

พี่โชว์Engineering

บทแรกเราจะได้ baseline ที่เชื่อถือได้ครับ เป้าหมายคือให้ทุก format ใช้ข้อมูลเดียวกันและคืนข้อมูลครบ ก่อนเริ่มถามว่าใครเร็วกว่า

เตรียมโปรเจกต์

ดาวน์โหลด โปรเจกต์ Go พร้อม schemas, generated code, tests และผลดิบ แล้วแตกไฟล์ ใช้ Go 1.27 ขึ้นไป เปิด terminal ในโฟลเดอร์ go-api-serialization และรัน go mod download ครั้งแรก ไม่ต้องติดตั้ง compiler ของ schema เพื่อเริ่มเรียน

โค้ดบนหน้านี้เป็นตัวอย่างบางส่วน (fragment) เพื่ออธิบายจุดสำคัญ คำสั่ง shell ตรวจ syntax ส่วน โปรเจกต์เต็มตรวจด้วย go test ./... ใน quality gate ไม่ควรนำ fragment ไปรันเป็นโปรแกรมเดี่ยว

1. เข้าใจข้อมูลที่กำลังวัด

เปิด catalog.go แล้วดู Fixture(n) ซึ่งสร้างสินค้าแบบ deterministic: เรียกด้วยจำนวนเท่าเดิมจะได้ข้อมูลเท่าเดิม ชื่อมีภาษาไทย ราคาใช้หน่วยย่อยจำนวนเต็ม และ tags มีข้อความซ้ำที่ gzip น่าจะบีบได้ดี จึงไม่ควรนำผลขนาดนี้ไปทำนายข้อมูลสุ่มหรือภาพถ่าย

ตัวอย่างบางส่วนของแบบจำลองข้อมูล:

type Product struct {
    ID         int64    `json:"id" msgpack:"id" avro:"id"`
    Name       string   `json:"name" msgpack:"name" avro:"name"`
    PriceCents int64    `json:"price_cents" msgpack:"price_cents" avro:"price_cents"`
    InStock    bool     `json:"in_stock" msgpack:"in_stock" avro:"in_stock"`
    Tags       []string `json:"tags" msgpack:"tags" avro:"tags"`
}

Fixture(1) มี ID 1 ราคา 12500 และ stock เป็น false ชื่อเริ่มด้วย “ต้นไม้ริมหน้าต่าง” เรา normalize nil slices เป็น empty slices เพื่อให้การเปรียบเทียบไม่พังเพราะรูปแบบเก็บค่าเริ่มต้นต่างกัน

2. ตรวจความถูกต้องก่อนจับเวลา

go test -run 'TestRoundTrip/json' -v
go run ./cmd/sizes

ผลที่ตรวจได้: tests ผ่านทั้งข้อมูลว่าง ภาษาไทย emoji และค่า int64 ขอบบน คำสั่ง sizes แสดง CSV ที่มี 15 แถวข้อมูล: 5 รูปแบบ × 3 จำนวน ขนาดเป็น bytes จริง ไม่ใช่จำนวนตัวอักษรไทย

3. วัด JSON baseline

go test -run '^$' -bench 'BenchmarkCodecs/json' -benchmem -benchtime=300ms -count=5

อ่าน ns/op เป็นเวลาต่อ operation, B/op เป็น bytes ที่ allocate และ allocs/op เป็นจำนวน allocation การเตรียม fixtures อยู่นอก loop แต่ validation และการสร้าง Go object อยู่ในงานที่วัด decode จะคืนสินค้าและ tags ทุกชิ้น

อย่าใช้ MB/s ของแต่ละ format เป็นอันดับความเร็ว เพราะตัวหารของแต่ละแถวคือขนาด wire ของ format นั้นเอง ให้เทียบ ns/op สำหรับงานที่ให้ผลเท่ากัน

แบบฝึกหัด

เปลี่ยนชื่อสินค้าเป็นข้อความยาวขึ้นใน Fixture รัน tests แล้วเก็บไฟล์ sizes อีกชุด เปรียบเทียบ raw bytes กับ gzip bytes อธิบายว่าความซ้ำของข้อความทำให้ผลต่างจากข้อความสุ่มอย่างไร จากนั้นคืน fixture ก่อนนำผลไปเทียบกับบทถัดไป

อ่านต่อ