惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
CERT Recently Published Vulnerability Notes
GbyAI
GbyAI
Google DeepMind News
Google DeepMind News
C
CXSECURITY Database RSS Feed - CXSecurity.com
AWS News Blog
AWS News Blog
V
Vulnerabilities – Threatpost
T
Tenable Blog
P
Proofpoint News Feed
C
Check Point Blog
T
The Exploit Database - CXSecurity.com
F
Full Disclosure
P
Privacy & Cybersecurity Law Blog
美团技术团队
U
Unit 42
C
Cyber Attacks, Cyber Crime and Cyber Security
阮一峰的网络日志
阮一峰的网络日志
Simon Willison's Weblog
Simon Willison's Weblog
量子位
AI
AI
Spread Privacy
Spread Privacy
Help Net Security
Help Net Security
Know Your Adversary
Know Your Adversary
IT之家
IT之家
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
P
Proofpoint News Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
LangChain Blog
I
Intezer
T
The Blog of Author Tim Ferriss
爱范儿
爱范儿
月光博客
月光博客
Recorded Future
Recorded Future
O
OpenAI News
WordPress大学
WordPress大学
Microsoft Security Blog
Microsoft Security Blog
J
Java Code Geeks
Y
Y Combinator Blog
Engineering at Meta
Engineering at Meta
S
Security @ Cisco Blogs
Recent Announcements
Recent Announcements
P
Privacy International News Feed
NISL@THU
NISL@THU
MongoDB | Blog
MongoDB | Blog
W
WeLiveSecurity
B
Blog RSS Feed
Blog — PlanetScale
Blog — PlanetScale
博客园 - Franky
Cyberwarzone
Cyberwarzone
H
Hacker News: Front Page

核桃的炼金工坊

2023 韩国游记 C++23: Flat Containers Deducing This Stateful Metaprogramming 推し、燃ゆ Customization Point Object 2020 总结 搞了个 C++ 构建系统 软件设计哲学(NOTE) Paxos Note 关于 cpp 可见性的黑魔法后门 一个关于 private member function detect 的 SFINAE 模板 User-defined conversion and Copy elision VIM and Latex Interface in C++ Compile Time Reflection in C++11 C++11内存模型 在C++17中的部分新特性 Const Reference of Pointer
Compare Between CRTP and Virtual
Hawtian Wang · 2018-10-16 · via 核桃的炼金工坊

我们平时都会使用虚函数来实现 C++ 里的运行时的多态,但是虚函数会带来很多性能上面的问题:

  1. 虚函数的调用需要额外的寻址
  2. 虚函数不能被 inline,当使用比较小的虚函数的时候会带来很严重的性能负担
  3. 需要在每个对象中维护一个额外的虚函数表

但是在有些情况下,我们就可以用一些静态的类型分发策略来带来一些性能上面的好处。

struct VirtualInterface {
  virtual void Skip(uint32_t steps) = 0;
};

struct VirtualImpl : public VirtualInterface {
  uint32_t index_;

  void Skip(uint32_t steps) override { index_ += steps; index_ %= INT_MAX; }
};

void VirtualRun(VirtualInterface* interface) {
  for (auto i = 0; i < N; i++) {
    for (auto j = 0; j < i; j++) {
      interface->Skip(j);
    }
  }
}

这里有一个很简单的例子,我们搞了一个简单的计数类来模拟这个过程。首先使用虚函数的方法去实现这个。在开了O2的情况下,运行了 3260628226 ns。

然后我们使用 CRTP 来实现:

template <typename Impl>
struct CrtpInterface {
  void Skip(uint32_t steps) { static_cast<Impl*>(this)->Skip(steps); }
};

struct CrtpImpl : public CrtpInterface<CrtpImpl> {
  void Skip(uint32_t steps) {
    index_ += steps;
    index_ %= INT_MAX;
  }

  uint32_t index_ = 0;
};

template <typename T>
void CrtpRun(CrtpInterface<T>* interface) {
  for (auto i = 0; i < N; i++) {
    for (auto j = 0; j < i; j++) {
      interface->Skip(j);
    }
  }
}

同样运行我们的代码, 29934437 ns。 显然在省去了查虚函数表,并且可以inline的情况下,程序有了更好的表现。

在具体的实现方式上,参考上面的实现就可以了…