แจกแจงประสิทธิภาพของบิลด์

วันที่ รายงานปัญหา ดูแหล่งที่มา ตอนกลางคืน · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

บิลด์ที่สะอาดเทียบกับบิลด์ที่เพิ่มขึ้น

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

เราขอแนะนำให้ดูบิลด์ที่เพิ่มขึ้นและสะอาดแยกกัน โดยเฉพาะเมื่อ ที่คุณกำลังรวบรวม / รวบรวมเมตริกที่ขึ้นอยู่กับสถานะของ แคชของ Bazel (ตัวอย่างเช่น เมตริกขนาดคำขอสร้าง ) อื่นๆ และยังแสดงถึงประสบการณ์ของผู้ใช้ 2 แบบที่แตกต่างกัน เมื่อเทียบกับการเริ่มต้น การสร้างใหม่ทั้งหมดตั้งแต่ต้น (ซึ่งใช้เวลานานกว่าเนื่องจาก Cold Cache) เพิ่ม เกิดขึ้นบ่อยครั้งกว่าที่นักพัฒนาซอฟต์แวร์ทำซ้ำโค้ด (โดยทั่วไปคือ เนื่องจากแคชมักจะร้อนอยู่แล้ว)

คุณสามารถใช้ฟิลด์ CumulativeMetrics.num_analyses ใน BEP เพื่อจัดประเภท งานสร้าง หากเป็น num_analyses <= 1 แสดงว่าเป็นบิลด์ที่สะอาด ไม่เช่นนั้น เราสามารถ จัดหมวดหมู่ให้เป็นบิลด์ที่เพิ่มขึ้น - ผู้ใช้อาจเปลี่ยน กับ Flag หรือเป้าหมายที่แตกต่างกัน ทำให้เกิดการสร้างที่สะอาดตาอย่างมีประสิทธิภาพ ช่วง คำนิยามของส่วนเพิ่มที่เข้มงวดขึ้น มักจะต้องมีรูปแบบ ของการเรียนรู้ เช่น การดูจำนวนแพ็กเกจที่โหลด (PackageMetrics.packages_loaded)

เมตริกบิลด์เชิงกำหนดเป็นตัวแทนสำหรับประสิทธิภาพของบิลด์

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

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

เราสามารถแบ่งปัญหานี้ออกเป็นระยะต่างๆ ของบิลด์ และใช้รายการต่อไปนี้ เป็นเมตริกพร็อกซีสำหรับงานที่ทำในแต่ละระยะ ดังนี้

  1. PackageMetrics.packages_loaded: จำนวนแพ็กเกจที่โหลดสำเร็จ การถดถอยนี้แสดงถึงงานอื่นๆ ที่ต้องทำให้เสร็จเพื่ออ่านและแยกวิเคราะห์ ไฟล์ BUILD เพิ่มเติมแต่ละไฟล์ในระยะการโหลด

    • กรณีนี้มักเกิดจากการเพิ่มทรัพยากร Dependency และการมีการโหลดทรัพยากร Dependency การปิดแบบสับเปลี่ยน
    • ใช้คำค้นหา / cqueryเพื่อค้นหา ซึ่งอาจมีการเพิ่มทรัพยากร Dependency ใหม่
  2. TargetMetrics.targets_configured: แสดงจำนวนเป้าหมายและ ด้านต่างๆ ที่กำหนดค่าไว้ในบิลด์ การถดถอยแสดงถึงงานเพิ่มเติมใน สร้างและข้ามผ่านกราฟเป้าหมายที่กำหนดค่าไว้

    • กรณีนี้มักเกิดจากการเพิ่มทรัพยากร Dependency และจำเป็นต้องสร้าง กราฟการปิดแบบสกรรม
    • ใช้ cquery เพื่อค้นหาตำแหน่งใหม่ อาจมีการเพิ่มทรัพยากร Dependency แล้ว
  3. ActionSummary.actions_created: แสดงการดำเนินการที่สร้างในบิลด์ และการถดถอยแสดงถึงงานที่มากขึ้นในการสร้างกราฟการทำงาน หมายเหตุ จะรวมถึงการดำเนินการที่ไม่ได้ใช้ซึ่งอาจไม่ได้ดำเนินการด้วย

    • ใช้ aquery เพื่อแก้ไขข้อบกพร่องการเกิดปัญหาซ้ำ เราขอแนะนำให้เริ่มต้นด้วย --output=summary ก่อนที่จะดูข้อมูลเจาะลึกเพิ่มเติม --skyframe_state
  4. ActionSummary.actions_executed: จำนวนการดำเนินการที่ทำ การถดถอยจะหมายถึงการทำงานที่มากขึ้นในการดำเนินการเหล่านี้โดยตรง

    • BEP จะเขียนสถิติการกระทำ ActionData ที่แสดงประเภทการดำเนินการที่ดำเนินการมากที่สุด โดยค่าเริ่มต้น จะรวบรวมประเภทการดำเนินการ 20 อันดับแรก แต่คุณสามารถส่ง --experimental_record_metrics_for_all_mnemonics เพื่อรวบรวมข้อมูลนี้สำหรับการดำเนินการทุกประเภทที่ได้ดำเนินการ
    • ข้อมูลนี้จะช่วยให้คุณทราบว่าระบบได้ดำเนินการประเภทใดไปแล้วบ้าง (เพิ่มเติม)
  5. BuildGraphSummary.outputArtifactCount: จำนวนอาร์ติแฟกต์ที่สร้างโดย การดำเนินการที่ดำเนินการไปแล้ว

    • หากจำนวนของการดำเนินการที่ไม่เพิ่มขึ้น อาจเป็นไปได้ว่า มีการเปลี่ยนแปลงการใช้กฎ

