Tag: 编译器优化

当C#编译器的内容具有Conditional属性时,它是否会优化foreach块?

我正在编写一些调试代码,我想知道我在做什么可能会损害性能。 我们来看看代码: foreach (var item in aCollection) Debug.WriteLine(item.Name); 我知道Debug类使用Conditional属性来避免在发布模式下编译(或者每当DEBUG未定义时),但是当在发布模式下编译时,这最终会成为无用/空迭代,还是会被编译器优化?

避免.NET Native bug

我花了去年(兼职)将我现有的(并且成功的)Windows 8.1应用程序迁移到Windows 10 UWP。 现在,在将其发布到商店之前,我在“发布”构建模式(触发.NET Native)中测试了应用程序。 一切似乎都有效,直到我 – 偶然 – 注意到一个微妙但严重(因为数据妥协)的错误。 我花了两天时间将其缩减为这三行代码: var array1 = new int[1, 1]; var array2 = (int[,])array1.Clone(); array2[0, 0] = 666; if (array1[0, 0] != array2[0, 0]) { ApplicationView.GetForCurrentView().Title = “OK.”; } else { ApplicationView.GetForCurrentView().Title = “Bug.”; } 在调试模式下,克隆2D数组意味着修改一个数组项不会影响另一个数组。 在释放模式下,修改一个arrays也会改变另一个arrays。 (我正在使用最新的VS 2017.) 现在,我意识到使用.NET Native 1.6(这不是VS 2017中的默认设置),解决了这个特殊问题。 但我失去了对.NET Native的信心。 .NET Native仍然在我的应用程序中引入了多少错误? […]

符合条件的C#编译器是否可以优化本地(但未使用)变量(如果它是对象的唯一强引用)?

另请参阅以下相关资源: .NET垃圾收集器是否执行代码的预测分析? (在Stack Overflow上) WP7:GC何时将局部变量视为垃圾 (MSDN上的博客文章) 换一种说法: 可以在变量超出范围之前回收局部变量引用的对象(例如,因为变量已分配,但之后不再使用),或者该变量在变量退出之前保证不符合垃圾收集条件。范围? 让我解释: void Case_1() { var weakRef = new WeakReference(new object()); GC.Collect(); // <– doesn't have to be an explicit call; just assume that // garbage collection would occur at this point. if (weakRef.IsAlive) … } 在这个代码示例中,我显然必须计划垃圾收集器回收新object的可能性; 因此if语句。 (请注意,我使用weakRef的唯一目的是检查新object是否仍然存在。) void Case_2() { var unusedLocalVar = new object(); var […]

是否存在技术原因,C#不发出“尾部。”CIL指令?

可能重复: 为什么.net / C#没有消除尾递归? 请使用以下C#代码: using System; namespace TailTest { class MainClass { public static void Main (string[] args) { Counter(0); } static void Counter(int i) { Console.WriteLine(i); if (i < int.MaxValue) Counter(++i); } } } C#编译器(无论如何)都会将Counter方法编译成以下CIL: .method private static hidebysig default void Counter (int32 i) cil managed { .maxstack 8 IL_0000: ldarg.0 IL_0001: call […]

CLR编译器优化的示例

我在几个月内就.Net性能和优化做了一个演示,我想提供一些不必要的优化样本,无论如何都要由编译器完成。 我在哪里可以找到关于编译器在代码之前和之后实际能够进行哪些优化的一些解释?

由于缓存委托,c#编译器的奇怪行为

假设我有以下程序: static void SomeMethod(Func otherMethod) { otherMethod(1); } static int OtherMethod(int x) { return x; } static void Main(string[] args) { SomeMethod(OtherMethod); SomeMethod(x => OtherMethod(x)); SomeMethod(x => OtherMethod(x)); } 我无法理解编译的il代码(它使用太多额外的代码)。 这是简化版: class C { public static C c; public static Func foo; public static Func foo1; static C() { c = new C(); } C(){} […]

.Max()vs OrderByDescending()。First()

这纯粹是出于我自己的知识,如果我要编写我将使用的代码.Max() 。 一开始以为.Max()只需要通过numbers来传递numbers来查找最大值,而第二种方法必须对可枚举的整个事物进行排序然后找到第一个。 所以它是O(n) vs O(n lg n) 。 但后来我想也许它知道它只需要最高,只是抓住它。 问题: LINQ和/或编译器是否足够智能,以确定它不需要对整个可枚举进行排序,并将代码缩小到与.Max()基本相同的位置? 有一种可量化的方法可以找到答案吗? IEnumerable numbers = Enumerable.Range(1, 1000); int max = numbers.Max(); int max2 = numbers.OrderByDescending(x => x).First();

禁用特定函数或代码块的编译器优化(C#)

编译器在优化RELEASE构建方面做得很好,但有时候确保为本地函数关闭优化(但不是通过取消Project Options > Optimize code来关闭整个项目)。 在C ++中,这可以通过以下方式实现( #pragma通常已注释掉): #pragma optimize( “”, off ) // Some code such as a function (but not the whole project) #pragma optimize( “”, on ) C#中有等价的吗? UPDATE 几个优秀的答案建议使用MethodImplOptions.NoOptimization装饰方法。 这是在.NET 3.5中实现的,但不是在Compact Framework(CF)版本中。 一个相关的后续问题是,是否相当于: * projects targeting .NET 3.0 or earlier? * projects deployed to a device such as Windows CE 6.0 […]

表达树生成的IL是否经过优化?

好吧,这只是好奇心,没有现实世界的帮助。 我知道使用表达式树,您可以像常规C#编译器一样动态生成MSIL。 由于编译器可以决定优化,我很想知道在Expression.Compile()期间生成的IL是什么情况。 基本上有两个问题: 因为在编译时编译器可以在调试模式和释放模式下产生不同的(可能是略微的)IL,在调试模式和发布模式下构建时通过编译表达式生成的IL是否存在差异? 此外,在运行时将IL转换为本机代码的JIT在调试模式和发布模式下都应该有很大的不同。 编译表达式也是如此吗? 或者来自表达树的IL根本没有被咬过? 我的理解可能有缺陷,请纠正我以防万一。 注意:我正在考虑分离调试器的情况。 我问的是Visual Studio中“debug”和“release”附带的默认配置设置。

为什么.NET JIT编译器决定不内联或优化对没有副作用的空静态方法的调用?

我认为我正在观察.NET JIT编译器没有内联或优化对没有副作用的空静态方法的调用,考虑到一些直言不讳的在线资源,这有点令人惊讶。 我的环境是x64,Windows 8.1,.NET Framework 4.5上的Visual Studio 2013。 鉴于这个简单的测试程序( https://ideone.com/2BRCpC ) class Program { static void EmptyBody() { } static void Main() { EmptyBody(); } } 通过优化上述程序的发布版本为Main和EmptyBody生成以下MSIL: .method private hidebysig static void Main() cil managed { .entrypoint // Code size 6 (0x6) .maxstack 8 IL_0000: call void Program::EmptyBody() IL_0005: ret } // end of method […]