การย่อและบีบอัด: รูปแบบไฟล์ไบนารีที่ปรับแต่งได้ของเรา

คิดถึงการพัฒนาประสิทธิภาพและคุณสมบัติการレンเดอร์ที่เราได้นำมาสู่ ROBLOX ในปีที่ผ่านมา หนึ่งในนั้นคือชิ้นส่วนน้ำหนักเบา, คลัสเตอร์ที่รวดเร็ว, การตรวจจับการชนที่มีประสิทธิภาพ, และระบบแสงสว่างแบบไดนามิก การปรับปรุงเหล่านี้ได้ทำลายขีดจำกัดที่เคยมีมา – ทั้งจำนวนชิ้นส่วน, การจำลองฟิสิกส์, และความยืดหยุ่นทางด้านการออกแบบ – ที่ผู้สร้างเคยเผชิญ และเปิดประตูสู่โลกแห่งความเป็นไปได้ที่ไม่มีที่สิ้นสุด พวกมันยังได้เปิดเผยขีดจำกัดใหม่ ๆ อีกด้วย เมื่อผู้สร้างได้ผลักดันขอบเขตให้ไกลออกไปมากกว่าที่เคยเป็นมา ในบทความนี้ เราจะอธิบายถึงวิธีการที่เราได้ลดขนาดไฟล์ของสถานที่ใน ROBLOX ลงได้ประมาณ 100 เท่า และลดเวลาในการโหลด/บันทึกได้ 5-10 เท่า
ลองนึกถึงชิ้นส่วนที่มีน้ำหนักเบาเป็นพิเศษ ฟีเจอร์นี้ซึ่งตอนนี้ใช้ได้กับชิ้นส่วน ROBLOX ทั้งหมด (ไม่ใช่แค่รูปร่างและวัสดุที่เลือกเท่านั้น) ช่วยให้คุณสามารถสร้างสถานที่ใน ROBLOX ที่มีอิฐนับหมื่นชิ้น และยังสามารถทำงานได้ทั้งบนเดสก์ท็อปและอุปกรณ์มือถือ อย่างไรก็ตาม สถานที่ที่มีชิ้นส่วนนับหมื่นชิ้นอาจส่งผลให้ไฟล์มีขนาดใหญ่มาก สถานที่ทดสอบของเรา ซึ่งเราจะอ้างอิงตลอดบทความนี้ มีชิ้นส่วนทั้งหมด 50,000 ชิ้น และมีน้ำหนักถึง 230 เมกะไบต์ ซึ่งใหญ่พอที่จะส่งผลกระทบต่อผู้สร้างในหลายๆ ด้าน: การเรนเดอร์, การบันทึก/โหลด, การเผยแพร่, การโหลดสถานที่จากเซิร์ฟเวอร์ และอื่นๆ อีกมากมาย
เราได้ตัดสินใจว่าถึงเวลาที่เหมาะสมในการจัดการกับขนาดไฟล์ของผลงานใน ROBLOX แล้ว – ทั้งเพื่อปรับปรุงประสบการณ์ของผู้ใช้และสนับสนุนการพัฒนาโครงการที่ยังไม่ได้ประกาศอย่างเป็นทางการ เพื่อจุดประสงค์นี้ เรากำลังจะเริ่มทดสอบรูปแบบไฟล์ใหม่ในเร็ว ๆ นี้ ซึ่งจะบันทึกข้อมูล ROBLOX ในรูปแบบไบนารีแทนที่จะเป็น XML การเปลี่ยนแปลงนี้จะไม่มีผลกระทบต่อผู้ใช้โดยตรง แต่จะลดเวลาที่ผู้สร้างผลงานต้องใช้ในการรอคอยลงเมื่อเวลาผ่านไป เราจะค่อยๆ เปิดตัววิธีการใหม่ในการบันทึกข้อมูล ROBLOX อย่างช้าๆ โดยเริ่มจากไฟล์ชั่วคราวที่สร้างขึ้นสำหรับเซสชัน "เล่นคนเดียว" และ "เริ่มเซิร์ฟเวอร์" ใน ROBLOX Studio และในที่สุดจะนำไปใช้กับการจัดเก็บข้อมูลในเซิร์ฟเวอร์ Personal Build รวมถึงการอัปโหลดและการบันทึกในเครื่อง