เมตริกเหล่านี้ได้รับผลกระทบจากสถานะแคชในเครื่องทั้งหมด ดังนั้นคุณจะต้อง ต้องการตรวจสอบว่าบิลด์ที่คุณแยกเมตริกเหล่านี้ออกมา บิลด์สะอาด

เราพบว่าการถดถอยในเมตริกเหล่านี้อาจมาพร้อมกับ การเกิดปัญหาซ้ำเกี่ยวกับเวลาจริง เวลา CPU และการใช้งานหน่วยความจำ

การใช้ทรัพยากรในเครื่อง

Bazel ใช้ทรัพยากรมากมายในเครื่องของคุณ (ทั้งสำหรับการวิเคราะห์ กราฟบิลด์และการขับเคลื่อนการดำเนินการ และการเรียกใช้การกระทำเกี่ยวกับสถานที่) อาจส่งผลต่อประสิทธิภาพ / ความพร้อมใช้งานของเครื่องของคุณในการดำเนินการ และงานอื่นๆ ได้ด้วย

เวลาที่ใช้

บางทีเมตริกที่เสี่ยงต่อสัญญาณรบกวนมากที่สุด (และอาจแตกต่างกันไปตามรุ่น คือเวลาที่เหมาะสม โดยเฉพาะอย่างยิ่ง เวลาใช้งานจริง เวลา CPU และเวลาของระบบ คุณสามารถ ใช้ bazel-bench เพื่อ การเปรียบเทียบสำหรับเมตริกเหล่านี้ และเมื่อมี --runs จำนวนมากพอ คุณจะสามารถ เพิ่มนัยสำคัญทางสถิติของการวัด

  • เวลากำแพง คือเวลาที่ผ่านไปในชีวิตจริง

    • หากเวลาการแสดงผลถดถอยเท่านั้น เราขอแนะนําให้รวบรวม โปรไฟล์การติดตาม JSON และการดู เพื่อดูความแตกต่าง มิฉะนั้น การใช้ ให้ตรวจสอบเมตริกอื่นๆ ที่เกิดปัญหาซ้ำเนื่องจากเมตริกดังกล่าวอาจส่งผลต่อการจำกัดการเข้าชม
  • เวลาของ CPU คือเวลาที่ CPU ใช้งานโค้ดผู้ใช้

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

    • หากเวลาของระบบถดถอย ส่วนใหญ่จะสัมพันธ์กับ I/O เมื่อ 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()

    • ม้านั่งบาเซล ให้ตัวเปรียบเทียบสำหรับเมตริกนี้ด้วย
    • นอกจากนี้ยังมีpeak-heap-size max-heap-size used-heap-size และ committed-heap-size (โปรดดู เอกสารประกอบ) แต่ ไม่ค่อยเกี่ยวข้อง
  • ของ BEP MemoryMetrics.peak_post_gc_heap_size: ขนาดของฮีป JVM สูงสุดใน ไบต์หลัง GC (ต้องตั้งค่า --memory_profile ที่พยายามบังคับให้ GC เต็มรูปแบบ)

การใช้หน่วยความจำถดถอยมักเป็นผลมาจากการถดถอยใน สร้างเมตริกขนาดคำขอ ซึ่งมักเกิดจากการเพิ่มทรัพยากร Dependency หรือมีการเปลี่ยนแปลงกฎ การใช้งานของคุณ

หากต้องการวิเคราะห์การใช้หน่วยความจำของ Bazel ในระดับที่ละเอียดยิ่งขึ้น เราขอแนะนำให้ใช้ เครื่องมือสร้างโปรไฟล์หน่วยความจำในตัว สำหรับกฎต่างๆ

การทำโปรไฟล์หน่วยความจำของผู้ปฏิบัติงานถาวร

ในขณะที่ผู้ปฏิบัติงานอย่างต่อเนื่องสามารถช่วยเร่งการสร้างได้ อย่างมาก (โดยเฉพาะภาษาที่แปลโดยอินเทอร์พรีเตอร์) ร่องรอยความทรงจำ สร้างปัญหาได้ Bazel รวบรวมเมตริกเกี่ยวกับผู้ปฏิบัติงาน โดยเฉพาะ ฟิลด์ WorkerMetrics.WorkerStats.worker_memory_in_kb บอกจำนวนหน่วยความจำ ที่ผู้ปฏิบัติงานใช้ (ตามความสามารถในการจำ)

เครื่องมือสร้างโปรไฟล์การติดตาม JSON ยัง เก็บรวบรวมการใช้งานหน่วยความจำของผู้ปฏิบัติงานถาวรระหว่างการเรียกใช้โดยการส่งผ่าน --experimental_collect_system_network_usage (ใหม่ใน Bazel 6.0)

โปรไฟล์ที่มีการใช้งานหน่วยความจำของผู้ปฏิบัติงาน

รูปที่ 2 โปรไฟล์ที่มีการใช้งานหน่วยความจำของผู้ปฏิบัติงาน

การลดค่าของ --worker_max_instances (ค่าเริ่มต้น 4) อาจช่วย ปริมาณหน่วยความจำที่ผู้ปฏิบัติงานถาวรใช้ เรากำลังพัฒนาอย่างต่อเนื่อง ทำให้ตัวจัดการทรัพยากรและเครื่องจัดตารางเวลาของ Bazel ฉลาดขึ้น ซึ่งทำให้การปรับแต่ง จะไม่ค่อยเกิดขึ้นในอนาคต

การตรวจสอบการจราจรของข้อมูลในเครือข่ายสำหรับบิลด์ระยะไกล

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

หากใช้การดำเนินการระยะไกลสำหรับบิลด์ คุณอาจต้องพิจารณา การตรวจสอบการจราจรของข้อมูลในเครือข่ายระหว่างการเรียกใช้โดยใช้ NetworkMetrics.SystemNetworkStats Proto จาก BEP (ต้องผ่าน --experimental_collect_system_network_usage)

นอกจากนี้ โปรไฟล์การติดตาม JSON ช่วยให้คุณดูการใช้งานเครือข่ายทั้งระบบได้ตลอดช่วงบิลด์ ด้วยการติดธง --experimental_collect_system_network_usage (ใหม่ใน Bazel 6.0)

โปรไฟล์ที่มีการใช้งานเครือข่ายทั้งระบบ

รูปที่ 3 โปรไฟล์ที่มีการใช้งานเครือข่ายทั้งระบบ

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

อีกตัวเลือกหนึ่งคือการกำหนดค่า แคชดิสก์เพื่อบันทึกไว้ แบนด์วิดท์การดาวน์โหลด