Page 25 - 《软件学报》2024年第6期
P. 25

陈金宝 等: DBI-Go: 动态插桩定位 Go 二进制的非法内存引用                                             2601


                 初始化开销是惊人的. 为了了解该部分比值为何如此之高, 我们将                    R i/ 大于 100 的部分单独进行分析. 通过分析发
                                                                      o
                 现, 这部分例子原生开销很小, 均不超过           10 ms, 与其相对应的    DBI-Go  的初始化开销均在     500 ms 左右, 如图  12  所
                 示, 仅在极个别例子上初始化开销超过了             1 500 ms. 这表明 DBI-Go  的初始化开销的下限在 500 ms 左右, 因此在遇
                 到原生开销很小, 只有几毫秒的测例时显得              R i/ 很大. 但实际上, 500 ms 的初始化开销是完全可以接受的.
                                                    o

                      0.8
                                            callback overhead      0.008                    init overhead
                      0.7
                                                                   0.007
                      0.6
                                                                   0.006
                      0.5
                                                                   0.005
                     密度  0.4                                      密度  0.004
                      0.3
                                                                   0.003
                      0.2                                          0.002
                      0.1                                          0.001
                       0                                             0
                            0   2   4   6   8   10  12                     0   100  200  300  400  500
                              额外开销相比与原生开销比值                                 额外开销相比与原生开销比值
                          图 10    R c/ 的核密度分布曲线                        图 11    R i/o  的核密度分布曲线
                                  o

                      3 000 000
                     DBI-Go 初始化开销 (μs)  2 000 000
                      2 500 000

                      1 500 000
                      1 000 000
                       500 000
                           0           所示. 从中看出, 单独使用措施
                           2 228  2 486  2 617  2 738  2 808  2 882  2 905  2 978  3 004  3 071  3 220  3 300  3 479  3 558  3 662  3 803  3 896  3 926  3 964  4 338  5 032  6 429
                                                         原生开销 (μs)
                                        图 12 比值大于     100  的额外初始化开销与原生开销

                 4.3   误报率测试
                    为了验证 DBI-Go    所利用的   Go  写屏障机制以及第 3.4 节中的两个措施对误报率的影响, 对这些措施进行了
                 单独或组合的测试. 在下文中, 使用“措施 1” 来代表第             3.4 节中的“过滤掉非     Go 函数” 措施; 使用“措施 2” 来代表
                 第  3.4 节中的“过滤掉   Go 运行时函数”措施; 使用“措施 3”来代表使用第            3.4 节中的“过滤掉非指针 store” 措施; 使
                 用“无”代表不使用任何措施, 直接插桩           Go  二进制中的所有     store. 我们使用 Go 的标准库和编译工具链提供的 277
                 个包, 测试方法与第 4.1 节相同.
                    最终的测试结果如表        1                         1  和  2  都没有效果. 这是因为目前     G 的二进制中都包
                 含大量的运行时管理函数以及汇编函数等非                Go  函数, 单独过滤运行时函数或者非          Go  函数无法消除在单一二进
                 制  (包) 上的误报. 从表   1  中可以看出, 同时使用措施      1  和  2  相比单独的措施  1  或 2 可以大大降低误报的包的数量,
                 但此时误报率仍然较高, 这是因为此时还没有恢复                 Go  二进制中   store  指针的语义, 仍对所有    Go 用户代码中的
                 store 进行检查. 单独使用措施     3  的误报率也较高, 原因在于       Go  运行时中有诸多违反      Go  逃逸不变式的    store, 但运
                 行时保证了其安全性. 同时使用措施           2  和措施  3  可以带来最低的误报率, 在测试的 277 个包中误报率为             0. 在测试
                 中, 措施  1  无法在措施   3  的基础上进一步降低误报, 这是因为          Go  编译器只会对 Go 函数插入写屏障, 因此使用措
                 施 3 就潜在的消除了所有非        Go 函数带来的影响. 虽然措施        1  无法在措施 3   的基础上进一步降低误报率, 但并不
   20   21   22   23   24   25   26   27   28   29   30