เอาของเก่าออกไป
ขนาดไฟล์มีความสำคัญ มันส่งผลต่อเวลาที่ใช้ในการบันทึกและโหลดไฟล์ในเครื่อง รวมถึงการเผยแพร่และโหลดเนื้อหาจาก ROBLOX.com นอกจากนี้ยังมีข้อจำกัดเรื่องขนาดไฟล์สำหรับสิ่งที่สามารถเผยแพร่ไปยัง ROBLOX.com (ผู้สร้างได้พบวิธีแก้ไขโดยเขียนสคริปต์เพื่อสร้างชิ้นส่วนเพิ่มเติมหลังจากที่เกมได้โหลดแล้ว)
ROBLOX ได้เก็บข้อมูลตำแหน่งในรูปแบบ XML มาเป็นเวลานานแล้ว นี่คือรูปแบบที่ใช้งานง่ายและมีโครงสร้างแบบลำดับชั้น โดยแต่ละวัตถุจะมีคุณสมบัติ และแต่ละคุณสมบัติจะมีค่า และทุกอย่างจะรวมกันเป็นต้นไม้ของข้อมูลที่สวยงาม อย่างไรก็ตาม รูปแบบนี้ไม่สามารถขยายได้ไม่มีที่สิ้นสุด สาเหตุหลักคือต้องใช้เวลาในการแปลงข้อมูลที่สามารถอ่านได้จากหน่วยความจำให้เป็นสตริง (เช่น เมื่อบันทึก) และมีความซ้ำซ้อนของข้อมูลอย่างมาก ชิ้นส่วนสองชิ้นที่มีความเหมือนกันเกือบทั้งหมดจะถูกเก็บไว้เป็นก้อน XML แยกกันทั้งหมด เมื่อบันทึกเป็น XML สถานที่ทดสอบของเราที่มีชิ้นส่วน 50,000 ชิ้นและมีขนาดไฟล์ 230 เมกะไบต์ จะใช้เวลาบันทึก 23 วินาที และใช้เวลาโหลด 37 วินาที แม้ว่าจะมีประโยชน์ เช่น สามารถอ่านได้โดยมนุษย์ (มีประโยชน์สำหรับการแก้ไขข้อผิดพลาด) และรองรับการทำงานย้อนหลัง/ไปข้างหน้า (มีประโยชน์ในสภาพแวดล้อมที่ ROBLOX Studio และ ROBLOX Player ไม่ได้อยู่ในเวอร์ชันที่ตรงกันเสมอ) แต่เรากำลังก้าวออกจากรูปแบบนี้
เราได้พิจารณาปรับปรุงตัวแยกวิเคราะห์ XML ของเรา แต่ทราบดีว่าประโยชน์ที่ได้รับจะมีจำกัด เราจึงตัดสินใจที่จะทำครั้งใหญ่ด้วยการปรับเปลี่ยนรูปแบบที่เราใช้บันทึกข้อมูล ROBLOX อย่างสิ้นเชิง
ต้อนรับสิ่งใหม่
โดยการบันทึกผลงานสร้างสรรค์ใน ROBLOX เป็นรูปแบบไบนารี เราสามารถกำจัดข้อมูลอ้างอิงที่ซ้ำซ้อนเกี่ยวกับคุณสมบัติต่าง ๆ ได้ ซึ่งเพียงแค่นี้ก็ทำให้ขนาดไฟล์ลดลงถึง 10 เท่า
หนึ่งในทางเลือกของรูปแบบ XML ที่มีข้อความหนาแน่นคือรูปแบบไบนารี มีความแตกต่างอย่างชัดเจนระหว่างทั้งสองรูปแบบ
- ไบนารีไม่สามารถอ่านได้โดยมนุษย์ อย่างไรก็ตาม ข้อมูลไบนารีมีความคล้ายคลึงกับการแสดงผลในหน่วยความจำมาก ซึ่งหมายความว่าเราสามารถนำวัตถุที่อยู่ในหน่วยความจำมาเขียนเป็นสตรีมของไบต์ได้อย่างง่ายดาย (และในทางกลับกัน)
- แทนที่จะใช้ลำดับชั้นของวัตถุแต่ละอันที่มีคุณสมบัติทั้งหมดประมาณ 30 รายการและค่าของมัน ROBLOX จะเก็บข้อมูลเป็นกลุ่ม (เช่น สำหรับแต่ละคุณสมบัติ เราจะบันทึกค่าสำหรับวัตถุทั้งหมดในที่เดียวกัน) เพื่อลดการซ้ำซ้อน วิธีนี้ยังช่วยให้ข้ามการโหลดข้อมูลที่ล้าสมัยได้ง่ายขึ้น ซึ่งอาจเกิดขึ้นได้หากเราลบคุณสมบัติของชิ้นส่วนบางอย่างในอนาคต เราจึงยังคงได้รับประโยชน์จากความเข้ากันได้ทั้งแบบย้อนหลังและแบบไปข้างหน้า
โดยการบันทึกการสร้าง ROBLOX ในรูปแบบไบนารี เราสามารถกำจัดข้อมูลอ้างอิงที่ซ้ำซ้อนกับคุณสมบัติ (ซึ่งผู้ใช้ไม่สามารถเพิ่ม/ลบได้และมักจะเป็นแบบคงที่) และลดขนาดไฟล์ลงได้ประมาณ 10 เท่า อย่างไรก็ตาม มันไม่ได้ง่ายเหมือนการกดสวิตช์วิเศษ เราได้สร้างวิธีการบันทึกค่าคุณสมบัติ (จำนวนเต็ม) ในแบบที่ทั้งรวดเร็วและบีบอัดได้
แปลงค่าทรัพย์สินเพื่อความเร็วและการบีบอัด
เริ่มต้นด้วยการแยกค่าจำนวนเต็มของมูลค่าทรัพย์สินออกเป็นสี่ไบต์ ค่าสูงสุดสำหรับแต่ละไบต์คือ 2^8-1 (หรือ 255) ค่าเจ็ดจะมีลักษณะดังนี้:
0 | 0 | 0 | 7 |
และค่า 258 จะมีลักษณะดังนี้:
0 | 0 | 1 | 2 |
แทนที่จะเก็บค่าแต่ละค่าตามแถว โค้ดของเราจะเก็บค่าตามคอลัมน์ เนื่องจากค่าส่วนใหญ่ใน ROBLOX มีขนาดเล็ก เราจึงได้ค่าศูนย์จำนวนมากซ้อนกัน ความซ้ำซ้อนแบบนี้เหมาะสำหรับการบีบอัดข้อมูล
ตัวอย่างเช่น สมมติว่าเราต้องการเขียนจำนวนเต็มต่อไปนี้ลงในไฟล์: 1, 5, 4, 258 วิธีที่ง่ายที่สุดคือเขียนไบต์ของพวกมันตามลำดับ เช่นนี้:
0 | 0 | 0 | 1 | 0 | 0 | 0 | 5 | 0 | 0 | 0 | 4 | 0 | 0 | 1 | 2 |
แต่เมื่อเราจัดเรียงใหม่ตามคอลัมน์ พวกมันจะถูกเขียนเป็น:
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 5 | 4 | 2 |
การบีบอัดนี้ทำได้มีประสิทธิภาพมากกว่าเนื่องจากมีเลขศูนย์ซ้ำกันจำนวนมาก
ตัวเลขติดลบทำให้เทคนิคนี้ใช้งานได้ยากขึ้น ตัวเลขติดลบไม่ได้พบบ่อยนัก แต่สามารถเกิดขึ้นได้ในข้อมูลของ ROBLOX ตัวอย่างเช่น เมื่อมีการใช้ตัวเลขติดลบเพื่อชดเชยองค์ประกอบ GUI หลังจากดำเนินการทางคณิตศาสตร์ที่เรียกว่าการเติมเลขฐานสองสอง (2^32 + (-7)) ตัวเลขติดลบเจ็ดจะปรากฏเป็นดังนี้:
255 | 255 | 255 | 249 |
ตัวเลขที่ไม่เป็นศูนย์ทั้งหมดนี้รบกวนเป้าหมายของเรา: กระแสไบต์ที่สามารถบีบอัดได้สูงซึ่งประกอบด้วยเลขศูนย์ เราได้ออกแบบกลเม็ดที่สองเพื่อแปลงจำนวนเต็มลบให้เป็นจำนวนเต็มบวกขนาดเล็ก ทุกครั้งที่มีค่ามากกว่าหรือเท่ากับ 0 เราจะนำค่าดังกล่าวไปคำนวณตามสูตรนี้:
2 x nเมื่อใดก็ตามที่ตัวเลขมีค่าน้อยกว่า 0 เราจะถือว่า:
2 x |n| - 1นี่หมายความว่าค่า 7 จะถูกแทนด้วย 14 (2 x 7) ค่า -7 จะถูกแทนด้วย 13 (2 x |7| - 1) เมื่อเรานำตัวเลขเหล่านี้มาเรียงซ้อนกัน ตัวเลขศูนย์จะสะสมกัน ทำให้เราได้ไฟล์ที่สามารถบีบอัดได้มาก
0 | 0 | 0 | 14 |
0 | 0 | 0 | 13 |
การแปลงและการคำนวณทั้งหมดนี้เกิดขึ้นด้วยต้นทุนที่ต่ำมาก ด้วยเหตุนี้ การจัดการงานนี้ตั้งแต่ต้นจึงมีประสิทธิภาพมากกว่าการพึ่งพาอัลกอริทึมการบีบอัดเพียงอย่างเดียว
หลังจากที่เราได้แยกค่าตัวเลขของมูลค่าทรัพย์สินลงเป็นไบต์แล้ว เราจะทำการบีบอัดข้อมูลผ่าน LZ4 โดยอัตโนมัติ ซึ่งเป็นอัลกอริทึมแบบไม่สูญเสียข้อมูลที่สามารถบีบอัดข้อมูลไบนารีได้อย่างรวดเร็วโดยใช้ทรัพยากรน้อยมาก ขั้นตอนนี้ช่วยลดขนาดไฟล์ลงได้อีกมาก ก่อนหน้านี้ไม่มีการบีบอัดข้อมูลในขั้นตอนนี้ของกระบวนการจัดเก็บข้อมูลเลย – การบีบอัดจะเกิดขึ้นเฉพาะเมื่อมีการสร้างไฟล์และถูกโอนผ่าน HTTP ไปยัง ROBLOX.com โดยใช้การบีบอัดอัตโนมัติของ Gzip เท่านั้น
ทดสอบรูปแบบใหม่
ด้วยรูปแบบไฟล์ไบนารีและการบีบอัดด้วย LZ4 พื้นที่ ROBLOX ขนาด 230 เมกะไบต์ถูกลดลงเหลือไม่ถึง 1 เมกะไบต์ หลังจากการบีบอัดด้วย Gzip ไฟล์จะมีขนาดประมาณ 100 กิโลไบต์ นี่คือผลลัพธ์ของการทดสอบสองสามรายการที่เราดำเนินการภายใน:
ทดสอบ 1
เราสร้างสถานที่ทดสอบด้วยชิ้นส่วน 50,000 ชิ้น, ข้อต่อ ManualWeld 150,000 จุด และวอกเซล 8 ล้านตัว
XML | ไบนารี | |
ขนาด | 230 เมตรเหนือระดับทะเล | 600 กิโลไบต์ |
ขนาด (หลังจาก Gzip) | 3.9 เมกะไบต์ | 93 กิโลไบต์ |
เวลาในการโหลด | 27 วินาที | 3.7 วินาที |
ประหยัดเวลา | 20 วินาที | 0.5 วินาที |
ทดสอบ 2
เราได้ทดสอบ Welcome to the Neighborhood of ROBLOXia ซึ่งเป็นระดับจริงใน ROBLOX ที่สร้างขึ้นด้วย 40,000 ชิ้นส่วน ระดับนี้ไม่มีข้อต่อมากนัก ซึ่งอธิบายความแตกต่างของตัวเลขเมื่อเทียบกับสถานที่ทดสอบ ผู้สร้างที่กล้าหาญหลายคนได้ลบข้อต่อออกจากระดับของพวกเขาผ่านสคริปต์เพื่อลดขนาดไฟล์ แต่สูญเสียการจำลองทางกายภาพไปด้วย นี่ควรจะทำให้ชีวิตของพวกเขาง่ายขึ้น
XML | ไบนารี | |
ขนาด | 112 เมกะไบต์ | 1 เมกะไบต์ |
ขนาด (หลังจาก Gzip) | 3.5 เมกะไบต์ | 700 กิโลไบต์ |
เวลาในการโหลด | 15 วินาที | 2 วินาที |
ประหยัดเวลา | 9 วินาที | 0.2 วินาที |
หมายเหตุ: เวลาในการโหลด/บันทึกมาจากเซิร์ฟเวอร์ เวลาบันทึกใน Studio จะเท่ากัน เวลาในการโหลดใน Studio จะนานกว่าเล็กน้อยเนื่องจากมีการทำงานเพิ่มเติมเพื่อตั้งค่าระบบที่จัดการการยกเลิก/ทำซ้ำ

