【问题标题】:C# Compiler-as-a-Service: Mono.CSharp vs Microsoft.CSharpC# 编译器即服务:Mono.CSharp 与 Microsoft.CSharp
【发布时间】:2013-10-11 19:18:13
【问题描述】:

我希望将代码中某些基于反射的部分替换为使用动态运行时编译性能更好的部分。环顾四周,我发现 Mono 和 Microsoft 都有单独的编译器即服务解决方案:Mono.CSharpMicrosoft.CSharp

冒着提出基于意见的问题的风险,我想知道这两者的比较如何?

据我从非常肤浅的初步调查中得知,它们通常都提供 CAAS 功能。我能够使用 Microsoft.CSharp 编译一个“Hello World”类并执行它。虽然我还没有对 Mono 做同样的事情,但我假设它可以做同样的事情。

有没有人有任何经验或两者都可以评论这个问题?


编辑:我并不是要比较 Mono 的 C# 和 Microsoft 的 C# - 我们已经熟悉并使用了这两者。该问题专门针对两种 CAASCompiler-as-a-Service)解决方案。

CAAS 不是(无论如何).NET 运行时的标准部分,即还没有 System.Compile 命名空间。 Mono.CSharpMicrosoft.CSharp 这两个解决方案是 C# 的独立非标准 CAAS 解决方案。它们的界面非常不同,因此是个问题。

Mono's compiler service

Microsoft's compiler service


编辑#2:完全忘记了Roslyn(感谢@Lex Li

【问题讨论】:

  • @nvoigt,我不认为它是重复的,因为您提供的链接标题具有误导性,并不是问题的真正含义。
  • 这不是重复的,我对标题不好。查看我的更新。
  • @AmirAbiri 哦,好的,这样就搞定了。
  • Microsoft.CSharp 仍然是 CodeDom 驱动的恕我直言。 Mono.CSharp 不同。您可以将 Mono.CSharp 与 Roslyn 进行比较,但从不将其与 Microsoft.CSharp 进行比较。命名空间相似度纯属偶然,并无密切关系。
  • 我完全忘记了 Roslyn - 我前段时间读过它。我会把它添加到我的候选人名单中。

标签: c# mono compiler-as-a-service


【解决方案1】:

现在的 Microsoft.CSharp (.net 4.5) 是 C# 编译器用来为 C# 动态表达式发出绑定的 API。因此它是 C# 编译器,但非常有限。 .NET 和 Mono 都实现了相同的 API (dll),因此您可以在 .NET 上编译并在 Mono 上运行,反之亦然。

Mono.CSharp 是 Mono C# 编译器的评估器风格 API。它允许您编译任何类似 C# 文本的代码(表达式、语句、类型声明等)并执行它。它严重依赖 System.Reflection 和 System.Reflection.Emit。

这些都与 CodeDom 没有任何关系。

【讨论】:

  • 性能怎么样?我的初始测试表明,使用Microsoft.CSharp 编译的代码与静态编译的代码的性能相同(当我了解它背后的内容时,这是可以预料的)。接下来我将在Mono.CSharp 上运行相同的测试。您在这方面有何经验?
  • Microsoft.CSharp 生成的代码可以被认为与批处理编译器的输出相同。它在幕后生成 IL,它像任何其他 IL 代码一样经过 JIT 编辑
【解决方案2】:

好吧,我现在比较了Mono.CSharpMicrosoft.CSharp,结果是Mono 的版本在比较中表现不佳。

我用两个动态编译器编译了以下代码:

using System;
using CompilerServiceTest;

public class LalaDynamicImpl : ILala
{
    private static int _counter;

    public void DoLala()
    {
        _counter++;
    }
}

主程序看起来是这样的:

public interface ILala
{
    void DoLala();
}

public class LalaStaticImpl : ILala
{
    private static int _counter;

    public void DoLala()
    {
        _counter++;
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        Message("Compiling dynamic lala...");
        var lala = BuildDynamicLala();

        Message("Testing dynamic lala...");
        Test(lala);

        Message("Sleeping for 1s...");
        GC.Collect();
        Thread.Sleep(1000);

        Message("Testing static lala...");
        Test(new LalaStaticImpl());
    }

    private static void Test(ILala lala)
    {
        var watch = Stopwatch.StartNew();
        for (var i = 0; i < 1000000000; i++)
            lala.DoLala();
        Console.WriteLine(watch.Elapsed);
    }
}

在我的机器上结果是:

  • 静态编译类:1.9s
  • 使用Microsoft.CSharp编译的动态编译类:1.9s
  • Mono.CSharp编译的动态编译类:10s

结果与 Mono 团队提到的 here 以及 Marek Safar 在他的回答中提到的一致 - Microsoft.CSharp 编译器服务是实际编译器的包装器,代码的编译和优化方式与正常情况相同代码。 Mono.Csharp 编译器服务与 Mono 编译器是分开的,更像是一个“eval”机器。它不像标准编译器那样优化代码。

基本上,Mono 编译器服务似乎并不是真正用于性能关键型场景,而是用于丰富的功能、学习、测试等。

在装有 .NET 4.0 (VS 2010) 和 Mono 3.2.3 的 Windows 7 64 位机器上测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-25
    • 2015-10-17
    相关资源
    最近更新 更多