การดำเนินการแบบไดนามิก

รายงานปัญหา ดูแหล่งที่มา

การดำเนินการแบบไดนามิกเป็นฟีเจอร์ใน Bazel ที่การดำเนินการเดียวกันภายในและระยะไกลจะเริ่มต้นพร้อมกัน โดยใช้เอาต์พุตจาก Branch แรกที่เสร็จสิ้น แล้วยกเลิกอีก Branch ซึ่งรวมความสามารถในการดำเนินการและ/หรือแคชที่ใช้ร่วมกันขนาดใหญ่ของระบบบิลด์ระยะไกลกับเวลาในการตอบสนองต่ำของการปฏิบัติการภายใน ทำให้งานสร้างที่สะอาดและสมบูรณ์แบบโดยรวมมีข้อดีทั้ง 2 อย่าง

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

กำลังเปิดใช้การดำเนินการแบบไดนามิกใช่ไหม

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

หากต้องการเปิดใช้โมดูลการดำเนินการแบบไดนามิก ให้ส่งแฟล็ก --internal_spawn_scheduler ไปยัง Bazel การดำเนินการนี้จะเพิ่มกลยุทธ์การดำเนินการใหม่ที่ชื่อว่า dynamic ตอนนี้คุณใช้ตัวแปรนี้เป็นกลยุทธ์สําหรับการช่วยจำที่ต้องการเรียกใช้แบบไดนามิก เช่น --strategy=Javac=dynamic ได้แล้ว โปรดดูส่วนถัดไปสำหรับวิธีเลือกความทรงจำที่จะเปิดใช้การดำเนินการแบบไดนามิก

สำหรับการช่วยจำที่ใช้กลยุทธ์แบบไดนามิก ระบบจะนำกลยุทธ์การดำเนินการระยะไกลมาจากแฟล็ก --dynamic_remote_strategy และกลยุทธ์ในพื้นที่จากแฟล็ก --dynamic_local_strategy การส่ง --dynamic_local_strategy=worker,sandboxed จะกำหนดค่าเริ่มต้นสำหรับสาขาการดำเนินการแบบไดนามิกในท้องถิ่นเพื่อลองใช้กับผู้ปฏิบัติงานหรือการดำเนินการแบบแซนด์บ็อกซ์ตามลำดับนั้น การส่งผ่าน --dynamic_local_strategy=Javac=worker จะลบล้างค่าเริ่มต้นของระบบช่วยจำ Javac เท่านั้น เวอร์ชันรีโมตจะทำงานในลักษณะเดียวกัน คุณสามารถระบุแฟล็กทั้งสองได้ หลายครั้ง หากดำเนินการภายในเครื่องไม่ได้ การทำงานก็จะทำงานจากระยะไกลตามปกติ หรือในทางกลับกัน

หากระบบระยะไกลมีแคช แฟล็ก --dynamic_local_execution_delay จะเพิ่มการหน่วงเวลาให้กับการดำเนินการภายในเครื่องเป็นมิลลิวินาทีหลังจากที่ระบบระยะไกลได้ระบุว่ามีการพบแคช การดำเนินการนี้จะหลีกเลี่ยงการเรียกใช้การดำเนินการภายในเมื่อมีแนวโน้มว่าจะพบแคชมากกว่า ค่าเริ่มต้นคือ 1, 000 มิลลิวินาที แต่ควรปรับให้นานกว่าการใช้แคชตามปกติ เวลาจริงจะขึ้นอยู่กับระบบระยะไกล และระยะเวลาเดินทางไปกลับ โดยปกติแล้ว ค่าสำหรับผู้ใช้ทั้งหมดของระบบระยะไกลหนึ่งๆ จะเหมือนกัน เว้นแต่ผู้ใช้บางรายจะอยู่ไกลพอที่จะเพิ่มเวลาในการตอบสนองแบบไป-กลับ คุณใช้ฟีเจอร์การสร้างโปรไฟล์แบบ Bazel เพื่อดูระยะเวลาที่ Hit แคชทั่วไปใช้เวลาได้

