根据Scott Meyers的说法,C++在C上闪耀的一个领域是函数对象比函数指针更快.他说这是因为函数对象是内联的,这会提高速度.
我有两个问题:
我们如何验证函数对象实际上是内联的?我们能否在实践中验证这一点?
函数对象的内联是否依赖于我们使用的编译器,还是所有编译器的行为都是这样的?
我在应用程序中观察到了很多"堆栈内省"代码,这些代码通常隐含地依赖于它们的包含方法没有内联的正确性.这些方法通常涉及到:
MethodBase.GetCurrentMethod
Assembly.GetCallingAssembly
Assembly.GetExecutingAssembly
现在,我发现围绕这些方法的信息非常混乱.我听说运行时不会内联调用GetCurrentMethod的方法,但我找不到任何相关的文档.我曾多次在StackOverflow上看过帖子,比如这个帖子,表明CLR没有内联交叉汇编调用,但GetCallingAssembly
文档强烈指出不是这样.
还有备受诟病的人[MethodImpl(MethodImplOptions.NoInlining)]
,但我不确定CLR是否认为这是"请求"或"命令".
请注意,我要求从合同的角度来概述资格,而不是当前JITter的实施由于实施困难而拒绝考虑方法,或者JITter最终在评估交易后最终选择内联合格方法时权衡.我已经阅读了这个和这个,但他们似乎更关注最后两点(有传递提到的MethodImpOptions.NoInlining和"异国情调的IL指令",但这些似乎是作为启发而不是义务呈现).
什么时候CLR 允许内联?
在C++中,我可以声明一个方法"内联",编译器可能会内联它.据我所知,Java中没有这样的关键字.
如果JVM决定这样做,内联就完成了吗?我能以某种方式影响这个决定吗?
以C++编写的一个数值软件的以下关键循环基本上将两个对象的成员比较:
for(int j=n;--j>0;)
asd[j%16]=a.e<b.e;
Run Code Online (Sandbox Code Playgroud)
a
和b
是类ASD
:
struct ASD {
float e;
...
};
Run Code Online (Sandbox Code Playgroud)
我正在调查将此比较放在轻量级成员函数中的效果:
bool test(const ASD& y)const {
return e<y.e;
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
for(int j=n;--j>0;)
asd[j%16]=a.test(b);
Run Code Online (Sandbox Code Playgroud)
编译器正在内联这个函数,但问题是,汇编代码会有所不同,导致运行时开销超过10%.我要问:
为什么编译器会推出不同的汇编代码?
为什么生产的组件更慢?
编辑: 第二个问题已通过实施@ KamyarSouri的建议(j%16)得到了回答.汇编代码现在看起来几乎相同(请参阅http://pastebin.com/diff.php?i=yqXedtPm).唯一的区别是第18,33,48行:
000646F9 movzx edx,dl
Run Code Online (Sandbox Code Playgroud)
此图表显示了我的代码的50个测试的FLOP/s(最多为缩放因子).
用于生成绘图的gnuplot脚本:http://pastebin.com/8amNqya7
编译器选项:
/ Zi/W3/WX-/MP/Ox/Ob2/Oi/Ot/Oy/GL/D"WIN32"/ D"NDEBUG"/ D"_CONSOLE"/ D"_UNICODE"/ D"UNICODE"/ Gm-/EHsc/MT/GS-/Gy/arch:SSE2/fp:exact/Zc:wchar_t/Zc:forScope/Gd/analyze-
链接器选项:/ INCREMENTAL:NO"kernel32.lib""user32.lib""gdi32.lib""winspool.lib""comdlg32.lib""advapi32.lib""shell32.lib""ole32.lib""oleaut32. lib""uuid.lib""odbc32.lib""odbccp32.lib"/ ALLOWISOLATION/MANIFESTUAC:"level ='asInvoker'uiAccess ='false'"/ SUBSYSTEM:CONSOLE/OPT:REF/OPT:ICF/LTCG/TLBID …
我有一种独特的情况.我一直在开发一个用于发送电子邮件的开源库.在这个库中,我需要一种可靠的方法来获取调用方法.我StackTrace
通过分析其中的StackFrame
对象来做到这一点.这在调试模式项目中没有问题,其中优化已关闭.
当我切换到启用优化的发布模式时,会出现问题.堆栈跟踪如下所示:
> FindActionName at offset 66 in file:line:column <filename unknown>:0:0
> Email at offset 296 in file:line:column <filename unknown>:0:0
> CallingEmailFromRealControllerShouldFindMailersActionName at offset 184
in file:line:column <filename unknown>:0:0
> _InvokeMethodFast at offset 0 in file:line:column <filename unknown>:0:0
> InvokeMethodFast at offset 152 in file:line:column <filename unknown>:0:0
...
Run Code Online (Sandbox Code Playgroud)
这是从失败的单元测试中获得的.在这个跟踪的第3行中,我应该看到一个被称为TestEmail
在其他地方定义的方法,但我相信JITter正在内联它.我已经读过你可以通过使方法虚拟来防止内联,但这不起作用.有没有人知道一种可靠的方法来防止方法内联,所以你的方法会出现在堆栈跟踪中?
我需要从c#中的样式表内联css.
就像这是如何工作的.
http://www.mailchimp.com/labs/inlinecss.php
css很简单,只是类,没有花哨的选择器.
我使用的是正则表达式考虑(?<rule>(?<selector>[^{}]+){(?<style>[^{}]+)})+
剥离从CSS规则,然后尝试做简单的字符串替换所在班被称为,但一些HTML元素已经有一个风格的标签,所以我必须说明,作为好.
有更简单的方法吗?或者已经用c#写的东西?
如果您的html也是有效的xml,我已经能够提出一个简单的CSS内联器.它使用正则表达式来获取<style />
元素中的所有样式.然后将css选择器转换为xpath表达式,并在任何预先存在的内联样式之前将样式内联添加到匹配元素.
注意,CssToXpath没有完全实现,有些东西它不能做......但是.
CssInliner.cs
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Xml.XPath;
namespace CssInliner
{
public class CssInliner
{
private static Regex _matchStyles = new Regex("\\s*(?<rule>(?<selector>[^{}]+){(?<style>[^{}]+)})",
RegexOptions.IgnoreCase
| RegexOptions.CultureInvariant
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
public List<Match> Styles { get; private set; }
public string InlinedXhtml { get; private set; }
private XElement XhtmlDocument { get; set; }
public CssInliner(string xhtml)
{
XhtmlDocument = ParseXhtml(xhtml);
Styles = GetStyleMatches(); …
Run Code Online (Sandbox Code Playgroud) 假设我有这样一个类:
class ApplicationDefs{
public static final String configOption1 = "some option";
public static final String configOption2 = "some other option";
public static final String configOption3 = "yet another option";
}
Run Code Online (Sandbox Code Playgroud)
我的应用程序中的许多其他类都使用这些选项.现在,我想单独更改其中一个选项并仅部署已编译的类.但是,如果这些领域在消费者类中被列入,这就变得不可能了吗?
是否有任何选项可以禁用编译时常量的内嵌?
文档说,
有时您想要在GHC的管道中准确控制INLINE编译指示何时打开.
我为什么要这个?(除非我也使用RULES编译指示,在这种情况下,我可能希望推迟函数的内联,以便触发相关规则.)只有在简化过程的特定阶段才能更好地内联哪些函数?
我知道:
在命令式语言(如C)中,两者之间存在区别,其中运算符与函数不同.但是,在Haskell这样的函数式语言中,两者之间是否存在差异?运算符也是函数?
两者之间的唯一区别是功能内联可以在程序的选择部分上执行,而部分评估是在整个程序上执行的(即?
vs ?
)?
两种优化技术之间的语义差异是什么?
optimization haskell functional-programming inlining compiler-optimization