2

该应用程序需要 JS 支持(程序是用 C# 编写的)并且 JINT 被用作解释器。我注意到当应用程序作为 64 位应用程序运行时性能会显着降低。

我已将其简化为以下示例,该示例说明了该问题:

Stopwatch sw = new Stopwatch();
sw.Start();

for (int i = 0; i < 1000; i++)
{
    var engine = new Jint.Engine(cfg =>
    {
        cfg.Strict(true); // Good practive for javascript
        cfg.AllowClr(); // Access to .net
        cfg.LimitRecursion(16); // Help stop broken scripts taking down application
        cfg.CatchClrExceptions(ex => ex is Exception);
    });

    try
    {
        engine.Execute(@"
              function test() 
              { 
                throw 'Error';
              };

              test();
        ");
    }
    catch (Exception) { }
}

sw.Stop();

Debug.WriteLine(sw.Elapsed);

当它被编译为 32 位应用程序时,大约需要 11 秒。当它被编译为 64 位应用程序时,大约需要 35 秒。请在实际应用程序中经常抛出异常。

有谁知道为什么会这样?

请注意,这只是在调试器下运行时出现的问题。在调试器之外,性能似乎相似。


更新#1

我一直在研究这个,现在有这个例子:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        Stopwatch sw = new Stopwatch();
        sw.Start();

        for (int i = 0; i < 20000; i++)
        {
            DefinedDotNetApi();
        }

        sw.Stop();
        MessageBox.Show(sw.Elapsed.ToString());
    }

    public static void DefinedDotNetApi()
    {
        var engine = new Jint.Engine();

        engine.SetValue("demoJSApi", new DemoJavascriptApi());

        var result = engine.Execute("demoJSApi.helloWorldFromDotNet('TestTest');demoJSApi.helloWorldFromDotNet('TestTest')").GetCompletionValue();
    }

    public class DemoJavascriptApi
    {
        public string helloWorldFromDotNet(string name)
        {
            return $"Hello {name} - this is executed in {typeof(Program).FullName}";
        }
    }
}

运行 32 位应用程序时,这比构建为 64 位应用程序时快 20-30%。

即使这样做:

    public static void DefinedDotNetApi()
    {
        var engine = new Jint.Engine();

        engine.SetValue("demoJSApi", new DemoJavascriptApi());

        // var result = engine.Execute("demoJSApi.helloWorldFromDotNet('TestTest');demoJSApi.helloWorldFromDotNet('TestTest')").GetCompletionValue();
        var result = engine.Execute("function test() { return 'test'; };test();").GetCompletionValue();
    }

因此,如果没有 .NET 回调,它在 64 位模式下仍然慢 10-20%。

有人知道为什么吗?


更新#2

此示例显示了 32 位和 64 位进程之间的速度差异。我使用 benchmarkdotnet.org 来显示差异。

public class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<JintTest>();
    }
}

[LegacyJitX86Job, LegacyJitX64Job]
[MinColumn, MaxColumn, MeanColumn, MedianColumn]
public class JintTest
{
    public JintTest()
    {
        Test();
    }

    private const string ContextString = @"/*var test1;var LineupScheduleItem1 = undefined;var LineupScheduleItem2 = undefined;var LineupScheduleItem3 = undefined;var LineupScheduleItem4 = undefined;*/";

    [Benchmark]
    public void Test()
    {
        Jint.Engine engine = new Jint.Engine(cfg =>
        {
            cfg.Strict(true); // Good practive for javascript
            cfg.AllowClr(); // Access to .net
            cfg.LimitRecursion(16); // Help stop broken scripts taking down application
            cfg.CatchClrExceptions(ex => ex is Exception);
        });

        JavaScriptParser parser = new Jint.Parser.JavaScriptParser(true);

        int maxIterations = 500;
        for (int i = 0; i < maxIterations; i++)
        {
            engine.Execute(parser.Parse(ContextString));
        }
    }
}

该脚本已全部注释掉,并且正在执行中。64 位进程大约慢 30%。脚本是否被解析似乎没有什么区别。

有谁知道为什么会这样?

4

0 回答 0