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

รายงานปัญหา ดูแหล่งที่มา รุ่น Nightly · 7.4 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 ส่วนได้ โดยปกติแล้วจะเป็นการดำเนินการภายในเล็กๆ น้อยๆ เช่น การสร้างลิงก์สัญลักษณ์ ระบบจะไม่รวมการตีกลับจากแคชในเครื่องไว้ในสรุปนี้ หากมีกระบวนการ 0 รายการ (หรือน้อยกว่าที่คาดไว้) ให้เรียกใช้ bazel clean ตามด้วยคำสั่ง build/test

การแก้ปัญหาการพบแคช

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

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

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

  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 แคชทั้งหมด ให้ข้ามไปยังส่วนถัดไป

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

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

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

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

    ก. เพิ่ม --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 ครั้ง หากบันทึกไม่เหมือนกัน ให้ตรวจสอบการกําหนดค่าบิลด์เพื่อหาความคลาดเคลื่อน รวมถึงพร็อพเพอร์ตี้จากสภาพแวดล้อมโฮสต์ที่รั่วไหลไปยังบิลด์ใดบิลด์หนึ่ง

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

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

บันทึกการดําเนินการจะสร้างได้ในรูปแบบใดรูปแบบหนึ่งต่อไปนี้ แบบกะทัดรัด (--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 cd bazel bazel build //src/tools/execlog:parser

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

    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. ใช้ข้อความที่คุณต้องการแทนที่ diff /tmp/exec1.log.txt และ /tmp/exec2.log.txt