การแก้ไขข้อบกพร่องของ Hit แคชระยะไกลสำหรับการดำเนินการระยะไกล

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

หน้านี้จะอธิบายวิธีตรวจสอบอัตรา Hit ของแคชและวิธีตรวจสอบการไม่พบแคชในบริบทของการดำเนินการระยะไกล

หน้านี้ถือว่าคุณมีบิลด์และ/หรือการทดสอบที่ใช้การเรียกใช้จากระยะไกลได้สําเร็จ และคุณต้องการตรวจสอบว่าคุณใช้แคชระยะไกลอย่างมีประสิทธิภาพ

ตรวจสอบอัตรา Hit ของแคช

ในเอาต์พุตมาตรฐานของการเรียกใช้ Bazel ให้ดูที่บรรทัด INFO ที่แสดง ซึ่งสอดคล้องกับการดำเนินการของ Bazel บรรทัดดังกล่าวจะแสดงรายละเอียดว่าการดำเนินการนั้นทําที่ใด มองหาป้ายกํากับ remote ซึ่งระบุการดำเนินการที่ดำเนินการจากระยะไกล linux-sandbox สําหรับการดำเนินการที่ดำเนินการในแซนด์บ็อกซ์ในเครื่อง และค่าอื่นๆ สําหรับกลยุทธ์การดําเนินการอื่นๆ การกระทำที่เกิดผลลัพธ์ จากแคชระยะไกลจะแสดงเป็น remote cache hit

เช่น

INFO: 11 processes: 6 remote cache hit, 3 internal, 2 remote.

ในตัวอย่างนี้ มี Hit ของแคชระยะไกล 6 รายการ และการดําเนินการ 2 รายการไม่มี Hit ของแคชและดําเนินการจากระยะไกล คุณสามารถละเว้นส่วนภายใน 3 ส่วนได้ โดยปกติแล้วจะเป็นการดำเนินการภายในเล็กๆ น้อยๆ เช่น การสร้างลิงก์สัญลักษณ์ ในพื้นที่ Hit จากแคชไม่รวมอยู่ในสรุปนี้ หากมีกระบวนการ 0 รายการ (หรือน้อยกว่าที่คาดไว้) ให้เรียกใช้ bazel clean ตามด้วยคำสั่ง build/test

การแก้ปัญหาการตีข้อมูลแคช

หากคุณไม่ได้รับอัตรา Hit ของแคชตามที่คาดไว้ ให้ทำดังนี้

ตรวจสอบว่าการเรียกใช้คําสั่งบิลด์/ทดสอบเดิมอีกครั้งทําให้เกิด Hit ของแคช

  1. เรียกใช้บิลด์และ/หรือการทดสอบที่คุณต้องการป้อนข้อมูลในแคช ครั้งแรกที่บิลด์ใหม่ทำงานบนสแต็กที่เฉพาะเจาะจง คุณจึงไม่จำเป็นต้องดำเนินการเกี่ยวกับระยะไกล การพบแคช ในฐานะส่วนหนึ่งของการดำเนินการระยะไกล ระบบจะจัดเก็บผลลัพธ์การดำเนินการใน และการเรียกใช้ครั้งต่อๆ ไปควรจะนำมาใช้

  2. เรียกใช้ bazel clean คำสั่งนี้จะล้างแคชในเครื่อง ซึ่งจะช่วยให้คุณตรวจสอบ Hit ของแคชระยะไกลได้โดยไม่ต้องปิดบังผลลัพธ์ด้วย Hit ของแคชในเครื่อง

  3. เรียกใช้บิลด์และการทดสอบที่คุณกำลังตรวจสอบอีกครั้ง (ใน อัตโนมัติ)

  4. ตรวจสอบบรรทัด INFO เพื่อดูอัตรา Hit ของแคช หากไม่เห็นกระบวนการใดๆ ยกเว้น remote cache hit และ internal แสดงว่าระบบกําลังสร้างและเข้าถึงแคชอย่างถูกต้อง ในกรณีดังกล่าว ให้ข้ามไปยังส่วนถัดไป

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

    ก. เรียกใช้บิลด์หรือการทดสอบที่เป็นปัญหาอีกครั้งเพื่อดูบันทึกการดำเนินการ

      bazel clean
      bazel --optional-flags build //your:target --execution_log_compact_file=/tmp/exec1.log

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

    หากแก้ปัญหาการแคชได้และตอนนี้การเรียกใช้ซ้ำทำให้เกิด Hit แคชทั้งหมด ให้ข้ามไปยังส่วนถัดไป

    หากรหัสการกระทําเหมือนกันแต่ไม่มีการตีข้อมูลแคช แสดงว่าอาจมีบางอย่างในการกําหนดค่าที่ป้องกันไม่ให้แคช ดำเนินการต่อในส่วนนี้เพื่อตรวจสอบปัญหาที่พบได้ทั่วไป

  6. ตรวจสอบว่าการดำเนินการทั้งหมดในบันทึกการดำเนินการตั้งค่า cacheable เป็น "จริง" หาก cacheable ไม่ปรากฏในบันทึกการดำเนินการสําหรับการดําเนินการหนึ่งๆ แสดงว่ากฎที่เกี่ยวข้องอาจมีแท็ก no-cache ในคําจํากัดความในไฟล์ BUILD ดูช่อง mnemonic และ target_label ในบันทึกการดำเนินการเพื่อช่วยระบุที่มาของการดำเนินการ

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

    หากหาบรรทัดคำสั่งจริงได้ยาก ให้ใช้บรรทัดคำสั่งตามมาตรฐานจากโปรโตคอลเหตุการณ์การสร้าง ดังนี้

    ก. เพิ่ม --build_event_text_file=/tmp/bep.txt ลงในคำสั่ง Bazel เพื่อรับ บันทึกในเวอร์ชันข้อความ

    ข. เปิดบันทึกเวอร์ชันข้อความและค้นหาข้อความ structured_command_line ที่มี command_line_label: "canonical" ซึ่งจะแสดงตัวเลือกทั้งหมดหลังจากการขยาย

    ค. ค้นหา remote_accept_cached และตรวจสอบว่าได้ตั้งค่าเป็น false หรือไม่

    ง. หาก remote_accept_cached คือ false ให้ตรวจสอบว่าอยู่ที่ไหน ตั้งค่าเป็น false: ที่บรรทัดคำสั่งหรือใน bazelrc

