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

การดำเนินการแบบไดนามิก เป็นฟีเจอร์ใน Bazel ตั้งแต่เวอร์ชัน 0.21, ซึ่งจะเริ่มการดำเนินการในเครื่องและระยะไกลของการดำเนินการเดียวกันแบบขนาน โดยใช้เอาต์พุตจาก 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 จะตั้งค่าเริ่มต้นสำหรับ Branch ในเครื่องของการดำเนินการแบบไดนามิกให้ลองใช้ Worker หรือการดำเนินการแบบแซนด์บ็อกซ์ตามลำดับ การส่ง --dynamic_local_strategy=Javac=worker จะลบล้างค่าเริ่มต้นสำหรับตัวย่อ Javac เท่านั้น เวอร์ชันระยะไกลจะทำงานในลักษณะเดียวกัน คุณระบุแฟล็กทั้ง 2 รายการได้หลายครั้ง หากดำเนินการในเครื่องไม่ได้ ระบบจะดำเนินการระยะไกลตามปกติ และในทางกลับกัน

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

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

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

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

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

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

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

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

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

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

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

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

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

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

การแก้ปัญหา

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

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