傻瓜式debug

xieby1

🎉2024.01.26

1 问题场景一

  • 正确性测试:每次commit都有会
    • 程序正确性没问题
  • 性能回归测试:隔了几十个commit才跑了一次
    • 跑出了明显的性能下降
  • 测试慢
    • 一轮测试2小时
  • 开发紧张
    • 每天提交20个commit、不能堵住新commit

1.1 可能的解决方法

git bisect
git bisect bad HEAD
git bisect good <commit>
<run tests>
git bisect good/bad
<run tests>
git bisect good/bad
<run tests>
...

1.2 时间预估

git bisect
git bisect bad HEAD
git bisect good <commit>
<run tests>
git bisect good/bad
<run tests>
git bisect good/bad
<run tests>
...

串行!

  • git bisect次数
    • \(\left \lceil log_2(几十) \right \rceil\)
  • 预计消耗时间
    • \(2 \times \left \lceil log_2(几十) \right \rceil 小时\)
    • \(\approx 十几小时 \approx 通宵\)

1.3 解决方法

  • git bisect次数
    • \(\left \lceil log_2(几十) \right \rceil\)
  • 预计消耗时间
    • \(2 \times \left \lceil log_2(几十) \right \rceil 小时\)
    • \(\approx 十几小时 \approx 通宵\)

每隔两小时设一个闹钟⏰

也就一晚上的事情嘛😼

绝对不会耽误明天的工期

1.4 过了一晚🌃

找到了导致性能下降的commit …

case X86_INS_CALL: switch (oprs_type) {
    case OT_OPR0_I: {
        if (szs[0] == 8) {
            // fuck capstone change relative imm to abosolute address
            uint64_t rel_imm = imms[0] - macroop->address - macroop->size;
            ub.issuec({opc2c_limm_sz8, X86OPR_T1, encode_imm(rel_imm)}, {rel_imm});
            ub.issuec({opc0_stcall}, {});
            ub.issuec({opc2c_subimm_sz8, X86OPR_RSP, encode_imm(8)}, {8});
            ub.issuec({opc1c_wripcall, X86OPR_T1}, {});
            return true;
        }
    } break;
} break; // X86_INS_CALL

1.5 但是

case X86_INS_CALL: switch (oprs_type) {
    case OT_OPR0_I: {
        if (szs[0] == 8) {
            // fuck capstone change relative imm to abosolute address
            uint64_t rel_imm = imms[0] - macroop->address - macroop->size;
            ub.issuec({opc2c_limm_sz8, X86OPR_T1, encode_imm(rel_imm)}, {rel_imm});
            ub.issuec({opc0_stcall}, {});
            ub.issuec({opc2c_subimm_sz8, X86OPR_RSP, encode_imm(8)}, {8});
            ub.issuec({opc1c_wripcall, X86OPR_T1}, {});
            return true;
        }
    } break;
} break; // X86_INS_CALL

这个commit就几行指令

盯了一个小时都没想明白

为啥会性能下降呢?

1.6 为啥呀

为啥会性能下降呢?

2 问题场景二

一条X86的CALL_I


原本Gem5

gem5_limm
gem5_stcall
gem5_subimm
gem5_wripcall

替换成了

就出错了

微译器

transutor_limm
transutor_stcall
transutor_subimm
transutor_wripcall

2.1 可能的解决方法

拆分这个commit!

    1. 原原原微
    1. 原原微原
    1. 原原微微
    1. 原微原原
    1. 原微原微
    1. 原微微原
    1. 原微微微
    1. 微原原原
    1. 微原原微
    1. 微原微原
    1. 微原微微
    1. 微微原原
    1. 微微原微
    1. 微微微原

全测一遍!

2.2 可能的解决方法

但是按一定的顺序

    1. 原原原微
    1. 原原微原
    1. 原微原原
    1. 微原原原
    1. 原原微微
    1. 原微原微
    1. 原微微原
    1. 微原原微
    1. 微原微原
    1. 微微原原
    1. 原微微微
    1. 微原微微
    1. 微微原微
    1. 微微微原

2.3 时间预估

\(<14次 \times 2 小时 \approx 28 机时\)

并行:\(2小时\) 😼

    1. 原原原微
    1. 原原微原
    1. 原微原原
    1. 微原原原
    1. 原原微微
    1. 原微原微
    1. 原微微原
    1. 微原原微
    1. 微原微原
    1. 微微原原
    1. 原微微微
    1. 微原微微
    1. 微微原微
    1. 微微微原

3 总结!

如果有良好的测试集的话

  • 纯傻瓜式debug!
    • commit粒度:git bisect
    • 行粒度:拆分

4 优化?

  • commit粒度:git bisect
    • 并行?且自动化?
  • 行粒度:拆分
    • 基于语义自动拆分?且自动测试?

5 谢谢