ตรวจสอบการแคชในเครื่องต่างๆ

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

  1. ทำการแก้ไขเล็กน้อยในบิลด์เพื่อหลีกเลี่ยงการใช้แคชที่มีอยู่

  2. เรียกใช้บิลด์ในเครื่องแรกโดยทำดังนี้

     bazel clean
     bazel ... build ... --execution_log_compact_file=/tmp/exec1.log
  3. เรียกใช้บิลด์บนเครื่องที่ 2 เพื่อให้แน่ใจว่ามีการแก้ไขจากขั้นตอนที่ 1 รวม:

     bazel clean
     bazel ... build ... --execution_log_compact_file=/tmp/exec2.log
  4. เปรียบเทียบบันทึกการดำเนินการสำหรับทั้ง 2 ไฟล์ วิ่ง หากบันทึกไม่เหมือนกัน ให้ตรวจสอบการกําหนดค่าบิลด์เพื่อหาความคลาดเคลื่อน รวมถึงพร็อพเพอร์ตี้จากสภาพแวดล้อมโฮสต์ที่รั่วไหลไปยังบิลด์ใดบิลด์หนึ่ง

การเปรียบเทียบบันทึกการดำเนินการ

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

บันทึกการดำเนินการสร้างได้ใน 3 รูปแบบต่อไปนี้ กะทัดรัด (--execution_log_compact_file) ไบนารี (--execution_log_binary_file) หรือ JSON (--execution_log_json_file) ขอแนะนำให้ใช้รูปแบบกะทัดรัด เพราะจะสร้างไฟล์ขนาดเล็กมาก โอเวอร์เฮ็ดของรันไทม์เล็กน้อย วิธีการต่อไปนี้ใช้ได้กับทุกรูปแบบ คุณ และยังแปลงค่าเหล่านี้โดยใช้เครื่องมือ //src/tools/execlog:converter ได้ด้วย

หากต้องการเปรียบเทียบบันทึกสำหรับบิลด์ 2 รายการที่ไม่ได้แชร์ Hit ของแคชตามที่คาดไว้ ให้ทำดังนี้

  1. รับบันทึกการดำเนินการจากบิลด์แต่ละรายการและจัดเก็บเป็น /tmp/exec1.log และ /tmp/exec2.log

  2. ดาวน์โหลดซอร์สโค้ด Bazel และสร้าง //src/tools/execlog:parser เครื่องมือ:

    git clone https://github.com/bazelbuild/bazel.git ซีดี บาเซล บิลด์ของ bazel //src/tools/execlog:parser

  3. ใช้เครื่องมือ //src/tools/execlog:parser เพื่อแปลงบันทึกเป็น รูปแบบข้อความที่มนุษย์อ่านได้ ในรูปแบบนี้ การดำเนินการในบันทึกที่ 2 จัดเรียงให้ตรงกับลำดับในบันทึกแรก ซึ่งทำให้เปรียบเทียบได้ง่ายขึ้น

    bazel-bin/src/tools/execlog/parser \
      --log_path=/tmp/exec1.log \
      --log_path=/tmp/exec2.log \
      --output_path=/tmp/exec1.log.txt \
      --output_path=/tmp/exec2.log.txt
    
  4. ใช้ข้อความโปรดของคุณเพื่อให้แตกต่างจาก /tmp/exec1.log.txt และ /tmp/exec2.log.txt