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

2024-01-10

好吧,这只是好奇心,对现实世界没有帮助。

我知道使用表达式树,您可以像常规 C# 编译器一样即时生成 MSIL。由于编译器可以决定优化,我很想问在执行期间生成的 IL 的情况如何Expression.Compile()。基本上有两个问题:

  1. 因为在编译时编译器可以产生不同的(可能略有不同)IL调试模式和发布模式,在调试模式和发布模式下构建时,编译表达式生成的 IL 有区别吗?

  2. 此外,在运行时将 IL 转换为本机代码的 JIT 在调试模式和发布模式下应该有很大不同。编译表达式也是如此吗?或者表达式树中的 IL 根本没有被抖动?

我的理解可能有错误,请指正。

Note:我正在考虑调试器分离的情况。我问的是 Visual Studio 中“调试”和“发布”附带的默认配置设置。


由于在编译时编译器可以在调试模式和发布模式下生成不同的(可能略有不同)IL,因此在调试模式和发布模式下构建时编译表达式生成的IL是否有差异?

这个问题实际上有一个非常简单的答案:不。给定两个相同的 LINQ/DLR 表达式树,如果其中一个由在发布模式下运行的应用程序编译,而另一个在调试模式下运行,则生成的 IL 不会有任何差异。无论如何,我不确定这将如何实施;我不知道其中的代码有任何可靠的方法System.Core了解您的项目正在运行调试版本或发布版本。

然而,这个答案实际上可能具有误导性。表达式编译器发出的 IL 在调试和发布版本之间可能没有差异,但在 C# 编译器发出表达式树的情况下,表达式树本身的结构在调试和发布模式之间可能会有所不同。我对 LINQ/DLR 内部结构相当熟悉,但对 C# 编译器不太了解,所以我只能说may在这些情况下会有差异(也可能没有)。

此外,在运行时将 IL 转换为本机代码的 JIT 在调试模式和发布模式下应该有很大不同。编译表达式也是如此吗?或者表达式树中的 IL 根本没有被抖动?

JIT编译器吐出的机器码不一定是vastly预优化的 IL 与未优化的 IL 不同。结果很可能是相同的,特别是如果唯一的区别是一些额外的临时值。我怀疑两者在更大、更复杂的方法中会出现更大的分歧,因为 JIT 优化给定方法所花费的时间/精力通常有上限。但听起来您似乎更感兴趣的是编译的 LINQ/DLR 表达式树的质量与在调试或发布模式下编译的 C# 代码相比如何。

我可以告诉你 LINQ/DLRLambdaCompiler执行的优化非常少——肯定比发布模式下的 C# 编译器少;调试模式可能更接近,但我认为 C# 编译器稍微更激进一些。这LambdaCompiler通常不会尝试减少临时局部变量的使用,并且条件、比较和类型转换等操作通常会使用比您预期更多的中间局部变量。我实际上只能想到三个优化does履行:

  1. 嵌套的 lambda 表达式将在可能的情况下内联(“如果可能”往往是“大多数时候”)。实际上,这可以有很大帮助。请注意,这仅在您Invoke a LambdaExpression;如果您在表达式中调用已编译的委托,则它不适用。

  2. 至少在某些情况下,省略了不必要/冗余的类型转换。

  3. 如果a的值TypeBinaryExpression (i.e., [value] is [Type]) 在编译时已知,该值可以作为常量内联。

除了 #3 之外,表达式编译器不进行“基于表达式”的优化;也就是说,它不会分析表达式树来寻找优化机会。列表中的其他优化在很少或没有关于树中其他表达式的上下文的情况下进行。

通常,您应该假设编译的 LINQ/DLR 表达式生成的 IL 的优化程度远低于 C# 编译器生成的 IL。然而,生成的 IL 代码有资格进行 JIT 优化,因此很难评估现实世界的性能影响,除非您实际尝试使用等效代码来测量它。

One of the things to keep in mind when composing code with expression trees is that, in effect, you are the compiler1. LINQ/DLR trees are designed to be emitted by some other compiler infrastructure, like the various DLR language implementations. It's therefore up to you to handle optimizations at the expression level. If you are a sloppy compiler and emit a bunch of unnecessary or redundant code, the generated IL will be larger and less likely to be aggressively optimized by the JIT compiler. So be mindful of the expressions you construct, but don't fret too much. If you need highly optimized IL, you should probably just emit it yourself. But in most cases, LINQ/DLR trees perform just fine.


