ทำไมรายงานหน้าเว็บถึงไม่ใช่ความจริงทั้งหมด
เวลาเราวัดประสิทธิภาพของโค้ดด้วยเครื่องมืออย่าง csperf หลายคนมักจะตื่นเต้นกับกราฟสีสวยๆ หรือตารางตัวเลขบนหน้าเว็บ (HTML Report) ที่มันสร้างออกมาให้เราดูทันที เรามักจะเชื่อตัวเลขเหล่านั้นทันทีโดยไม่ได้สงสัยอะไร เพราะมันดูอ่านง่ายและสรุปผลมาให้เสร็จสรรพ แต่ในความเป็นจริงแล้ว หน้าเว็บเหล่านั้นเป็นเพียง Wrapper (กรอบที่หุ้มข้อมูลไว้เพื่อให้อ่านง่าย) ที่ถูกสร้างขึ้นมาเพื่อแสดงผลเท่านั้น
หัวใจสำคัญจริงๆ ของการวัดประสิทธิภาพไม่ได้อยู่ที่หน้าเว็บที่ตาเราเห็น แต่อยู่ที่ไฟล์ JSON (รูปแบบไฟล์ที่เก็บข้อมูลเป็นคู่คีย์กับค่า ซึ่งโปรแกรมอ่านได้ง่าย) ที่เครื่องมือสร้างขึ้นมาต่างหาก ไฟล์นี้เปรียบเสมือนสมุดบันทึกเล่มใหญ่ที่เก็บทุกอย่างเอาไว้ ตั้งแต่ค่าตัวเลขดิบ เวลาที่เริ่มทำงาน ไปจนถึงรายละเอียดของเครื่องคอมพิวเตอร์ที่ใช้ทดสอบ หากเรามองข้ามไฟล์นี้ไป เราก็จะพลาดข้อมูลสำคัญที่จะใช้ยืนยันว่าผลลัพธ์ของเรานั้นน่าเชื่อถือแค่ไหน
ถ้าคุณอยากเติบโตเป็นโปรแกรมเมอร์ที่ทำงานกับประสิทธิภาพได้จริง คุณต้องเลิกดูแค่ตารางสวยๆ แล้วหันมาฝึกอ่านไฟล์ข้อมูลดิบเหล่านี้ให้เป็น เพราะการที่คุณจะบอกว่าโปรแกรมของคุณเร็วขึ้นหรือช้าลงได้ คุณต้องมีหลักฐานที่ตรวจสอบได้จริง ไม่ใช่แค่ภาพหน้าจอที่ใครจะทำขึ้นมาหลอกกันก็ได้ การเข้าใจไฟล์ JSON นี้คือด่านแรกของการเปลี่ยนจากมือใหม่ที่ใช้เครื่องมือเป็น ไปสู่มืออาชีพที่เข้าใจกลไกการทำงานของมัน
รู้จักกับ csperf และการสร้างไฟล์ข้อมูลดิบ
ก่อนที่เราจะไปเจาะลึกกัน เราต้องรู้วิธีสร้างไฟล์ JSON นี้ขึ้นมาก่อน ถ้าคุณยังไม่ได้ติดตั้งเครื่องมือ ให้เปิด Terminal (หน้าจอสั่งงานด้วยพิมพ์คำสั่ง) แล้วพิมพ์คำสั่ง pip install csperf เพื่อติดตั้งให้เรียบร้อยเสียก่อน เมื่อติดตั้งแล้ว เราจะลองรันคำสั่งเพื่อวัดประสิทธิภาพของโค้ดตัวอย่างในเครื่องของเราเอง โดยเน้นไปที่การทำงานของ CPU เป็นหลัก
การวัดประสิทธิภาพที่ดีต้องไม่ทำแค่ครั้งเดียวแล้วจบไป เพราะสภาพแวดล้อมของคอมพิวเตอร์แต่ละจังหวะอาจไม่เหมือนกัน เราจึงต้องมีการทำ Warm-up (การรันโค้ดทิ้งไว้เพื่อให้ระบบพร้อมทำงาน) เพื่อให้แคชและส่วนประกอบต่างๆ ร้อนพร้อมทำงานก่อนที่จะเริ่มวัดค่าจริงๆ การตั้งค่า --repeat-runs 5 จะช่วยให้เราได้ค่าเฉลี่ยที่แม่นยำขึ้น และลดความคลาดเคลื่อนที่อาจเกิดขึ้นจากการรันเพียงครั้งเดียว
ลองใช้คำสั่งด้านล่างนี้เพื่อสร้างไฟล์ผลลัพธ์กันดู โดยให้ลองรันบนเครื่องของตัวเองและสังเกตไฟล์ที่เกิดขึ้นในโฟลเดอร์ results ที่เรากำหนดไว้
# รันคำสั่งวัดประสิทธิภาพและเก็บข้อมูลลงไฟล์ JSON
csperf run \
--input examples/cpp/matrix_traversal.cpp \
--backend cpu \
--warmup-runs 1 \
--repeat-runs 5 \
--output results/first.json
คำสั่งนี้แบ่งเป็นส่วนๆ คือ csperf run เพื่อสั่งเริ่มการทำงาน ตามด้วย --input เพื่อระบุไฟล์โค้ดที่เราต้องการวัดผล ส่วน --backend คือการบอกว่าเรากำลังวัดประสิทธิภาพบน CPU และสุดท้ายคือ --output ที่กำหนดชื่อไฟล์เพื่อเก็บข้อมูลดิบเอาไว้ ผลลัพธ์ที่ได้คือไฟล์ first.json ที่บรรจุข้อมูลมหาศาลซึ่งเราจะเอาไปวิเคราะห์กันในหัวข้อถัดไป
สำรวจข้อมูลในไฟล์ JSON
เมื่อคุณเปิดไฟล์ first.json ขึ้นมาด้วยโปรแกรมแก้ไขข้อความ (Text Editor) คุณจะเห็นโครงสร้างข้อมูลที่ดูเหมือนซับซ้อน แต่จริงๆ แล้วมันคือ "คลังข้อมูล" ที่เก็บทุกรายละเอียดไว้ ที่สำคัญที่สุดคือส่วนของ metrics ซึ่งเก็บค่าตัวเลขดิบ เช่น execution_time_ms (เวลาที่ใช้ทำงานหน่วยเป็นมิลลิวินาที) หรือ cache_misses (จำนวนครั้งที่ข้อมูลไม่อยู่ในหน่วยความจำชั่วคราว) ซึ่งเป็นข้อมูลจริงที่ถูกนำไปวาดเป็นกราฟบนหน้าเว็บ
นอกจากตัวเลขแล้ว ในไฟล์ยังมีส่วนของ Metadata (ข้อมูลที่อธิบายรายละเอียดของข้อมูลอีกที) เช่น ชื่อเครื่อง (Hostname) วันเวลาที่ทดสอบ ระบบปฏิบัติการ และรุ่นของ CPU ข้อมูลเหล่านี้สำคัญมากเวลาที่คุณต้องเปรียบเทียบผลลัพธ์ระหว่างเครื่องคอมพิวเตอร์ของคุณกับเพื่อน เพราะถ้าสเปกเครื่องต่างกัน ผลลัพธ์ที่ได้ย่อมเปรียบเทียบกันตรงๆ ไม่ได้ และไฟล์ JSON นี้คือสิ่งเดียวที่ช่วยยืนยันความแตกต่างนั้นได้
ลองใช้คำสั่ง csperf profile เพื่อเปลี่ยนไฟล์ JSON นี้ให้กลายเป็นไฟล์สรุปผลรูปแบบอื่นๆ เช่น HTML หรือ CSV (รูปแบบไฟล์ตาราง) เพื่อดูว่าข้อมูลดิบเหล่านี้ถูกแปลงร่างไปอย่างไร โดยคำสั่งนี้จะอ่านไฟล์ JSON แล้วสร้างไฟล์รายงานที่อ่านง่ายขึ้นมาให้เราทันที
# แปลงไฟล์ JSON เป็นรายงานหน้าเว็บและตารางข้อมูล
csperf profile results/first.json
หลังจากรันคำสั่งนี้ คุณจะพบไฟล์ results/first.html และ results/first.csv เพิ่มขึ้นมาในโฟลเดอร์เดียวกัน ไฟล์ HTML คือสิ่งที่คุณคุ้นเคย ส่วนไฟล์ CSV คือตารางที่เอาไปเปิดในโปรแกรม Excel ได้ง่ายๆ เพื่อนำไปทำกราฟเปรียบเทียบเพิ่มเติมด้วยตัวเอง
การอ่านข้อมูลให้เป็นมืออาชีพด้วยเครื่องมือช่วย
การมานั่งอ่านไฟล์ JSON ยาวๆ ด้วยตาเปล่าอาจทำให้ตาลายได้ มืออาชีพจึงมักใช้เครื่องมืออย่าง jq เข้ามาช่วยในการดึงข้อมูลเฉพาะที่ต้องการออกมา นี่เป็นทักษะสำคัญที่โปรแกรมเมอร์ต้องมี เพราะบางครั้งเราไม่ได้ต้องการรายงานทั้งชุด แต่ต้องการแค่ค่าใดค่าหนึ่งเพื่อเอาไปใส่ในระบบติดตามผลอัตโนมัติ (CI Pipeline)
ตัวอย่างเช่น ถ้าคุณอยากรู้แค่ว่าเวลาในการทำงานทั้งหมดคือเท่าไหร่ คุณสามารถใช้คำสั่ง jq เพื่อดึงค่า execution_time_ms ออกมาโดยไม่ต้องเปิดไฟล์อ่านเอง วิธีนี้จะทำให้คุณทำงานได้เร็วขึ้นมาก โดยเฉพาะเวลาที่คุณต้องจัดการกับไฟล์ผลลัพธ์จำนวนมากจากการรันหลายๆ รอบ การฝึกใช้เครื่องมือเหล่านี้จะทำให้คุณดูเหมือนโปรแกรมเมอร์ที่เข้าใจงานเบื้องหลัง ไม่ใช่แค่ผู้ใช้งานทั่วไป
ลองดูตัวอย่างการใช้คำสั่งดึงค่าเฉพาะเจาะจงออกจากไฟล์ผลลัพธ์กันดู
# ดึงค่าเวลาทำงานทั้งหมดออกมาจากไฟล์ JSON ด้วย jq
jq '.metrics.execution_time_ms' results/first.json
คำสั่ง jq จะทำการอ่านโครงสร้างไฟล์ JSON ตามลำดับชั้นที่คุณระบุไว้ ในที่นี้คือเข้าไปดูในส่วน metrics แล้วเลือกค่า execution_time_ms ออกมาแสดง ผลลัพธ์ที่ได้จะเป็นตัวเลขโดดๆ เช่น 5.1566 ซึ่งเป็นค่าที่คุณสามารถนำไปใช้คำนวณต่อในสคริปต์ของคุณได้ทันทีโดยไม่ต้องเสียเวลาไปกวาดสายตามองหาในไฟล์
ข้อควรระวังที่มือใหม่มักพลาด
ความผิดพลาดที่พบบ่อยที่สุดคือการพึ่งพาแค่หน้าเว็บรายงานผลเพียงอย่างเดียว บางครั้งหน้าเว็บอาจจะค้างหรือแสดงผลข้อมูลเก่าที่ไม่ได้อัปเดต ถ้าคุณไม่ดูไฟล์ JSON คุณจะไม่มีทางรู้เลยว่าตัวเลขนั้นเป็นข้อมูลล่าสุดจริงหรือไม่ หรือเกิดความผิดพลาดในขั้นตอนการประมวลผล (Parsing) หรือไม่ ดังนั้นกฎเหล็กคือ "ให้ดู JSON ก่อนเสมอ" แล้วค่อยดูผลลัพธ์ที่สรุปออกมา
อีกเรื่องที่สำคัญคือการละเลยข้อมูล Hardware Metadata ถ้าคุณทดสอบบนคอมพิวเตอร์ที่ต่างกัน แล้วผลลัพธ์ออกมาไม่เหมือนกัน คุณต้องกลับมาดูไฟล์ JSON ว่า CPU รุ่นเดียวกันไหม หรือใช้ Compiler (โปรแกรมแปลงโค้ดเป็นภาษาเครื่อง) เวอร์ชันเดียวกันหรือเปล่า การมองข้ามรายละเอียดเหล่านี้จะทำให้คุณสรุปผลผิดพลาด และอาจกลายเป็นการแก้ปัญหาที่ปลายเหตุ
สุดท้ายคือเรื่องของความสม่ำเสมอในการรัน หลายคนรันแค่รอบเดียวแล้วสรุปผลทันที ซึ่งไม่ปลอดภัยเลย ข้อมูลที่เชื่อถือได้ต้องผ่านการรันหลายรอบเพื่อให้เห็นค่าเฉลี่ยและค่าความเบี่ยงเบน (Standard Deviation) ถ้าคุณเห็นค่าความเบี่ยงเบนใน JSON สูงมาก แสดงว่าโค้ดของคุณอาจมีปัญหาเรื่องการจัดการทรัพยากรที่ไม่คงที่ ซึ่งเป็นสิ่งที่คุณจะไม่มีวันสังเกตเห็นจากกราฟสรุปเพียงอย่างเดียว
สรุป: การเป็นโปรแกรมเมอร์ที่เน้นหลักฐาน
การเข้าใจไฟล์ JSON ของ csperf ไม่ใช่แค่เรื่องของความรู้วิชาการ แต่มันคือการสร้างนิสัยในการทำงานแบบมีหลักฐานรองรับ (Evidence-based) ในฐานะคนที่กำลังจะเป็นโปรแกรมเมอร์ การที่คุณสามารถอธิบายได้ว่าตัวเลขประสิทธิภาพของคุณมาจากไหน และมีปัจจัยอะไรบ้างที่ส่งผลต่อตัวเลขเหล่านั้น จะทำให้คุณดูน่าเชื่อถือในสายตาเพื่อนร่วมงานและหัวหน้างานอย่างมาก
ลองทำการบ้านคืนนี้ด้วยการรันโค้ดเดิมแต่เปลี่ยนตัวเลือก --backend เป็น llvm แทน แล้วลองเปรียบเทียบไฟล์ JSON ทั้งสองชุดดูว่าค่า cpu_cycles หรือ cache_misses มีความแตกต่างกันอย่างไร การเปรียบเทียบแบบนี้จะช่วยให้คุณเห็นภาพว่าการเลือกเครื่องมือที่ต่างกัน ส่งผลต่อประสิทธิภาพของโปรแกรมอย่างไรบ้าง นี่คือจุดเริ่มต้นของการเป็นวิศวกรซอฟต์แวร์ที่แท้จริง
จำไว้ว่าในโลกของการเขียนโปรแกรม ข้อมูลคือความจริง และไฟล์ JSON นี้คือแหล่งความจริงเพียงหนึ่งเดียวที่คุณมี อย่าปล่อยให้กราฟสีสวยๆ มาบังตาคุณจากการเห็นปัญหาหรือโอกาสในการพัฒนาโค้ดให้ดีขึ้น การฝึกอ่านข้อมูลดิบตั้งแต่วันนี้จะทำให้คุณก้าวไปข้างหน้าได้ไกลกว่าคนอื่นที่ทำได้แค่ใช้งานเครื่องมือตามคำสั่งเพียงอย่างเดียว
ที่มา: Reading csperf JSON: The Real Performance Artifact — DEV Community