วิธีวัดประสิทธิภาพกราฟิกของเบราว์เซอร์

Ilmari Heikkinen

การเปรียบเทียบกราฟิกของเบราว์เซอร์โดยสังเขป: แสดงข้อมูลให้มากที่สุดเท่าที่จะทำได้ขณะที่รักษาอัตราเฟรมให้ลื่นไหล เมื่ออัตราเฟรมลดลง คุณจะทราบได้ว่าคุณวาดได้มากน้อยเพียงใดต่อเฟรม สิ้นสุดโพสต์ หากไม่ ตกลง ฉันจะอธิบายเพิ่มเติม

เวลาตัวอย่าง นี่คือข้อมูลโค้ดเล็กๆ ที่มีฟังก์ชัน tick เปรียบเทียบ ฟังก์ชัน tick เรียกใช้ฟังก์ชัน draw โดยมีโหลดการวาดที่เพิ่มขึ้นจนกระทั่งการวาดใช้เวลานานกว่า 33 มิลลิวินาทีอย่างต่อเนื่อง

var t, previousTime;
var drawLoad = 1;
var slowCount = 0;
var maxSlow = 10;
// Note, you might need to polyfill performance.now and requestAnimationFrame
t = previousTime = performance.now();
var tick = function() {
    var maximumFrameTime = 1000/30; // 30 FPS
    t = performance.now();
    var elapsed = t - previousTime;
    previousTime = t;
    if (elapsed < maximumFrameTime || slowCount < maxSlow) {
        if (elapsed < maximumFrameTime) {
            drawLoad+=10;
        } else {
            slowCount++;
        }
        draw(drawLoad);
        requestAnimationFrame(tick);
    } else {
        // found maximum sustainable load at 30 FPS
        document.getElementById('res').innerHTML = ("could draw "+(drawLoad)+" in " +
            maximumFrameTime + " ms");
    }
};
requestAnimationFrame(tick);

ดูตัวอย่างที่เผยแพร่ได้ที่ jsFiddle

คุณจะเห็นได้ว่าการเปรียบเทียบยังคงแสดงไปเรื่อยๆ จนถึงจุดที่ทำให้ช้าลงได้อย่างไร นี่เป็นวิธีที่ง่ายและดีในการดูว่าคุณวาดเส้นได้ในอัตราเฟรมที่ลื่นไหลมากน้อยเพียงใด นอกจากนี้คุณยังสามารถใส่ฟังก์ชันการวาดของคุณเองลงในตัวอย่างและทำการเปรียบเทียบแบบกำหนดเอง ไชโย!

คำเตือนและข้อผิดพลาดที่พบบ่อยเมื่อเปรียบเทียบกราฟิกของเบราว์เซอร์

ดังนั้น หากตัวอย่างด้านบนเป็นวิธีที่ใช้ได้ผล คุณจะมีวิธีใดบ้างที่ไม่เหมาะสม ปัจจัยที่ทำให้คุณเปรียบเทียบสิ่งที่ไม่เกี่ยวข้องหรือทำให้คุณมีเมตริกประสิทธิภาพแปลกๆ ที่ดูเหมือนจะไม่เกี่ยวข้องกับความแรงของแอป เรายินดีที่คุณถาม นี่คือ 2 สาเหตุที่พบบ่อยที่สุดที่ฉันเคยเห็นมาบนอินเทอร์เน็ต

การวัด FPS สูงสุด: วาดเฟรมทุกเฟรมและวัด FPS ซึ่งจะทำงานได้ไม่ดีนักสำหรับการวัดประสิทธิภาพกราฟิกบน Chrome เนื่องจากการใช้งานกราฟิกที่สำคัญจะถูกซิงค์กับอัตราการรีเฟรชหน้าจอ (ดังนั้น คุณจึงได้รับการอัปเดตหน้าจอสูงสุด 60 ครั้งต่อวินาที) การวัดความเร็วในการวาดน่าจะไม่มีประโยชน์มากนักเพราะระบบการวาดภาพของ Chrome จะใส่คำสั่งวาดลงในบัฟเฟอร์คำสั่งที่จะเรียกใช้งานในการรีเฟรชหน้าจอถัดไป