การดำเนินการแบบไดนามิกใช้ได้กับกลยุทธ์ที่แซนด์บ็อกซ์ในเครื่องและผู้ปฏิบัติงานอย่างต่อเนื่อง ผู้ปฏิบัติงานถาวรจะทำงานด้วยแซนด์บ็อกซ์โดยอัตโนมัติเมื่อใช้ร่วมกับการดำเนินการแบบไดนามิก และจะใช้ผู้ปฏิบัติงาน Multiplex ไม่ได้ กลยุทธ์แซนด์บ็อกซ์ในระบบดาร์วินและ Windows อาจทำงานช้า คุณสามารถส่ง --reuse_sandbox_directories เพื่อลดค่าใช้จ่ายในการสร้างแซนด์บ็อกซ์ในระบบเหล่านี้

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

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

สำหรับข้อมูลพื้นฐานเพิ่มเติมเกี่ยวกับวิธีการทำงานของการดำเนินการแบบไดนามิกและการล็อก โปรดดูบล็อกโพสต์ที่ยอดเยี่ยมของ Julio Merino

ฉันควรใช้การดำเนินการแบบไดนามิกเมื่อใด

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

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

ตั้งแต่รุ่น 5.0.0-pre.20210708.4 การสร้างโปรไฟล์ประสิทธิภาพจะมีข้อมูลเกี่ยวกับการดำเนินการของผู้ปฏิบัติงาน รวมถึงเวลาที่ใช้ในการทำตามคำของานหลังจากเสร็จสิ้นการแข่งขันการดำเนินการแบบไดนามิก หากเห็นเทรดของผู้ปฏิบัติงานการดำเนินการแบบไดนามิกใช้เวลาอย่างมากในการรับทรัพยากร หรือใช้เวลานานใน async-worker-finish อาจเป็นเพราะการดำเนินการในเครื่องที่ช้าทำให้เทรดของผู้ปฏิบัติงานล่าช้า

การทำโปรไฟล์ข้อมูลที่มีประสิทธิภาพการดำเนินการแบบไดนามิกต่ำ

ในโปรไฟล์ด้านบน ซึ่งใช้ผู้ปฏิบัติงาน Javac 8 คน เราพบว่าผู้ปฏิบัติงาน Javac จำนวนมากแพ้การแข่งและทำงานในชุดข้อความ async-worker-finish ให้เสร็จสิ้น ปัญหานี้เกิดจากการช่วยจำการทำงานของผู้ปฏิบัติงานซึ่งอาศัยทรัพยากรจำนวนมากจนทำให้ผู้ปฏิบัติงานล่าช้า

การทำโปรไฟล์ข้อมูลด้วยประสิทธิภาพการดำเนินการแบบไดนามิกที่ดีขึ้น

เมื่อเรียกใช้ Javac โดยใช้การดำเนินการแบบไดนามิกเท่านั้น จะมีเพียงประมาณครึ่งหนึ่งของผู้ปฏิบัติงานที่เริ่มต้นแพ้ที่แข่งหลังจากที่เริ่มทำงาน

เราเลิกใช้งานแฟล็ก --experimental_spawn_scheduler ที่แนะนำก่อนหน้านี้แล้ว โดยจะเปิดการดำเนินการแบบไดนามิกและกำหนดให้ dynamic เป็นกลยุทธ์เริ่มต้นสำหรับการช่วยจำทั้งหมด ซึ่งมักจะทำให้เกิดปัญหาประเภทนี้

การแสดง

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

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

--experimental_dynamic_local_load_factor เป็นตัวเลือกการจัดการทรัพยากร ขั้นสูงเวอร์ชันทดลอง ค่านี้มีค่าตั้งแต่ 0 ถึง 1, 0 ในการปิดฟีเจอร์นี้ เมื่อกำหนดค่ามากกว่า 0 แล้ว Bazel จะปรับจำนวนการดำเนินการที่กำหนดเวลาไว้เฉพาะในเครื่องเมื่อมีการดำเนินการหลายรายการที่รอการกำหนด การตั้งค่าเป็น 1 จะทำให้มีการตั้งเวลาการดำเนินการได้มากตามจำนวน CPU ที่ใช้ได้ (ตาม --local_cpu_resources) ค่าที่ต่ำลงจะกำหนดจำนวนการดำเนินการที่ตั้งเวลาให้น้อยลงตามจำนวนการดำเนินการที่เรียกใช้ได้ อาจฟังดูขัดกับความรู้สึก แต่ด้วยระบบระยะไกลที่ดี การดำเนินการภายในจะไม่ช่วยอะไรมากนักเมื่อมีการเรียกใช้การดำเนินการหลายรายการ และจะใช้ CPU ของเครื่องเพื่อจัดการการดำเนินการระยะไกลมากกว่า

