了解 C# 中运行时代码生成的各种选项(Roslyn、CodeDom、Linq 表达式,...?)

2024-01-27

我正在开发一个应用程序,我想在其中动态生成数值计算的代码(为了性能)。作为数据驱动操作来执行此计算太慢。为了描述我的要求,请考虑此类:

class Simulation
{
    Dictionary<string, double> nodes;

    double t, dt;

    private void ProcessOneSample()
    {
        t += dt;
        // Expensive operation that computes the state of nodes at the current t.
    }

    public void Process(int N, IDictionary<string, double[]> Input, IDictionary<string, double[]> Output)
    {
        for (int i = 0; i < N; ++i)
        {
            foreach (KeyValuePair<string, double[]> j in Input)
                nodes[j.Key] = j.Value[i];
            ProcessOneSample();
            foreach (KeyValuePair<string, double[]> j in Output)
                j.Value[i] = nodes[j.Key];
        }    
    }
}

我想做的是 JIT 编译一个实现 Process 中的外循环的函数。定义此函数的代码将由当前用于实现 ProcessOneSample 的数据生成。为了澄清我的期望,我希望所有字典查找在编译过程中执行一次(即 JIT 编译将直接绑定到字典中的相关对象),这样当编译的代码实际上是执行后,就好像所有查找都已被硬编码。

我试图找出解决这个问题的最佳工具是什么。我问这个问题的原因是因为有很多选择:

  • 使用罗斯林。当前的障碍是如何将语法中的表达式绑定到主机程序中的成员变量(即“状态”字典中的值)。这可能吗?
  • 使用 LINQ 表达式(Expression.Compile)。
  • 使用 CodeDom。最近我在谷歌搜索中意识到了这一点,以及是什么引发了这个问题。我对于在 .Net 中跌跌撞撞地使用第三个编译框架并不太兴奋。
  • 在我知道之前我最初的计划any这些工具的其中一个功能是调用我自己 JIT 编译的本机代码 (x86)。我对此有一些经验,但是这里还有很多未知数我还没有解决。如果上述选项的性能不够,这也是我的备份选项。我更喜欢上述 3 种解决方案之一,因为我确信它们会简单得多,假设我可以让其中之一起作用!

有没有人有类似的经验可以分享?


我不确定我是否理解您的示例,并不是说代码生成是提高其性能的最佳方法。

但如果您想了解代码生成选项,请首先考虑您的要求。性能是你想要的,但是还有代码生成的性能,以及生成代码的性能。这些绝对不是同一件事。然后是代码的可写性和可读性。不同的选项在这一点上的得分差异很大。

你的第一个选择是反射.发射 http://msdn.microsoft.com/en-us/library/system.reflection.emit.aspx, 尤其动态方法 http://msdn.microsoft.com/en-us/library/system.reflection.emit.dynamicmethod.aspx。 Reflection.Emit 是一个相当低级的 API,并且非常高效(即代码生成具有良好的性能)。此外,因为您可以完全控制正在生成的代码,所以您有可能生成最有效的代码(或者显然生成非常糟糕的代码)。此外,您不受 C# 等语言允许执行的操作的限制,CLR 的全部功能都触手可及。 Reflection.Emit 的最大问题是您需要编写大量代码,并且需要深入的 IL 知识。编写该代码并不容易,之后阅读或维护它也不容易。

Linq.Expression http://msdn.microsoft.com/en-us/library/system.linq.expressions.aspx,更具体地说编译方法 http://msdn.microsoft.com/en-us/library/bb356928.aspx提供一个不错的选择。您可以将其视为本质上是使用 Reflection.Emit 生成 DynamicMethod 的类型安全包装器。生成代码会产生一些开销,这可能不是一个大问题。至于表达自由,您几乎可以做普通 C# 方法中可以做的所有事情。您无法完全控制生成的代码,但质量通常非常好。这种方法的最大优点是使用这种技术编写和读取程序要容易得多。

对于 Roslyn,您可以选择生成语法树,或者生成 C#(或 VB)并将其解析为要编译的语法树。现在猜测性能可能会如何还为时尚早,因为我们没有可用的生产代码(在撰写本文时)。显然,解析语法树会产生一些开销,如果您生成单个方法,Roslyn 并行生成多个方法的能力不会有太大帮助。不过,使用 Roslyn 可以实现非常可读的程序。

至于CodeDom,我建议不要使用。这是一个非常古老的 API,(在当前的实现中)启动 CSC.exe 进程来编译您的代码。我还认为它不支持完整的C#语言。

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

了解 C# 中运行时代码生成的各种选项(Roslyn、CodeDom、Linq 表达式,...?) 的相关文章

  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • 使用 WGL 创建现代 OpenGL 上下文?

    我正在尝试使用 Windows 函数创建 OpenGL 上下文 现代版本 基本上代码就是 创建窗口类 注册班级 创建一个窗口 choose PIXELFORMATDESCRIPTOR并设置它 创建旧版 OpenGL 上下文 使上下文成为当前

随机推荐