บทความ

หน้า 3D ที่คะแนน PageSpeed ตก เพราะเครื่องวัดไม่มี GPU

บนเครื่องที่มี GPU หน้านี้ลื่นปกติ แต่ในแล็บของ PageSpeed การสร้าง WebGL ด้วยซอฟต์แวร์ใช้เวลาราวหนึ่งวินาที นี่คือวิธีที่เราหาสาเหตุและแก้

แผนภาพเส้นเวลาสองแถว แถวบนคือ main thread ที่มีบล็อกยาวหนึ่งก้อนเป็นการสร้าง WebGL ด้วยซอฟต์แวร์ แถวล่างคือ main thread ที่ว่าง และ Worker ที่รับบล็อกนั้นไปแทน

หน้าแรกของเว็บนี้มีฉาก 3D ที่เขียนด้วย Three.js บนเครื่องของเราซึ่งมี GPU มันลื่นปกติ แต่เมื่อเอาไปวัดใน PageSpeed คะแนนเดสก์ท็อปอยู่ที่ 45 ถึง 63 และ Total Blocking Time อยู่ที่ 0.9 ถึง 3.9 วินาที

ช่องว่างระหว่างสองอย่างนี้คือเรื่องของบทความนี้ เครื่องวัดไม่ได้ผิด มันเป็นเครื่องคนละแบบ และการเข้าใจว่าต่างกันตรงไหนคือทั้งหมดของการแก้

เครื่องวัดไม่ใช่คอมพิวเตอร์ของลูกค้า

ห้องแล็บของ PageSpeed รัน Chrome บนเซิร์ฟเวอร์ที่ไม่มี GPU เมื่อหน้าเว็บขอ WebGL เบราว์เซอร์จึงใช้ตัวเรนเดอร์แบบซอฟต์แวร์ที่ชื่อ SwiftShader แทน มันทำงานได้ แต่ใช้ CPU ล้วน และแค่การสร้าง WebGL2 context ขึ้นมาก็กินเวลาราวหนึ่งวินาทีบน main thread ช่วงนั้นหน้าเว็บกดอะไรไม่ได้ ซึ่งคือสิ่งที่ Total Blocking Time วัดอยู่พอดี

แผนภาพเส้นเวลาเทียบก่อนและหลัง ก่อนแก้ main thread ถูกบล็อกราวหนึ่งวินาทีด้วยการสร้าง WebGL ด้วยซอฟต์แวร์ หลังแก้ main thread ว่าง และ Worker เป็นผู้สร้าง WebGL แทน
ในแล็บที่ไม่มี GPU การสร้าง WebGL context ด้วยซอฟต์แวร์บล็อก main thread ราวหนึ่งวินาที หลังแก้ งานนั้นย้ายไปอยู่ใน Worker

ทางที่ไม่พอ: ถามเบราว์เซอร์ตรง ๆ

ตัวเลือก failIfMajorPerformanceCaveat ของ WebGL ออกแบบมาให้การสร้าง context ล้มเหลวเมื่อเบราว์เซอร์จะต้องใช้ตัวเรนเดอร์ที่ช้า เราลองแล้ว แต่มันจับ SwiftShader ไม่ได้ จึงไม่ช่วยอะไร

ครั้งแรกเราจึงดักตอนสร้าง context แล้วอ่านชื่อตัวเรนเดอร์ ถ้าชื่อบอกว่าเป็นซอฟต์แวร์ก็ส่งค่าว่างกลับไป ให้ฉาก 3D ถอยไปใช้ภาพโปสเตอร์แทน วิธีนี้ติดอยู่ข้อเดียว การจะอ่านชื่อตัวเรนเดอร์ได้ต้องสร้าง context ก่อน และการสร้างนั้นแหละคือหนึ่งวินาทีที่เราอยากเลี่ยง

วิธีที่ได้ผล: ให้คนอื่นไปลองแทน

Web Worker ทำงานนอก main thread และสร้าง OffscreenCanvas ได้ เราจึงให้ Worker เล็ก ๆ ตัวหนึ่งไปสร้าง WebGL2 context บนแคนวาส 1×1 พิกเซล อ่านชื่อตัวเรนเดอร์ แล้วส่งคำตอบกลับมา จริงถ้าเป็นการ์ดจอจริง เท็จถ้าชื่อมี swiftshader, llvmpipe, softpipe หรือ software และว่างเปล่าถ้าบอกไม่ได้ หน้าเว็บไม่ต้องรอหรือจ่ายหนึ่งวินาทีนั้นเลย

