什么时候可以接受标题类库? [英] When are header-only libraries acceptable?

查看:90
本文介绍了什么时候可以接受标题类库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就我个人而言,我非常喜欢纯头文件库,但有些声称他们因为内联过多而导致代码膨胀(以及编译时间较长的其他明显问题)。



我想知道,这些说法有多少事实(有关膨胀的说法)?



此外,成本是否合理? (显然有一些不可避免的情况,例如当它是一个完全或大部分使用模板实现的库,但我更感兴趣的情况下,实际上有一个选择。)



我知道有没有硬性和快速的规则,指南等,就这样的东西,但我只是想了解别人对这个问题的想法。



p PS是的,这是一个非常模糊和主观的问题,我知道,所以我有这样的标签。

解决方案

为一个拥有自己的中间件部门的公司工作,以维护数百个由很多团队常用的图书馆。



同样的公司,我们害怕从头只有方法,并更喜欢二进制可兼容性超过性能,因为易于维护。



一般的共识是,性能增益)将不值得麻烦。



此外,所谓的代码膨胀可能对性能有负面影响,因为更多的代码将被加载到高速缓存中



在一个理想的世界里,我假设编译器和链接器可以是智能的,不能生成那些多个定义规则,但只要不是这样,我将(个人地)支持:




  • 二进制兼容性

  • 非内联(对于超过两行的方法)



为什么不测试?准备两个库(只有一个标题,另一个没有内联方法),并在YOUR的情况下检查它们各自的性能。



编辑: / strong>



jalf(感谢)指出,我应该精确地说明我的意思是完全符合二进制兼容性。



如果你可以(通常)链接到一个或另一个库,而不改变你自己的库,则给定库的2个版本是二进制兼容的。



因为您只能链接给定库目标的一个版本,所有使用目标加载的库将有效使用相同的版本...这里是此属性的传递性的原因。

  MyLib  - > Lib1(v1),Lib2(v1)
Lib1(v1) - > Target(v1)
Lib2(v1) - >目标(v1)

现在,我们需要在 / code>对于仅由 Lib2 使用的功能,我们提供了一个新版本(v2)。如果(v2)与二进制兼容(v1),则我们可以:

  Lib1(v1) - >目标(v2)
Lib2(v1) - >目标(v2)

但如果不是这样,那么我们将有:

  Lib1(v2) - >目标(v2)
Lib2(v2) - >目标(v2)



你是读的,即使 Lib1 不需要修复,你需要重新修改它的新版本 Target ,因为这个版本是必需的更新的 Lib2 可执行文件只能链接到目标的一个版本。



有了一个只有标题的库,因为你没有库,你是有效的不是二进制兼容。因此,每次你做一些修复(安全,关键bug等等),你需要提供一个新的版本,所有依赖你的库(甚至间接)将必须重新构建这个新的版本!


Personally, I quite like header-only libraries, but there are claims they cause code bloat due to over-inlining (as well as the other obvious problem of longer compile times).

I was wondering, how much truth is there to these claims (the one about bloat)?

Furthermore, are the costs 'justified'? (Obviously there are unavoidable cases such as when it's a library implemented purely or mostly with templates, however I'm more interested in the case where there's actually a choice available.)

I know there's no hard and fast rule, guideline, etc as far as stuff like this goes, but I'm just trying to get a feel for what others think on the issue.

P.S. Yes this is a very vague and subjective question, I'm aware, and so I have tagged it as such.

解决方案

I work for a company that has a "Middleware" department of its own to maintain a few hundreds of libraries that are commonly used by a great many teams.

Despite being in the same company, we shy from header only approach and prefer to favor binary compability over performance because of the ease of maintenance.

The general consensus is that the performance gain (if any) would not be worth the trouble.

Furthermore, the so called "code-bloat" may have a negative impact on performance as more code to be loaded in the cache implies more cache miss, and those are the performance killers.

In an ideal world I suppose that the compiler and the linker could be intelligent enough NOT to generate those "multiple definitions" rules, but as long as it is not the case, I will (personally) favor:

  • binary compatibility
  • non-inlining (for methods that are more than a couple of lines)

Why don't you test ? Prepare the two libraries (one header only and the other without inlining methods over a couple of lines) and check their respective performance in YOUR case.

EDIT:

It's been pointed out by 'jalf' (thanks) that I should precise what I meant exactly by binary compatibility.

2 versions of a given library are said binary compatible if you can (usually) link against one or the other without any change of your own library.

Because you can only link with one version of a given library Target, all the libraries loaded that use Target will effectively use the same version... and here is the cause of the transitivity of this property.

MyLib --> Lib1 (v1), Lib2 (v1)
Lib1 (v1) --> Target (v1)
Lib2 (v1) --> Target (v1)

Now, say that we need a fix in Target for a feature only used by Lib2, we deliver a new version (v2). If (v2) is binary compatible with (v1), then we can do:

Lib1 (v1) --> Target (v2)
Lib2 (v1) --> Target (v2)

However if it's not the case, then we will have:

Lib1 (v2) --> Target (v2)
Lib2 (v2) --> Target (v2)

Yep, you read it right, even though Lib1 did not required the fix, you head to rebuild it against a new version of Target because this version is mandatory for the updated Lib2 and Executable can only link against one version of Target.

With a header-only library, since you don't have a library, you are effectively not binary compatible. Therefore each time you make some fix (security, critical bug, etc...) you need to deliver a new version, and all the libraries that depend on you (even indirectly) will have to be rebuilt against this new version!

这篇关于什么时候可以接受标题类库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