--experimental_dynamic_slow_remote_time จะจัดลำดับความสำคัญเริ่มต้นของ Branch ในเครื่องเมื่อ Branch ระยะไกลทำงานเป็นเวลาอย่างน้อยเท่านี้ โดยปกติการดำเนินการที่กำหนดเวลาไว้ล่าสุดจะมีความสำคัญสูงสุด เนื่องจากมีโอกาสมากที่สุดที่จะชนะการแข่งขัน แต่บางครั้งระบบระยะไกลอาจค้างหรือใช้เวลานานกว่าปกติ อาจทำให้บิลด์พัฒนาต่อไปได้ ตัวเลือกนี้ไม่ได้เปิดใช้โดยค่าเริ่มต้น เนื่องจากอาจซ่อนปัญหาเกี่ยวกับระบบระยะไกลซึ่งควรได้รับการแก้ไข อย่าลืมตรวจสอบประสิทธิภาพของระบบระยะไกลหากเปิดใช้ตัวเลือกนี้

สามารถใช้ --experimental_dynamic_ignore_local_signals เพื่อให้สาขาระยะไกลเข้าควบคุมการทำงานเมื่อออกจากระบบที่สร้างขึ้นเนื่องจากสัญญาณที่กำหนด ซึ่งเป็นประโยชน์เมื่อใช้ร่วมกับขีดจำกัดทรัพยากรผู้ปฏิบัติงาน (ดู --experimental_worker_memory_limit_mb, --experimental_worker_sandbox_hardening และ --experimental_sandbox_memory_limit_mb)) ซึ่งกระบวนการของผู้ปฏิบัติงานอาจหยุดทำงานเมื่อใช้ทรัพยากรมากเกินไป

โปรไฟล์การติดตาม JSON มีกราฟที่เกี่ยวข้องกับประสิทธิภาพจำนวนหนึ่งซึ่งช่วยระบุวิธีปรับปรุงการแลกเปลี่ยนประสิทธิภาพและการใช้งานทรัพยากรได้

การแก้ปัญหา

ปัญหาในการดำเนินการกับแบบไดนามิกนั้นอาจมีความซับซ้อนและแก้ไขข้อบกพร่องยาก เนื่องจากปัญหาเกิดขึ้นได้ภายใต้ชุดค่าผสมบางอย่างระหว่างการดำเนินการในเครื่องและระยะไกลเท่านั้น --debug_spawn_scheduler จะเพิ่มเอาต์พุตจากระบบการดำเนินการแบบไดนามิกที่ช่วยแก้ไขข้อบกพร่องได้ นอกจากนี้ คุณยังปรับแฟล็ก --dynamic_local_execution_delay และจำนวนงานระยะไกลเทียบกับงานภายในเพื่อให้ทำให้เกิดปัญหาซ้ำได้ง่ายขึ้น

หากพบปัญหาเกี่ยวกับการดำเนินการแบบไดนามิกโดยใช้กลยุทธ์ standalone ให้ลองเรียกใช้โดยไม่ใช้ --experimental_local_lockfree_output หรือเรียกใช้การดำเนินการในเครื่องโดยใช้แซนด์บ็อกซ์ ซึ่งอาจทำให้บิลด์ของคุณช้าลงเล็กน้อย (ดูด้านบนหากคุณใช้ Mac หรือ Windows) แต่จะนำสาเหตุที่เป็นไปได้บางอย่างที่ทำให้การทำงานล้มเหลวออก