Bazel มีความซับซ้อนและทำสิ่งต่างๆ มากมายในระหว่างการบิลด์ ซึ่งบางอย่างอาจส่งผลต่อประสิทธิภาพการบิลด์ หน้านี้พยายามเชื่อมโยงแนวคิดบางอย่างของ Bazel กับผลกระทบต่อประสิทธิภาพการบิลด์ แม้จะไม่ครอบคลุมทั้งหมด แต่เราได้รวมตัวอย่างวิธีตรวจหาปัญหาด้านประสิทธิภาพการบิลด์ผ่านการแยกเมตริกและสิ่งที่คุณทำได้เพื่อแก้ไขปัญหา เราหวังว่าคุณจะนำแนวคิดเหล่านี้ไปใช้ได้เมื่อตรวจสอบการถดถอยของประสิทธิภาพการบิลด์
บิลด์เปล่าเทียบกับบิลด์แบบเพิ่ม
บิลด์เปล่าคือบิลด์ที่สร้างทุกอย่างตั้งแต่ต้น ส่วนบิลด์แบบเพิ่มจะใช้ซ้ำงานที่ทำเสร็จแล้ว
เราขอแนะนำให้ดูบิลด์เปล่าและบิลด์แบบเพิ่มแยกกัน โดยเฉพาะอย่างยิ่งเมื่อ คุณรวบรวม / รวมเมตริกที่ขึ้นอยู่กับสถานะของ แคชของ Bazel (เช่น เมตริกขนาดคำขอบิลด์ ) นอกจากนี้ บิลด์ทั้ง 2 แบบยังแสดงถึงประสบการณ์ของผู้ใช้ที่แตกต่างกัน บิลด์แบบเพิ่มเกิดขึ้นบ่อยกว่ามากเมื่อนักพัฒนาซอฟต์แวร์ทำซ้ำโค้ด (โดยปกติจะเร็วกว่าเนื่องจากแคชพร้อมใช้งานอยู่แล้ว) เมื่อเทียบกับการเริ่มบิลด์เปล่าตั้งแต่ต้น (ซึ่งใช้เวลานานกว่าเนื่องจากแคชยังไม่พร้อมใช้งาน)
คุณสามารถใช้ฟิลด์ CumulativeMetrics.num_analyses ใน BEP เพื่อจัดประเภทบิลด์ หาก num_analyses <= 1 จะเป็นบิลด์เปล่า ไม่เช่นนั้น เราจะจัดประเภทบิลด์นั้นเป็นบิลด์แบบเพิ่มโดยทั่วไป
ผู้ใช้อาจเปลี่ยนไปใช้แฟล็กหรือเป้าหมายอื่น ซึ่งทำให้เกิดบิลด์เปล่า คำจำกัดความที่เข้มงวดมากขึ้นเกี่ยวกับบิลด์แบบเพิ่มน่าจะอยู่ในรูปแบบของฮิวริสติก เช่น การดูจำนวนแพ็กเกจที่โหลด (PackageMetrics.packages_loaded)
เมตริกบิลด์แบบดีเทอร์มินิสติกเป็นตัวแทนของประสิทธิภาพการบิลด์
การวัดประสิทธิภาพการบิลด์อาจทำได้ยากเนื่องจากเมตริกบางอย่างมีลักษณะที่ไม่แน่นอน (เช่น เวลา CPU ของ Bazel หรือเวลาคิวในคลัสเตอร์ระยะไกล) ดังนั้น การใช้เมตริกแบบดีเทอร์มินิสติกเป็นตัวแทนของปริมาณงานที่ Bazel ทำจึงมีประโยชน์ ซึ่งจะส่งผลต่อประสิทธิภาพของ Bazel
ขนาดคำขอบิลด์อาจส่งผลอย่างมากต่อประสิทธิภาพการบิลด์ บิลด์ขนาดใหญ่อาจแสดงถึงงานที่มากขึ้นในการวิเคราะห์และสร้างกราฟบิลด์ การเติบโตแบบออร์แกนิกของบิลด์เกิดขึ้นตามธรรมชาติเมื่อมีการพัฒนา เนื่องจากมีการเพิ่ม/สร้างการขึ้นต่อกันมากขึ้น จึงมีความซับซ้อนมากขึ้นและใช้ค่าใช้จ่ายในการบิลด์มากขึ้น
เราสามารถแบ่งปัญหานี้ออกเป็นระยะต่างๆ ของการบิลด์ และใช้เมตริกต่อไปนี้เป็นเมตริกตัวแทนสำหรับงานที่ทำในแต่ละระยะ
PackageMetrics.packages_loaded: จำนวนแพ็กเกจที่โหลดสำเร็จ การถดถอยในที่นี้แสดงถึงงานที่ต้องทำมากขึ้นเพื่ออ่านและแยกวิเคราะห์ไฟล์ BUILD เพิ่มเติมแต่ละไฟล์ในระยะการโหลดTargetMetrics.targets_configured: แสดงจำนวนเป้าหมายและแง่มุมที่กำหนดค่าในบิลด์ การถดถอยแสดงถึงงานที่มากขึ้นในการสร้างและข้ามกราฟเป้าหมายที่กำหนดค่า- ซึ่งมักเกิดจากการเพิ่มการขึ้นต่อกันและต้องสร้างกราฟของการปิดทรานซิทีฟ
- ใช้คําสั่ง cquery เพื่อดูว่ามีการเพิ่มการขึ้นต่อกันใหม่ที่ใด
ActionSummary.actions_created: แสดงการดำเนินการที่สร้างขึ้นในบิลด์ และการถดถอยแสดงถึงงานที่มากขึ้นในการสร้างกราฟการดำเนินการ โปรดทราบว่าเมตริกนี้ยังรวมถึงการดำเนินการที่ไม่ได้ใช้ซึ่งอาจไม่ได้ดำเนินการ- ใช้ aquery เพื่อแก้ไขข้อบกพร่องของการถดถอย
เราขอแนะนำให้เริ่มต้นด้วย
--output=summaryก่อนที่จะเจาะลึกลงไปอีกด้วย--skyframe_state
- ใช้ aquery เพื่อแก้ไขข้อบกพร่องของการถดถอย
เราขอแนะนำให้เริ่มต้นด้วย
ActionSummary.actions_executed: จำนวนการดำเนินการที่ดำเนินการ การถดถอยแสดงถึงงานที่มากขึ้นในการดำเนินการเหล่านี้โดยตรง- BEP จะเขียนสถิติการดำเนินการ
ActionDataที่แสดงประเภทการดำเนินการที่ดำเนินการมากที่สุด โดยค่าเริ่มต้น ระบบจะรวบรวมประเภทการดำเนินการ 20 อันดับแรก แต่คุณสามารถส่ง--experimental_record_metrics_for_all_mnemonicsเพื่อรวบรวมข้อมูลนี้สำหรับประเภทการดำเนินการทั้งหมดที่ดำเนินการ - ซึ่งจะช่วยให้คุณทราบว่ามีการดำเนินการประเภทใด (เพิ่มเติม)
- BEP จะเขียนสถิติการดำเนินการ
BuildGraphSummary.outputArtifactCount: จำนวนอาร์ติแฟกต์ที่สร้างขึ้นโดยการดำเนินการที่ดำเนินการ- หากจำนวนการดำเนินการที่ดำเนินการไม่เพิ่มขึ้น แสดงว่ามีการเปลี่ยนแปลงการใช้งานกฎ
เมตริกเหล่านี้ทั้งหมดได้รับผลกระทบจากสถานะของแคชในเครื่อง ดังนั้นคุณจึงต้องตรวจสอบว่าบิลด์ที่คุณแยกเมตริกเหล่านี้ออกมาเป็นบิลด์เปล่า
เราสังเกตเห็นว่าการถดถอยในเมตริกเหล่านี้อาจมาพร้อมกับการถดถอยในเวลาจริง เวลา CPU และการใช้งานหน่วยความจำ
การใช้ทรัพยากรในเครื่อง
Bazel ใช้ทรัพยากรต่างๆ ในเครื่องของคุณ (ทั้งสำหรับการวิเคราะห์กราฟบิลด์และการขับเคลื่อนการดำเนินการ รวมถึงสำหรับการดำเนินการในเครื่อง) ซึ่งอาจส่งผลต่อประสิทธิภาพ / ความพร้อมใช้งานของเครื่องในการดำเนินการบิลด์และงานอื่นๆ
เวลาที่ใช้
เมตริกที่อาจได้รับผลกระทบจากสัญญาณรบกวนมากที่สุด (และอาจแตกต่างกันอย่างมากในแต่ละบิลด์) คือเวลา โดยเฉพาะเวลาจริง เวลา CPU และเวลาของระบบ คุณสามารถ
ใช้ bazel-bench เพื่อรับ
การเปรียบเทียบสำหรับเมตริกเหล่านี้ และใช้ --runs จำนวนมากพอเพื่อเพิ่มความสำคัญทางสถิติของการวัด
เวลาจริง คือเวลาที่ผ่านไปในโลกจริง
- หากเวลาจริง เท่านั้น ที่ถดถอย เราขอแนะนำให้รวบรวม โปรไฟล์การติดตาม JSON และดู ความแตกต่าง ไม่เช่นนั้น การตรวจสอบเมตริกอื่นๆ ที่ถดถอยน่าจะมีประสิทธิภาพมากกว่า เนื่องจากเมตริกเหล่านั้นอาจส่งผลต่อเวลาจริง
เวลา CPU คือเวลาที่ CPU ใช้ในการดำเนินการโค้ดของผู้ใช้
- หากเวลา CPU ถดถอยในคอมมิต 2 รายการของโปรเจ็กต์ เราขอแนะนำให้รวบรวมโปรไฟล์ CPU ของ Starlark นอกจากนี้ คุณควรใช้
--nobuildเพื่อจำกัดบิลด์ไว้ที่ระยะการวิเคราะห์ เนื่องจากเป็นระยะที่มีการทำงานที่ใช้ CPU มากที่สุด
- หากเวลา CPU ถดถอยในคอมมิต 2 รายการของโปรเจ็กต์ เราขอแนะนำให้รวบรวมโปรไฟล์ CPU ของ Starlark นอกจากนี้ คุณควรใช้
เวลาของระบบคือเวลาที่ CPU ใช้ในเคอร์เนล
- หากเวลาของระบบถดถอย มักจะสัมพันธ์กับการรับ/ส่งข้อมูลเมื่อ Bazel อ่านไฟล์จากระบบไฟล์
การสร้างโปรไฟล์การโหลดทั้งระบบ
แฟล็ก
--experimental_collect_load_average_in_profiler
ที่เปิดตัวใน Bazel 6.0 ช่วยให้
โปรไฟล์การติดตาม JSON รวบรวมค่าเฉลี่ยการโหลดของระบบระหว่างการเรียกใช้

