Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
了解C#中运行时代码生成的各种选项(Roslyn、CodeDom、Linq表达式等)_C#_Linq_Jit_Codedom_Roslyn - Fatal编程技术网

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

了解C#中运行时代码生成的各种选项(Roslyn、CodeDom、Linq表达式等),c#,linq,jit,codedom,roslyn,C#,Linq,Jit,Codedom,Roslyn,我正在开发一个应用程序,在这个应用程序中,我希望动态生成用于数值计算(性能)的代码。将此计算作为数据驱动操作进行太慢。为了描述我的需求,请考虑这个类: class Simulation { Dictionary<string, double> nodes; double t, dt; private void ProcessOneSample() { t += dt; // Expensive operation t

我正在开发一个应用程序,在这个应用程序中,我希望动态生成用于数值计算(性能)的代码。将此计算作为数据驱动操作进行太慢。为了描述我的需求,请考虑这个类:

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];
        }    
    }
}
类模拟
{
字典节点;
双t,dt;
私有void ProcessOneSample()
{
t+=dt;
//计算当前t节点状态的昂贵操作。
}
公共void进程(int N、IDictionary输入、IDictionary输出)
{
对于(int i=0;i
我想做的是JIT编译一个函数,该函数在进程中实现外部循环。定义此函数的代码将由当前用于实现ProcessOneSample的数据生成。为了澄清我的期望,我希望所有字典查找在编译过程中执行一次(即JIT编译将直接绑定到字典中的相关对象),以便在实际执行编译代码时,就好像所有查找都是硬编码的

我想弄清楚的是,解决这个问题的最佳工具是什么。我问这个问题的原因是有很多选择:

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

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

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

<>但是如果您想了解代码生成选项,首先考虑您的需求。性能是您想要的,但是还有代码生成的性能,以及生成的代码的性能。这些绝对不是一回事。然后是代码的可写性和可读性。不同的选项在这一点上的得分非常不同

你的第一个选择是,尤其是。Emit是一个非常低级的API,非常高效(即代码生成具有良好的性能)。此外,由于您可以完全控制正在生成的代码,因此您有可能生成最高效的代码(或者生成非常糟糕的代码,很明显)。此外,您不受C#等语言的限制,CLR的全部功能就在您的指尖。Reflection.Emit最大的问题是需要编写大量代码,并且需要对IL有深入的了解。编写代码并不容易,事后阅读或维护代码也不容易

,更具体地说,它提供了一个很好的替代方案。您可以将其视为使用Reflection.Emit生成DynamicMethod的基本类型安全包装。生成代码时会有一些开销,这可能不是什么大问题。至于言论自由,你几乎可以用普通的C#方法做任何事情。您无法完全控制生成的代码,但质量通常非常好。这种方法的最大优点是,使用这种技术编写和读取程序要容易得多

至于Roslyn,您可以选择生成语法树,或者生成C#(或VB)并将其解析为要编译的语法树。由于我们没有可用的生产代码(在编写本文时),所以猜测性能可能会是一种很早的方法。显然,解析语法树会有一些开销,如果您要生成一个方法,Roslyn在paralle中生成多个方法的能力将不会有多大帮助。不过,使用Roslyn有一个潜力,那就是它允许非常可读的程序


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

我不明白您将手动JIT什么。x86 asm?什么味道?我想你最好放弃这个想法。@SimonWhitehead是的,我可以生成一个本机函数来实现Process方法中描述的行为。这不是我的主要选择,我更愿意先使用其中一个.Net选项。只有当性能被证明是.Net选项中的一个问题时,我才会使用此选项。您确定这是加快代码速度的最佳方法吗?您是否测量了性能以查看字典访问是否确实存在问题?您是否考虑过更改接口(可能使用具有
double
属性的对象集合)?@svick消除字典查找并不是我尝试做的唯一一件事,这是我希望编译代码的示例。另一个大本钟