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

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

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

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

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

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

คุณใช้ --experimental_dynamic_ignore_local_signals เพื่อให้ Branch ระยะไกลเข้าควบคุมได้เมื่อการหยุดทำงานในเครื่องสิ้นสุดลงเนื่องจากสัญญาณที่กำหนด การทำเช่นนี้ส่วนใหญ่เป็นประโยชน์เมื่อใช้ร่วมกับขีดจำกัดทรัพยากรของผู้ปฏิบัติงาน (ดู --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) แต่จะนำสาเหตุบางประการที่อาจทำให้ทำงานไม่สำเร็จออก