สคริปต์ในหัวของหน้าแรกเริ่ม Worker ตั้งแต่ก่อนโหลดโค้ดอื่น และเก็บคำตอบไว้ให้ฉาก 3D มาอ่าน มีสามรายละเอียดที่ทำให้มันใช้ได้จริง

  • ไม่มีคำตอบภายใน 5 วินาทีถือว่าไม่มี GPU เพราะเครื่องที่ไม่มี GPU และกำลังถูกบีบมักตอบช้า การถอยไปใช้ภาพโปสเตอร์ปลอดภัยกว่าการรอ

  • จอที่กว้างไม่ถึง 700 พิกเซลข้ามการตรวจ เพราะมือถือไม่สร้างฉาก 3D อยู่แล้ว

  • Worker ต้องเป็นไฟล์จริง ไม่ใช่ Blob เพราะนโยบาย CSP ของเว็บไม่อนุญาต blob: ใน script-src และเราไม่ขยาย CSP เพื่อความสะดวก ไฟล์นั้นคือ /static/gl-probe.js

แผนผังลำดับ สคริปต์ในหัวหน้าเว็บเริ่ม Worker ซึ่งสร้าง WebGL2 บนแคนวาส 1 คูณ 1 พิกเซลและอ่านชื่อตัวเรนเดอร์ ถ้าเป็นการ์ดจอจริงจึงสร้างฉาก 3D ถ้าเป็นซอฟต์แวร์ ตอบไม่ได้ หรือไม่มีคำตอบใน 5 วินาที ก็ใช้ภาพโปสเตอร์หรือวิดีโอ loop
Worker ตอบก่อนที่ฉาก 3D จะเริ่ม ถ้าเป็นการ์ดจอจริงจึงสร้างฉาก ถ้าไม่ใช่หรือไม่มีคำตอบ ก็ใช้ภาพโปสเตอร์หรือวิดีโอ loop

ผลที่ได้

ก่อนแก้ การวัดบนเดสก์ท็อปได้ 45 ถึง 63 คะแนน และ Total Blocking Time 0.9 ถึง 3.9 วินาที หลังแก้ เมื่อวันที่ 15 ตุลาคม 2569 เรารัน Lighthouse 13.5 สามรอบบนเดสก์ท็อป ได้ 74, 79 และ 83 คะแนน และ Total Blocking Time เป็น 0 มิลลิวินาทีทั้งสามรอบ

แผนภูมิช่วงค่าก่อนและหลังแก้ คะแนนเดสก์ท็อปก่อนแก้ 45 ถึง 63 หลังแก้ 74, 79 และ 83 ส่วน Total Blocking Time ก่อนแก้ 0.9 ถึง 3.9 วินาที หลังแก้ 0 มิลลิวินาทีทั้งสามรอบ
คะแนนเดสก์ท็อปและ Total Blocking Time ก่อนและหลังเพิ่ม Worker ตรวจ GPU ก่อนแก้เป็นช่วงจากบันทึกการวัดของเรา หลังแก้เป็นสามรอบของ Lighthouse

ต้องบอกให้ครบ คะแนนยังไม่ใช่ 100 และยังแกว่งระหว่างรอบ ส่วนที่เหลือมาจากเรื่องอื่น เช่น เวลาที่ภาพหลักขึ้น สิ่งที่หายไปคือการบล็อกหน้าเว็บ ซึ่งเป็นการแก้ที่ต้นเหตุ ไม่ได้แก้ที่ตัวเลข ตัวเลขทั้งหมดนี้เป็นการวัดบนเครื่องของเรา ไม่ใช่ข้อมูลจากผู้ใช้จริง

สิ่งที่เรียนรู้

  • ผลวัดที่ต่ำไม่ได้แปลว่าเว็บช้าเสมอไป ถามก่อนว่าเครื่องวัดต่างจากเครื่องของผู้ใช้ตรงไหน

  • ฉากสำรองต้องออกแบบไว้ตั้งแต่แรก คนที่เครื่องไม่มี GPU ยังเห็นภาพโปสเตอร์หรือวิดีโอ loop ที่ใช้ได้ ไม่ใช่หน้าว่าง

  • บันทึกสิ่งที่ลองแล้วไม่ได้ผลไว้ในไฟล์กฎของโปรเจกต์ คนที่มาทำต่อจะไม่ต้องลองซ้ำ

บทความอื่น

อ่าน 4 นาที

Core Web Vitals อ่านอย่างไร โดยไม่ต้องเป็นโปรแกรมเมอร์

คะแนน PageSpeed เป็นตัวเลขเดียวที่คนมักดู แต่สิ่งที่ควรอ่านคือสามตัววัดกับข้อมูลจากผู้ใช้จริง และเว็บเดียวกันก็ได้คะแนนไม่เท่ากันทุกรอบ

อ่าน 4 นาที

เว็บเทมเพลตกับเว็บออกแบบเอง ต่างกันตรงไหนที่ลูกค้าตรวจเองได้

เทมเพลตไม่ได้แย่ และมีงานที่ควรใช้มัน แต่ความต่างตรวจเองได้ในสิบนาทีด้วยหกข้อ ไม่ต้องเชื่อคำของใคร รวมถึงของเรา

ดูบทความทั้งหมด

ติดต่อContact

อยากได้เว็บไซต์ที่ออกแบบแบบนี้

เล่าโจทย์ให้เราฟัง แล้วเราจะตอบกลับพร้อมขอบเขตงานและแพ็กเกจที่เหมาะกับคุณ