ในการทดสอบทั้งสองครั้ง มีการปรับปรุงในขนาดไฟล์ลดลงประมาณ 100 เท่า และเวลาในการโหลด/บันทึกลดลง 5-10 เท่า ตามที่ได้กล่าวไว้ตอนต้นของบทความนี้ เราจะทยอยเปิดตัวรูปแบบไฟล์ไบนารีอย่างช้าๆ โดยเริ่มจากไฟล์ชั่วคราวที่สร้างขึ้นเมื่อคุณเริ่มเล่นเซสชันผ่าน ROBLOX Studio โดยใช้ "เล่นคนเดียว" หรือ "เริ่มเซิร์ฟเวอร์" เราได้ดำเนินการตรวจสอบอย่างรอบคอบเพื่อให้แน่ใจว่าสิ่งนี้จะไม่ทำให้ข้อมูลของคุณเสียหาย แต่เราจะขอความคิดเห็นจากคุณหากคุณพบพฤติกรรมที่ผิดปกติ (เช่น ชิ้นส่วนของคุณไม่ปรากฏตามที่ควรจะเป็น หรือในกรณีที่ไม่น่าจะเกิดขึ้น คุณไม่สามารถเปิดไฟล์ได้)
เราจะเริ่มเก็บข้อมูลในรูปแบบไบนารีสำหรับเซิร์ฟเวอร์ Personal Build และข้อมูลที่บันทึกไว้ในเครื่องในที่สุด เมื่อถึงเวลานั้น คุณควรเริ่มเห็นประโยชน์ที่มากขึ้น ความหวังของเราคือคุณจะสามารถปรับตัวเข้ากับกระบวนการสร้าง บันทึก และเผยแพร่ที่ราบรื่นยิ่งขึ้น และเพลิดเพลินกับการปรับปรุงคุณภาพของประสบการณ์ ROBLOX ที่ละเอียดอ่อนแต่มีนัยสำคัญ


