C++ 有哪些奇技淫巧?
的有关信息介绍如下:
ToplingDB 中一个平白无奇的奇技淫巧:名字劫持。
ToplingDB fork 自 RocksDB 并且兼容其 API,实现了脱胎换骨的改进,然而我们对 RocksDB 主体代码的改动却出奇得少。
例如点查的实现函数 DBImpl::GetImpl,除了正常的执行逻辑,还有各种 stats/timming(后面简称 stats),这些 stats 会引入一些开销,在 RocksDB 中,相比于执行链路上的主体开销,stats 引入的开销完全可以忽略。
但是 ToplingDB 大幅提升了主体部分的性能,特别是开启 zero copy 时,点查 Get 不超过 200 纳秒(多层未 compact),这样一来,stats 的开销就比较可观了,在关闭 stats 的情况下,虽然不用记录 stats,但是相应的条件判断等是需要检查的。在火焰图中,这些代码占用了超过 10% 的时间。
怎样去掉这 10% 的开销?暴力硬改代码肯定可以实现,但是这就和上游 RocksDB 产生了偏离,为以后跟进新版、合并代码制造了障碍。所以,就使用了一个平白无奇的奇技淫巧:
该技巧的原理是 C++ 名字作用域规则,优先顺序:
DBImpl::GetImpl 中引入开销的是 class PerfStepTimer 和 StopWatch,所以我们修改:
新增了一个成员模板函数 DBImpl::GetInst,其模板参数名字 PerfStepTimer 和 StopWatch 优先于 namespace rocksdb 中的相应 class。我们再定义 FakePerfStepTimer 和 FakeStopWatch,它们模仿别人的外观但实际上啥都不干,这样,我们就避免了霰弹式修改原本的 DBImpl::GetImpl。
当关闭 timming 时,那 10% 的开销就彻底消除了。
C++ 的这种名字作用域规则被很多人诟病,但是如果用好了这个规则,将会受益无穷。
【完】