1 If you have ever wondered why LINQ/DLR expressions are so pedantic about requiring exact type matching, it's because they are intended to serve as a compiler target for multiple languages, each of which may have different rules regarding method binding, implicit and explicit type conversions, etc. Therefore, when constructing LINQ/DLR trees manually, you must do the work that a compiler would normally do behind the scenes, like automatically inserting code for implicit conversions.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

表达式树生成的 IL 是否经过优化? 的相关文章

  • ASP.NET MVC 中的经典 ASP (C#)

    我有一个应用程序想要 最终 转换为 ASP NET MVC 我想要进行全面的服务升级 到 ASP NET 但想要使用当前的 ASP 内容来运行当前的功能 这样我就可以在对新框架进行增量升级的同时升级小部分 该站点严重依赖于不太成熟的 VB6
  • 迭代变量并查找特定类型实例的技术

    我想迭代进程中内存中的变量 通过插件动态加载 并查找特定类型的实例 以前我可以找到特定类型 或内存中的所有类型 我可以创建类型的实例 我可以获取作为不同类型的字段包含的实例 但我无论如何都不知道只是 搜索 特定类型的实例 一种方法是使用 W
  • 为什么我不能用 `= delete;` 声明纯虚函数?

    Intro 纯虚函数使用通用语法声明 virtual f 0 然而 自 c 11 以来 有一种方法可以显式地传达non existence 特殊 成员函数的 Mystruct delete eg default constructor Q
  • 如何在 Android NDK 中创建新的 NativeWindow 而无需 Android 操作系统源代码?

    我想编译一个 Android OpenGL 控制台应用程序 您可以直接从控制台启动 Android x86 运行 或者从 Android x86 GUI 内的 Android 终端应用程序运行 这个帖子 如何在 Android NDK 中创
  • C++:重写已弃用的虚拟方法时出现弃用警告

    我有一个纯虚拟类 它有一个纯虚拟方法 应该是const 但不幸的是不是 该接口位于库中 并且该类由单独项目中的其他几个类继承 我正在尝试使用这个方法const不会破坏兼容性 至少在一段时间内 但我找不到在非常量方法重载时产生警告的方法 以下
  • Clang 编译器 (x86):80 位长双精度

    我正在尝试在 x86 Windows 平台上使用本机 80 位长双精度 海湾合作委员会选项 mlong double 80 https gcc gnu org onlinedocs gcc x86 Options html似乎不适用于 cl
  • 构造函数中显式关键字的使用

    我试图了解 C 中显式关键字的用法 并查看了这个问题C 中的explicit关键字是什么意思 https stackoverflow com questions 121162 但是 那里列出的示例 实际上是前两个答案 对于用法并不是很清楚
  • POCO HTTPSClientSession 发送请求时遇到问题 - 证书验证失败

    我正在尝试使用 POCO 库编写一个向服务器发出 HTTPS 请求的程序 出于测试目的 我正在连接到具有自签名证书的服务器 并且我希望允许客户端进行连接 为了允许这种情况发生 我尝试安装InvalidCertificateHandler这是
  • 从多个类访问串行端口

    我正在尝试使用串行端口在 arduino 和 C 程序之间进行通信 我对 C 编程有点陌生 该程序有多种用户控制形式 每一个都需要访问串口来发送数据 我需要做的就是从每个类的主窗体中写入串行端口 我了解如何设置和写入串行端口 这是我的 Fo
  • 访问者和模板化虚拟方法

    在一个典型的实现中Visitor模式 该类必须考虑基类的所有变体 后代 在许多情况下 访问者中的相同方法内容应用于不同的方法 在这种情况下 模板化的虚拟方法是理想的选择 但目前这是不允许的 那么 模板化方法可以用来解析父类的虚方法吗 鉴于
  • 如何从 C# 控制器重定向到外部 url

    我使用 C 控制器作为网络服务 在其中我想将用户重定向到外部网址 我该怎么做 Tried System Web HttpContext Current Response Redirect 但没有成功 使用控制器的重定向 http msdn
  • Azure 事件中心 - 按顺序接收事件

    我使用下面的代码从 Azure Event Hub 接收事件 https learn microsoft com en us azure event hubs event hubs dotnet framework getstarted s
  • 获取 2 个数据集 c# 中的差异

    我正在编写一个简短的算法 它必须比较两个数据集 以便可以进一步处理两者之间的差异 我尝试通过合并这两个数据集并将结果更改放入新的数据集来实现此目标 我的方法如下所示 private DataSet ComputateDiff DataSet
  • 如何一步步遍历目录树?

    我发现了很多关于遍历目录树的示例 但我需要一些不同的东西 我需要一个带有某种方法的类 每次调用都会从目录返回一个文件 并逐渐遍历目录树 请问我该怎么做 我正在使用函数 FindFirstFile FindNextFile 和 FindClo
  • 尚未处理时调用 Form 的 Invoke 时出现 ObjectDisposeException

    我们得到一个ObjectDisposedException从一个电话到Invoke在尚未处理的表格上 这是一些演示该问题的示例代码 public partial class Form2 Form void Form2 Load object
  • g++ 对于看似不相关的变量“警告:迭代...调用未定义的行为”

    考虑以下代码strange cpp include
  • 耐用功能是否适合大量活动?

    我有一个场景 需要计算 500k 活动 都是小算盘 由于限制 我只能同时计算 30 个 想象一下下面的简单示例 FunctionName Crawl public static async Task
  • 运算符“==”不能应用于“int”和“string”类型的操作数

    我正在编写一个程序 我想到了一个数字 然后计算机猜测了它 我一边尝试一边测试它 但我不断收到不应该出现的错误 错误是主题标题 我使用 Int Parse 来转换我的字符串 但我不知道为什么会收到错误 我知道它说 不能与整数一起使用 但我在网
  • 我在在线程序挑战编译器中遇到演示错误

    include
  • 使用 Crypto++ 获取 ECDSA 签名

    我必须使用 Crypto 在变量中获取 ECDSA 签名 我在启动 SignMessage 后尝试获取它 但签名为空 我怎样才能得到它 你看过 Crypto wiki 吗 上面有很多东西椭圆曲线数字签名算法 http www cryptop

随机推荐

  • 在 Node.js 中使用递归模式循环

    我一直在尝试使用 node js 迭代一系列城市 并向 google 发出迭代请求以获取每个城市的方向 然后我使用 JSON parse 来抽象驾驶时间 我需要找到一种方法来同步执行此操作 否则我将立即向谷歌请求每个城市的所有信息 我发现了
  • 如何导入位于当前工作目录中的 Python 库? [复制]

    这个问题在这里已经有答案了 我正在编写一个安装程序 它将从现有的 Python 文件中提取脚本 然后在主 Python 程序中使用它 我需要知道该怎么做是import
  • 在使用 libgdx 中的 scene2d 按钮时需要帮助

    我是 libGDX 的新手 我正在尝试通过扩展 com badlogic gdx scenes scene2d ui Button 来创建自定义按钮 我想要这个类中所有与按钮相关的逻辑 但我不知道如何使点击起作用 我阅读了许多有关添加事件侦
  • 使用 fetchone()[0] 时出现“TypeError:‘NoneType’对象不可订阅”

    我有一个问题fetchone 函数在sqlite3库对象connect 我执行的查询可能并不总是返回值 检查是否有返回值 如果它返回一个值 我使用该值将该值赋给我的变量fetchone 0 执行的代码 conn sqlite3 connec
  • SceneKit 中的自定义顶点属性

    我正在使用 SceneKit 生成一些自定义几何体 这工作正常 但我正在努力寻找一种包含自定义顶点属性的方法 具体来说 我希望每个顶点包含一个额外的 SCNVector3 我发现了很多使用 ShaderModifiers 来包含依赖于自定义
  • android:将按钮添加到应用程序的标题中?

    是否可以在应用程序标题的右上角添加一个按钮 例如 在 Feed 我的 feed 的标题中添加 刷新 按钮 http www android com market apps feedr lg 01 jpg http www android c
  • iOS 中的相机和照片库一起

    我正在创建一个应用程序 我需要在同一个屏幕上同时显示相机和照片库 屏幕的上半部分将有相机 屏幕的下半部分将有照片库 请参阅屏幕截图 另请告诉我这是否可行 如果可能 请帮助我如何做到这一点 谢谢 你尝试过Instagram http www
  • ACRA 异常 只能使用低 16 位作为 requestCode

    我的应用程序使用 ACRA 进行错误报告 并且我的设备收到了一些错误报告 Can only use lower 16 bits for requestCode Google 显示使用 startActivityForResult 时发生此错
  • 如何从 Python 中的函数返回两个值?

    我想从两个单独的变量中的函数返回两个值 例如 def select choice loop 1 row 0 while loop 1 print Choose from the following options 1 Row 1 2 Row
  • NHibernate 警告并且数据未保存

    当我通过调用 SaveOrUpdate 进行保存时 收到此警告 并且在调用 Transaction Commit 后数据未保存在数据库中 NHibernate Engine ForeignKeys 无法 确定 项目名称 是否与 分配的标识符
  • Spark DataFrame 重新分区和 Parquet 分区

    我在列上使用重新分区来将数据存储在镶木地板中 但 我看到没有 parquet 分区文件的数量与 不 Rdd 分区 rdd分区之间是否没有相关性 和镶木地板隔断 当我将数据写入镶木地板分区并使用 Rdd 时 重新分区 然后我从 parquet
  • 带有 C# 内部访问修饰符的 Doxygen

    我正在使用 Doxygen 为我正在处理的 C 项目生成一些 API 文档 我在这个项目中有相当多的 内部 功能 并且不希望 Doxygen 在它生成的生成的 html 中生成这些签名 我已尝试启用 HIDE FRIEND COMPOUND
  • macOS 中的 UIGraphicsBeginImageContextWithOptions 模拟

    以下是我用来在 iOS 中缩放图像的代码 即将 500x500 图像缩放到 100x100 图像 然后存储缩放后的副本 UIImage image UIImage originalImage scaledToSize CGSize desi
  • NaN 作为字典中的键

    谁能向我解释以下行为 gt gt gt import numpy as np gt gt gt np nan 5 np nan 5 gt gt gt float64 np nan 5 float64 np nan KeyError nan
  • 切换到共享运行时后 Office 插件加载失败

    我跟着配置您的 Office 加载项以使用共享 JavaScript 运行时 https learn microsoft com en us office dev add ins develop configure your add in
  • 如何使用searchkick根据某些条件进行索引

    我正在使用searchkick 和rails4 我有一个活动记录 People 其属性为 a b c 如何仅当 b 等于 type1 时才建立索引 否则不建立索引 目前我所知道的是 def search data a a b b c c e
  • java等待光标显示问题

    我在应用程序中显示等待光标时遇到问题 只要鼠标位于定义其自身光标的面板上方 等待光标就不会出现 如果面板不改变光标 则会出现等待光标 我附上 SSCE 来准确解释我的问题 public class BusyCursorTest extend
  • VS 2017 中的 MySQL 和 MVC 实体框架无法正常工作

    我正在尝试启动 MVC EF Visual Studio 2017 项目 我在本地实例上使用 MySQL 设置了数据连接 但是当我创建 ADO net 数据模型时 出现图中所示的错误 这里还有另一篇文章 无法对实体框架 6 使用 MySQL
  • 对数据库的访问进行队列以避免多个缓存项

    我有一个与音乐相关的 ASP NET 网站 它在第一次请求时缓存数据库中的大量静态信息 有时 应用程序负载较重时会重置应用程序并清除缓存 然后所有 http 请求都会转到数据库以检索静态数据并将其缓存以供其他请求使用 如何确保只有一个请求进
  • 表达式树生成的 IL 是否经过优化?

    好吧 这只是好奇心 对现实世界没有帮助 我知道使用表达式树 您可以像常规 C 编译器一样即时生成 MSIL 由于编译器可以决定优化 我很想问在执行期间生成的 IL 的情况如何Expression Compile 基本上有两个问题 因为在编译