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

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

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

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

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

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

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

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

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

การดำเนินการบางประเภทไม่เหมาะกับการดำเนินการจากระยะไกล การดำเนินการที่เหมาะที่สุด คือการดำเนินการที่เร็วกว่าในเครื่องโดยธรรมชาติ เช่น ผ่าน การใช้ 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 เป็นกลยุทธ์เริ่มต้นสำหรับตัวย่อทั้งหมด ซึ่งมักจะทำให้เกิดปัญหาประเภทนี้

ประสิทธิภาพ

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

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

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

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

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

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

การแก้ปัญหา

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

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