รูปที่ 1 โปรไฟล์ที่มีค่าเฉลี่ยการโหลดของระบบ
การโหลดสูงระหว่างการเรียกใช้ Bazel อาจบ่งชี้ว่า Bazel กำหนดเวลาการดำเนินการในเครื่องมากเกินไปพร้อมกันสำหรับเครื่องของคุณ คุณอาจต้องพิจารณา
ปรับ
--local_cpu_resources
และ --local_ram_resources,
โดยเฉพาะในสภาพแวดล้อมคอนเทนเนอร์ (อย่างน้อยจนกว่า
#16512 จะมีการผสาน)
การตรวจสอบการใช้งานหน่วยความจำของ Bazel
การใช้งานหน่วยความจำของ Bazel มาจากแหล่งที่มาหลัก 2 แหล่ง ได้แก่ Bazel info และ
BEP
bazel info used-heap-size-after-gc: ปริมาณหน่วยความจำที่ใช้เป็นไบต์หลังจากเรียกSystem.gc()- bazel bench ยังมีการเปรียบเทียบสำหรับเมตริกนี้ด้วย
- นอกจากนี้ ยังมี
peak-heap-size,max-heap-size,used-heap-sizeและcommitted-heap-size(ดู เอกสารประกอบ) แต่มีความเกี่ยวข้องน้อยกว่า
BEP’s
MemoryMetrics.peak_post_gc_heap_sizeของ BEP: ขนาดฮีป JVM สูงสุดเป็น ไบต์หลัง GC (ต้องตั้งค่า--memory_profileที่พยายามบังคับให้ทำ GC แบบเต็ม)
การถดถอยในการใช้งานหน่วยความจำมักเกิดจากการถดถอยใน เมตริกขนาดคำขอบิลด์, ซึ่งมักเกิดจากการเพิ่มการขึ้นต่อกันหรือการเปลี่ยนแปลงการใช้งานกฎ
หากต้องการวิเคราะห์การใช้หน่วยความจำของ Bazel ในระดับที่ละเอียดยิ่งขึ้น เราขอแนะนำให้ใช้ โปรไฟล์หน่วยความจำในตัว สำหรับกฎ
การสร้างโปรไฟล์หน่วยความจำของ Worker ที่ทำงานอยู่ตลอดเวลา
แม้ว่า Worker ที่ทำงานอยู่ตลอดเวลา จะช่วยเร่งความเร็วในการบิลด์
ได้อย่างมาก (โดยเฉพาะสำหรับภาษาที่ตีความ) แต่การใช้หน่วยความจำของ Worker เหล่านี้อาจ
เป็นปัญหาได้ Bazel จะรวบรวมเมตริกเกี่ยวกับ Worker โดยเฉพาะฟิลด์ WorkerMetrics.WorkerStats.worker_memory_in_kb จะบอกปริมาณหน่วยความจำที่ Worker ใช้ (ตามคำช่วยจำ)
โปรไฟล์การติดตาม JSON ยัง
รวบรวมการใช้งานหน่วยความจำของ Worker ที่ทำงานอยู่ตลอดเวลาระหว่างการเรียกใช้ด้วยการส่งแฟล็ก
--experimental_collect_system_network_usage (ใหม่ใน Bazel 6.0)

รูปที่ 2 โปรไฟล์ที่มีการใช้งานหน่วยความจำของ Worker
การลดค่า
--worker_max_instances
(ค่าเริ่มต้นคือ 4) อาจช่วยลด
ปริมาณหน่วยความจำที่ Worker ที่ทำงานอยู่ตลอดเวลาใช้ เรากำลังดำเนินการอย่างจริงจังเพื่อทำให้ตัวจัดการทรัพยากรและตัวกำหนดเวลาของ Bazel ฉลาดขึ้น เพื่อให้คุณไม่จำเป็นต้องปรับแต่งค่าต่างๆ บ่อยนักในอนาคต
การตรวจสอบการรับส่งข้อมูลเครือข่ายสำหรับการบิลด์ระยะไกล
ในการดำเนินการระยะไกล Bazel จะดาวน์โหลดอาร์ติแฟกต์ที่สร้างขึ้นจากการดำเนินการ ดังนั้น แบนด์วิดท์ของเครือข่ายจึงอาจส่งผลต่อประสิทธิภาพการบิลด์
หากคุณใช้การดำเนินการระยะไกลสำหรับการบิลด์ คุณอาจต้องพิจารณา
ตรวจสอบการรับส่งข้อมูลเครือข่ายระหว่างการเรียกใช้โดยใช้
NetworkMetrics.SystemNetworkStats โปรโตจาก BEP
(ต้องส่ง --experimental_collect_system_network_usage)
นอกจากนี้ โปรไฟล์การติดตาม JSON
ยังช่วยให้คุณดูการใช้งานเครือข่ายทั้งระบบตลอดระยะเวลาการบิลด์ได้
ด้วยการส่งแฟล็ก --experimental_collect_system_network_usage (ใหม่ใน Bazel
6.0)

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