Bazel มีความซับซ้อนและทำสิ่งต่างๆ มากมายในระหว่างการบิลด์ ซึ่งบางอย่างอาจส่งผลต่อประสิทธิภาพการบิลด์ หน้านี้พยายามที่จะเชื่อมโยง แนวคิด Bazel บางอย่างเหล่านี้กับผลกระทบต่อประสิทธิภาพการสร้าง แม้จะไม่ครอบคลุมทั้งหมด แต่เราได้รวมตัวอย่างวิธีตรวจหาปัญหาด้านประสิทธิภาพการบิลด์ ผ่านการดึงข้อมูล เมตริก และสิ่งที่คุณทำได้เพื่อแก้ไขปัญหา เราหวังว่าคุณจะนำแนวคิดเหล่านี้ไปใช้ได้เมื่อ ตรวจสอบการถดถอยของประสิทธิภาพการบิลด์
บิลด์เปล่าเทียบกับบิลด์แบบเพิ่ม
บิลด์เปล่าคือบิลด์ที่สร้างทุกอย่างตั้งแต่ต้น ส่วนบิลด์แบบเพิ่มจะนำงานที่เสร็จสมบูรณ์แล้วบางส่วนมาใช้ซ้ำ
เราขอแนะนำให้ดูการสร้างแบบ Clean และการสร้างแบบ Incremental แยกกัน โดยเฉพาะเมื่อคุณรวบรวม / รวมเมตริกที่ขึ้นอยู่กับสถานะของแคชของ 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 ใช้ในเคอร์เนล
- หากเวลาของระบบถดถอย ส่วนใหญ่จะสัมพันธ์กับ I/O เมื่อ Bazel อ่านไฟล์จากระบบไฟล์
การสร้างโปรไฟล์การโหลดทั่วทั้งระบบ
การใช้แฟล็ก
--experimental_collect_load_average_in_profiler
ที่เปิดตัวใน Bazel 6.0 โปรไฟล์เลส JSON Trace จะรวบรวมค่าเฉลี่ยของภาระงานของระบบระหว่างการเรียกใช้

รูปที่ 1 โปรไฟล์ที่มีค่าเฉลี่ยของโหลดระบบ
การโหลดสูงระหว่างการเรียกใช้ Bazel อาจบ่งชี้ว่า Bazel กำหนดเวลา
การดำเนินการในเครื่องมากเกินไปพร้อมกันสำหรับเครื่องของคุณ คุณอาจต้องพิจารณา
ปรับ
--local_cpu_resources
และ
--local_ram_resources
โดยเฉพาะในสภาพแวดล้อมคอนเทนเนอร์ (อย่างน้อยจนกว่าจะผสานรวม#16512)
การตรวจสอบการใช้งานหน่วยความจำของ Bazel
แหล่งที่มาหลัก 2 แหล่งในการดูการใช้หน่วยความจำของ Bazel คือ 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: ขนาดของฮีป JVM สูงสุดเป็นไบต์หลัง GC (ต้องตั้งค่า--memory_profileที่พยายามบังคับให้ทำ GC แบบเต็ม)
โดยปกติแล้ว การถดถอยในการใช้งานหน่วยความจำมักเป็นผลมาจากการถดถอยในเมตริก ขนาดคำขอ บิลด์ ซึ่งมักเกิดจากการเพิ่มการอ้างอิงหรือการเปลี่ยนแปลงการใช้งานกฎ
หากต้องการวิเคราะห์ร่องรอยการใช้หน่วยความจำของ Bazel ในระดับที่ละเอียดยิ่งขึ้น เราขอแนะนำให้ใช้โปรไฟล์เลอร์หน่วยความจำในตัวสำหรับกฎ
การสร้างโปรไฟล์หน่วยความจำของผู้ปฏิบัติงานแบบถาวร
แม้ว่าWorker ที่ทำงานอย่างต่อเนื่องจะช่วยเร่งความเร็วในการสร้างได้อย่างมาก (โดยเฉพาะภาษาที่ตีความ) แต่การใช้หน่วยความจำอาจเป็นปัญหาได้ Bazel จะรวบรวมเมตริกเกี่ยวกับ Worker โดยเฉพาะฟิลด์ WorkerMetrics.WorkerStats.worker_memory_in_kb จะบอกว่า Worker ใช้หน่วยความจำมากน้อยเพียงใด (ตามชื่อช่วยจำ)
เครื่องมือสร้างโปรไฟล์การติดตาม JSON ยังรวบรวม
การใช้งานหน่วยความจำของ Worker แบบถาวรระหว่างการเรียกใช้โดยส่งแฟล็ก
--experimental_collect_system_network_usage (ใหม่ใน Bazel 6.0)

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

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