问题标签 [inlining]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
css - 缓存的 CSS 文件的含义是什么?
具体来说,浏览器是否只缓存样式表的文本内容——因此它不必再次从网络中获取它——或者它是否还在解析后缓存它所包含的 CSS 规则的内部表示,因此既不获取也不获取需要解析缓存文件吗?
如果只缓存文本内容,缓存样式表比内联样式表有什么好处(不能缓存的地方)?
c++ - 侵入式数据结构中的成员钩子与基本钩子
我正在编写一个侵入式数据结构,并且想知道是使用基本挂钩还是成员挂钩。由于代码将被多次调用,我的问题是关于性能以及编译器能够在多大程度上内联此类代码。
基本钩子基于继承,而成员钩子通过模板参数使用指向成员的指针。我的设计选择是使用成员钩子,但我的经验表明,指针比静态代码更难优化。另一方面,所有这些指针在编译时都是已知的,也许编译器可以做一些魔术来分析正在发生的事情。
有没有人有这方面的经验?欢迎任何数据、提示或参考。
c++ - 使非 constexpr 整数值适应非类型模板参数和代码膨胀
F
考虑一个带constexpr size_t
参数的函数对象I
包裹在 typesize <I>
中,其中(为简洁起见)
当然,我们可以I
直接传递,但我想强调它是 constexpr,将其用作模板参数。函数F
在这里是虚拟的,但实际上它可以做各种有用的事情,比如从I
元组的第 th 元素中检索信息。F
假定无论I
. I
可以是任何整数类型,但假定为非负数。
问题
给定一个constexpr size_t
值,I
我们可以调用F
现在,如果我们想F
用非 consteprsize_t
值调用i
怎么办?考虑以下:
(我为什么需要这个?为了给出一些上下文,我实际上是在尝试将复合迭代器构建到一个容器视图中,该视图表示一系列“连接”(连接)异构容器。这将能够说出类似join(a, b) = c;
where数组join(a, b)
和c
长度相等。但是,i
迭代器状态是不是这样constexpr
,但子迭代器存储在元组中,需要通过constexpr
索引访问。个体value_type
的大致一致,因此连接视图可以采用它们的 common_type
类型,但是子容器和子迭代器是不同的类型。)
解决方案
在这里,我提出了 struct idx <F, L>
,它为此目的调整函数F
,假设输入参数小于L
. 这实际上可以很好地编译输出
这是一个活生生的例子。
idx
通过递归地将输入分解i
为二进制表示并重建 constexpr 对应项来工作N
:
其中R
表示2
当前迭代的幂。为了避免无限的模板实例化,对 进行了专门化N >= L
,返回F()(size <0>())
一个虚拟值:
事实上,这种方法是更常见的带有布尔参数的成语的概括:
其中f
是一个将 abool
作为模板参数的函数。在这种情况下,很明显所有两个可能的版本f
都被实例化了。
问题
尽管这可行,并且它的运行时复杂性可能是对数i
,但我担心编译时的影响,例如:
有多少
idx
和 它的组合template operator()
被实例化,以便在运行时为i
编译时未知的任何输入工作?(我再次理解“所有可能”,但有多少?)真的可以内联
operator()
吗?是否有任何“更容易”编译的替代策略或变体?
我应该忘记这个想法作为纯代码膨胀的实例吗?
笔记
以下是我针对不同值测量的编译时间(以秒为单位)和可执行文件大小(以 KB 为单位)L
:
因此,尽管它在 中看起来大致呈线性L
,但它相当长且大得令人沮丧。
尝试强制operator()
内联失败:可能被 Clang 忽略(可执行文件更大),而 GCC 报告recursive inlining
.
在可执行文件上运行nm -C
,例如 for L = 160
,显示511/1253
不同版本的operator()
(使用 Clang/GCC)。这些都是为了N < L
,所以看起来终止的专业化N >= L
确实被内联了。
附言。我会添加标签code-bloat
,但系统不会让我。
haskell - 定义没有 INLINE/INLINABLE 杂注
我正在尝试对紧密内部循环中使用的方法进行专门化,但 GHC 抱怨以下内容:
但是,它显然是使用 -O 构建的:
很明显,我确实有 INLINABLE 编译指示:
那么我做错了什么?
c++ - 为什么 C++ 内联函数有调用指令?
我读到内联函数,无论何时进行函数调用,我们都将函数调用替换为函数定义的主体。
根据上面的解释,当inline
是用户时不应该有任何函数调用。
如果是这样,为什么我call
会在汇编代码中看到三个指令?
笔记
目标文件的完整转储在这里
c# - 我需要担心 Unity/C# 中的内联吗?
为了代码清晰,我有时会创建一个很明显应该内联的函数,它可以是包装器,也可以是仅在单点调用的函数,或者是应该经常调用且速度很快的短函数。
在 CI 中会不加思索地内联它,但在 Unity/C# 中没有办法做到这一点 AFAIK(这似乎只在 .NET 4.5 上可用)。
我是否可以相信编译器足够聪明以实际巧妙地内联,或者我最好有时为了性能而牺牲代码清晰度,不信任编译器?
当然这取决于具体情况,过早的优化是邪恶的,你应该分析而不是猜测。然而,这个主题的一般概述可能仍然可以作为指导,以进行改进。
javascript - Chrome JS Profiler 和“未优化:内联救助”警告
我尝试使用 Chrome JS Profiler 记录 CPU 使用率来运行我的应用程序,但我收到了一些警告,有一些“ForInStatement 不是快速案例”,我已修复,但我得到了“Inlining Bailed Out”警告,例如在此代码中:
该函数基本上创建了一个障碍物(display(obstacles[i]) 绘制了障碍物的特定图像 - 由于上面提到的“ForInStatement”警告,两个单独的函数用于加载和代码)。
消息“Inlining Bailed Out”随机出现,尤其是当我玩超过一分钟时,它出现在 move_loader、display_loader 或 collision_loader 函数中。有时会,有时不会。
你能给我任何文字解释'这条消息的真正含义吗?我在网上阅读了很多帖子,并且了解“ForInStatement”逻辑,但我对内联救助一无所知。
另外,你能告诉我如何解决它吗?
谢谢!
c++ - 如何在 C++ 中清晰地生成内联结果
我一直在阅读 Scott Meyers 的Effective C++,更具体地说是关于内联的第 30 条。
所以我写了以下内容,试图用 gcc 4.6.3 进行优化
并使用以下替代方法生成相关组件:
就内联方法而言,这两个命令都生成了相同的程序集;我可以看到max()
方法体(也有一个cmpl
语句和相关的跳转)及其从foo()
.
我错过了一些非常明显的东西吗?我不能说我浏览了 gcc 手册页,但找不到任何相关的突出内容。
所以,我只是将-O3
默认情况下内联优化的优化级别提高到了,根据:
不幸的是,这个优化的(如预期的那样)上面的代码片段几乎不存在了。
max()
不再存在(至少作为显式标记的装配块)并且foo()
已减少为:
我目前无法清楚地理解(并且超出了研究范围)。
理想情况下,我希望看到的是块max()
内部的汇编代码。foo()
有没有办法(通过命令行选项或使用不同的(非平凡的?)代码片段)来产生这样的输出?
visual-studio - MSVC 2013 可以从单独的目标文件内联调用 x64 汇编代码吗?
我在 MSVC 上学习 x64 汇编。x64 代码中不允许内联汇编。我在一个单独的文件中写了一个非常简单的浮点函数:
然后我从 C++ 调用我的函数:
在发布模式下编译,/O2
优化并/LTCG
启用,我的反汇编可执行文件如下所示:
但是,如果我用 C++ 编写相同的函数,它会被转换为一条内联mulsd
指令。
(实际上,我不得不返回结果main
以避免使整个程序成为空操作,并随机化输入变量以防止编译器在编译时计算结果。)
对于希望通过手写汇编优化代码的程序员来说,这似乎是一个非常严重的缺陷。如果 MSVC 不能内联它,那么除非您在程序集中进行大量工作,否则函数调用开销可能不值得。
有没有办法让 MSVC 内联我缺少的手写程序集?
编辑:我知道使用堆栈的更复杂的汇编函数可能更难以内联,但是仅使用易失性寄存器的简单事情应该真的很容易......对吗?
visual-studio-2013 - 与 Extract Method 重构相反
有没有办法在 Visual Studio 中执行与“提取方法”重构相反的操作?
我有一个遗留代码库,它有大约 50 个非常短的私有函数,每个函数只使用一次,我的任务是内联它们。
如果无法进行自动内联重构,是否可以减少内联这些函数调用所需的时间?我目前的工作流程是:
- 复制函数中的代码。
- 找到它被调用的地方。
- 用复制的代码替换函数调用。
- 替换函数中的局部变量名称。
- 删除函数。