Bazel มีความซับซ้อนและทำอะไรหลายอย่างตลอดการสร้าง ซึ่งบางอย่างอาจส่งผลต่อประสิทธิภาพของบิลด์ หน้านี้จะพยายามเชื่อมโยงแนวคิดของ Bazel บางส่วนเหล่านี้เข้ากับนัยยะของประสิทธิภาพในการสร้าง เราได้รวบรวมตัวอย่างวิธีตรวจหาปัญหาด้านประสิทธิภาพผ่านการแตกเมตริกและวิธีแก้ไขที่ทำได้ ซึ่งช่วยได้ไม่มากเท่านี้ เราจึงหวังว่าคุณจะนำแนวคิดเหล่านี้ไปใช้ เมื่อตรวจสอบประสิทธิภาพที่ถดถอย
บิลด์ที่ดูสะอาดตาเทียบกับเวอร์ชันที่เพิ่มขึ้น
บิลด์ที่ชัดเจนคือบิลด์ที่สร้างทุกอย่างใหม่ตั้งแต่ต้น ขณะที่บิลด์ที่เพิ่มขึ้นจะใช้งานบางส่วนที่ทำเสร็จแล้วซ้ำ
เราขอแนะนำให้ดูบิลด์ที่เป็นระเบียบและเพิ่มขึ้นแยกกัน โดยเฉพาะอย่างยิ่งเมื่อคุณกำลังรวบรวม / รวมเมตริกที่ขึ้นอยู่กับสถานะของแคชของ Bazel (เช่น เมตริกขนาดคำขอสร้าง) การทดสอบยังแสดงถึงประสบการณ์ของผู้ใช้ 2 อย่างที่แตกต่างกันด้วย เมื่อเทียบกับการเริ่มสร้างบิลด์ที่สะอาดตั้งแต่ต้น (ซึ่งใช้เวลานานกว่าเนื่องจาก Cold Cache) เวอร์ชันที่เพิ่มขึ้นจะเกิดขึ้นบ่อยกว่าเมื่อนักพัฒนาซอฟต์แวร์ใช้โค้ดซ้ำๆ (โดยทั่วไปจะเร็วกว่าเนื่องจากแคชมักจะร้อนอยู่แล้ว)
คุณใช้ช่อง CumulativeMetrics.num_analyses
ใน BEP เพื่อแยกประเภทงานได้ หาก num_analyses <= 1
เวอร์ชันนี้เป็นบิลด์ที่ชัดเจน มิเช่นนั้น เราสามารถจัดหมวดหมู่ให้กว้างเพื่อน่าจะเป็นบิลด์แบบเพิ่มได้ ผู้ใช้อาจเปลี่ยนไปใช้ Flag อื่นหรือเป้าหมายอื่นซึ่งทําให้มีบิลด์ที่สะอาดอย่างมีประสิทธิภาพ คำนิยามของส่วนเพิ่มที่เข้มงวดยิ่งขึ้นมีแนวโน้มที่จะมาในรูปแบบของการเรียนรู้ ตัวอย่างเช่น การดูจำนวนแพ็กเกจที่โหลด (PackageMetrics.packages_loaded
)
กำหนดเมตริกบิลด์เพื่อเป็นพร็อกซีสำหรับประสิทธิภาพของบิลด์
การวัดประสิทธิภาพบิลด์อาจทำได้ยากเนื่องจากเมตริกบางรายการที่ไม่ได้กำหนด (เช่น เวลา CPU ของ Bazel หรือเวลาในคิวบนคลัสเตอร์ระยะไกล) ด้วยเหตุนี้ การใช้เมตริกเชิงกำหนดจึงเป็นพร็อกซีสำหรับจำนวนงานที่ Bazel ทำให้เสร็จ ซึ่งก็ส่งผลดีต่อประสิทธิภาพการทำงานด้วย
ขนาดของคำขอบิลด์อาจส่งผลกระทบที่สำคัญต่อประสิทธิภาพของบิลด์ บิลด์ที่ใหญ่ขึ้นอาจแสดงถึงงานที่มากขึ้นในการวิเคราะห์และสร้างกราฟบิลด์ การเติบโตที่เกิดขึ้นเองของบิลด์จะมีการพัฒนาอยู่แล้ว เนื่องจากมีการเพิ่ม/สร้างทรัพยากร Dependency มากขึ้น การสร้างก็ซับซ้อนขึ้นและมีราคาแพงขึ้นในการสร้าง
เราสามารถแบ่งปัญหานี้ออกเป็นขั้นตอนต่างๆ ของบิลด์ และใช้เมตริกต่อไปนี้เป็นเมตริกพร็อกซีสำหรับงานที่ทำในแต่ละระยะ
PackageMetrics.packages_loaded
: จำนวนแพ็กเกจที่โหลดสำเร็จแล้ว การถดถอยที่นี่แสดงถึงงานเพิ่มเติมที่ต้องทำเพื่ออ่านและแยกวิเคราะห์ไฟล์ BUILD เพิ่มเติมแต่ละไฟล์ในช่วงการโหลดTargetMetrics.targets_configured
: แสดงจำนวนเป้าหมายและมุมมองที่กำหนดค่าในบิลด์ การถดถอยแสดงถึงงานที่มากขึ้นในการสร้างและข้ามกราฟเป้าหมายที่กำหนดค่าไว้- ปัญหานี้มักเกิดจากการเพิ่มทรัพยากร Dependency และต้องสร้างกราฟของการปิดแบบสกรรม
- ใช้ cquery เพื่อดูว่าควรเพิ่มทรัพยากร Dependency ใหม่ไว้ที่ใดบ้าง
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 อ่านไฟล์จากระบบไฟล์
การสร้างโปรไฟล์ภาระงานทั้งระบบ
เครื่องมือสร้างโปรไฟล์การติดตาม JSON จะรวบรวมค่าเฉลี่ยการโหลดของระบบระหว่างการเรียกใช้โดยใช้แฟล็ก --experimental_collect_load_average_in_profiler
ที่เริ่มใช้ใน Bazel 6.0
รูปที่ 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()
- การเปรียบเทียบแบบ Bayel จะแสดงการเปรียบเทียบสำหรับเมตริกนี้ด้วย
- นอกจากนี้ยังมี
peak-heap-size
,max-heap-size
,used-heap-size
และcommitted-heap-size
(ดูเอกสารประกอบ) แต่มีความเกี่ยวข้องน้อยกว่า
BEP
MemoryMetrics.peak_post_gc_heap_size
: ขนาดของฮีป JVM สูงสุดเป็นไบต์ที่โพสต์ GC (ต้องมีการตั้งค่า--memory_profile
ที่พยายามบังคับใช้ GC แบบเต็ม)
การถดถอยในการใช้หน่วยความจำมักจะเป็นผลมาจากการถดถอยในเมตริกขนาดคำขอสร้าง ซึ่งมักเกิดจากการเพิ่มการอ้างอิงหรือการเปลี่ยนแปลงในการใช้งานกฎ
หากต้องการวิเคราะห์การใช้หน่วยความจำของ Bazel ในระดับที่ละเอียดขึ้น เราขอแนะนำให้ใช้เครื่องมือสร้างโปรไฟล์หน่วยความจำในตัวสำหรับกฎ
การสร้างโปรไฟล์หน่วยความจำของผู้ปฏิบัติงานถาวร
แม้ว่าพนักงานถาวรจะช่วยเร่งการสร้างบิวด์ต่างๆ ได้อย่างมาก (โดยเฉพาะภาษาที่แปลโดยอินเตอร์พรีเตอร์) แต่ก็อาจก่อให้เกิดปัญหาตามมาได้ Bazel รวบรวมเมตริกต่างๆ ของคนทำงาน โดยเฉพาะอย่างยิ่ง ช่อง WorkerMetrics.WorkerStats.worker_memory_in_kb
จะบอกปริมาณหน่วยความจำที่ผู้ปฏิบัติงานใช้ (ด้วยการช่วยจำ)
เครื่องมือสร้างโปรไฟล์การติดตาม JSON ยังรวบรวมการใช้หน่วยความจำผู้ปฏิบัติงานถาวรระหว่างการเรียกใช้ด้วยการส่งผ่านแฟล็ก --experimental_collect_system_network_usage
(ใหม่ใน Bazel 6.0)
รูปที่ 2 โปรไฟล์ที่มีการใช้งานหน่วยความจำของผู้ปฏิบัติงาน
การลดค่าของ
--worker_max_instances
(ค่าเริ่มต้น 4) อาจช่วยลดปริมาณหน่วยความจำที่ผู้ปฏิบัติงานถาวรใช้ไปได้ เรากําลังพยายามทําให้ผู้จัดการทรัพยากรและจัดตารางเวลาของ Bazel ฉลาดขึ้น เพื่อให้การปรับแต่งเช่นนี้เกิดขึ้นได้ไม่บ่อยนักในอนาคต
การตรวจสอบการจราจรของข้อมูลในเครือข่ายสำหรับบิลด์ระยะไกล
ในการดำเนินการจากระยะไกล Bazel จะดาวน์โหลดอาร์ติแฟกต์ที่สร้างขึ้นจากการดำเนินการต่างๆ ด้วยเหตุนี้ แบนด์วิดท์ของเครือข่ายจึงอาจส่งผลต่อประสิทธิภาพของบิลด์
หากใช้การดำเนินการระยะไกลสำหรับบิลด์ คุณอาจต้องตรวจสอบการจราจรของข้อมูลในเครือข่ายระหว่างการเรียกใช้โดยใช้
Proto ของ NetworkMetrics.SystemNetworkStats
จาก BEP
(ต้องมีการส่งผ่าน --experimental_collect_system_network_usage
)
นอกจากนี้ โปรไฟล์การติดตาม JSON ช่วยให้คุณดูการใช้งานเครือข่ายทั้งระบบได้ตลอดการสร้างโดยส่งแฟล็ก --experimental_collect_system_network_usage
(ใหม่ใน Bazel
6.0)
รูปที่ 3 โปรไฟล์ที่มีการใช้งานเครือข่ายทั้งระบบ
การใช้งานเครือข่ายที่สูงแต่เป็นเครือข่ายแบบแบนเมื่อใช้การดำเนินการระยะไกลอาจบ่งชี้ว่าเครือข่ายนั้นเป็นจุดคอขวดในบิลด์ของคุณ หากยังไม่ได้ใช้ ให้พิจารณาเปิดบิลด์ที่ไม่มีไบต์โดยการส่ง --remote_download_minimal
การดำเนินการนี้จะช่วยให้บิลด์ของคุณเร็วขึ้นโดยหลีกเลี่ยงการดาวน์โหลดอาร์ติแฟกต์ระดับกลางที่ไม่จำเป็น
อีกทางเลือกหนึ่งคือการกำหนดค่าดิสก์แคชในเครื่องเพื่อประหยัดแบนด์วิดท์การดาวน์โหลด