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

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

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

การตรวจสอบอัตราการเข้าถึงแคช

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

เช่น

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

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

การแก้ปัญหาการเข้าถึงแคช

หากอัตราการเข้าถึงแคชไม่เป็นไปตามที่คาดไว้ ให้ทำดังนี้

ตรวจสอบว่าการเรียกใช้คำสั่งสร้าง/ทดสอบเดิมซ้ำจะทำให้เกิดการเข้าถึงแคช

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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 จะเรียงลำดับให้ตรงกับลำดับในบันทึกแรก ซึ่งทำให้เปรียบเทียบได้ง่ายขึ้น

    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