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