การใช้ setTimeout เพื่อวัดประสิทธิภาพกราฟิกเป็นแนวคิดที่ไม่ดีอีกอย่างหนึ่ง ระยะเวลาสูงสุดของ setTimeout คือ 4 มิลลิวินาทีในเบราว์เซอร์ ดังนั้นคุณสามารถใช้เวลาได้สูงสุด 250 FPS ก่อนหน้านี้เบราว์เซอร์มีช่วงเวลาขั้นต่ำต่างกัน ดังนั้นคุณอาจพบว่ามีการเปรียบเทียบการวาดพื้นฐานที่ไม่สมบูรณ์มากซึ่งแสดงเบราว์เซอร์ A ที่กำลังทำงานที่ 250 FPS (ช่วงเวลาต่ำสุด 4 มิลลิวินาที) และเบราว์เซอร์ B ที่ทำงานที่ 100 FPS (ช่วงเวลาขั้นต่ำ 10 มิลลิวินาที) เห็นแล้วว่า A เร็วกว่า! ไม่ใช่ อาจเป็นได้ว่า B เรียกใช้โค้ดวาดได้เร็วกว่า A สมมติว่า A ใช้เวลา 3 มิลลิวินาที และ B ใช้เวลา 1 มิลลิวินาที ไม่ส่งผลกระทบต่อ FPS เนื่องจากเวลาวาดต่ำกว่าช่วง setTimeout ขั้นต่ำ และหากเบราว์เซอร์แสดงผลแบบไม่พร้อมกัน การเดิมพันทั้งหมดจะปิดลง อย่าใช้ setTimeout เว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่

วิธีดำเนินการ

วิธีเปรียบเทียบที่ดีกว่าคือการใช้ปริมาณการวาดภาพที่เหมือนจริงและคูณขนาดไปเรื่อยๆ จนกว่าอัตราเฟรมจะเริ่มลดลง ตัวอย่างเช่น หากคุณกำลังเขียนเกมมุมมองจากด้านบนที่มีภูมิประเทศเป็นแผนที่ย่อย ให้ลองวาดแผนที่ย่อยทุกๆ เฟรมแล้วดูว่าเล่นที่ 60 FPS หรือไม่ หากใช่ ให้เพิ่มภาระงาน (วาดแผนที่ย่อย 2 ครั้งในทุกๆ เฟรมโดยแสดงให้เห็นอย่างชัดเจนระหว่างเฟรม) เพิ่มไปเรื่อยๆ จนกว่า FPS จะลดลงเป็นระดับที่เสถียรใหม่ ตอนนี้คุณก็รู้จำนวนเลเยอร์ของแผนที่ย่อยที่คุณสามารถวาดได้ต่อเฟรมแล้ว

แอปพลิเคชันกราฟิกแต่ละแอปพลิเคชันมีความต้องการแตกต่างกัน คุณจึงควรเขียนการเปรียบเทียบโดยคำนึงถึงเรื่องนี้ด้วย วัดฟีเจอร์กราฟิกที่คุณใช้ในแอป เมื่อคุณพบสถานการณ์ที่ทำงานได้ช้า ให้ลองลดขนาดให้เหลือน้อยที่สุดของโค้ดที่ทำให้เกิดปัญหาซ้ำ (และส่งรายงานข้อบกพร่องที่ new.crbug.com หากควรจะดำเนินการเร็วกว่า)

หากต้องการดูวิธีเขียนโค้ดกราฟิกของเว็บที่มีประสิทธิภาพสูง โปรดดูการบรรยายของ Google I/O 2012 โดย Nat Duca และ Tom Wiltzius จากทีม Chrome GPU