【问题标题】:Why is this JavaScript method outperforming my C# method?为什么这个 JavaScript 方法优于我的 C# 方法?
【发布时间】:2019-11-02 18:13:42
【问题描述】:

我目前正在测试C#JavaScript 中某些列表操作的性能,以确定两者之间的差距。

目前,我正在测试在C#JavaScript 中向列表添加元素的速度。在这里,我发现不知何故 JavaScript 的性能优于 C#,尽管我之前的研究表明 C# 应该更快一些。

C#:

            var time = Stopwatch.StartNew();
            var loops = 10000000;
            var strList = new List<string>();
            time.Start();
            for (var i = 0; i < loops; i++)
            {
                strList.Add("Loop" + i);
            }
            time.Stop();
            Console.WriteLine("TIME: " + time.ElapsedMilliseconds + "ms");

JS:

    var t0 = performance.now();
    var loops = 10000000
    strList = []
    for(var i = 0; i < loops; i++)
    {
        strList.push("Loop" + i);
    }
    var t1 = performance.now();
    console.log("TIME: " + (t1-t0) + "ms");

我注意到,当我将两种语言中的 strList.push("Loop" + i); 函数替换为 strList.push("Loop")(不带索引)时,性能大幅提升。

With index:
C#:
-3805ms

JavaScript:
- 铬:6048 毫秒
- 火狐:1248 毫秒

Without index:
C#:
-166 毫秒

JavaScript:
- 铬:348 毫秒
- 火狐:154 毫秒

总结一下,我的问题是:为什么在 Firefox 上运行 JS 时,C# 会执行 JavaScript?为什么将索引添加到列表会导致性能如此极端地下降?是否有其他方法可以更快地执行此操作?

提前致谢!

【问题讨论】:

  • "Loop" + i 是两种语言的字符串连接。这需要一些时间。
  • 您可以通过new List&lt;string&gt;(loops)strList.Capacity = loops;预设列表容量
  • 问题不在于字符串连接所花费的时间,而在于这些字符串的内存分配。它将分配1000万个字符串!这给垃圾收集器带来了很多工作!
  • 您可能会在这里得到部分答案:The Baseline Interpreter: a faster JS interpreter in Firefox 70。另外,请确保在 Release 模式(不是 Debug 模式)下运行您的 C# 代码。
  • 我在发行版中运行它,是的。我在考虑是否有可能创建一个将使用 electron.NET 的新项目时,我很想知道这些信息。所以对于这个用例来说,还有常规的 ASP.NET 和 JS 设计选择可以取决于两者的性能。例如。我应该应用客户端过滤数据,还是可能优于服务器端等。

标签: c# list performance .net-core


【解决方案1】:

有趣的是,我做了一些检查,发现您的陈述与我的发现相符(C# 实现较慢)。据我所知,目标集合的分配和循环中新值的设置有点多余,而且会占用时间。此外,循环名称中带有或不带有索引的变体较慢,因为必须再次创建字符串,尽管 string.format 或 string.concat 没有任何区别。不过,我不是 Jon Skeet,我确实想知道确切的原因。

如果您考虑使用 LINQ 方法,我的新时间约为 12 毫秒

  var time = Stopwatch.StartNew();
    var loops = 10000000; 
    time.Start();
    var strList = Enumerable.Range(0, loops).Select(i => $"Loop{i}");

    time.Stop();
    Console.WriteLine("TIME: " + time.ElapsedMilliseconds + "ms");

【讨论】:

  • AFAIK Linq 语句相当懒惰——如果你在其中添加ToList(),性能可能会完全不同......
  • 感谢您的意见!我尝试了您的 LINQ 方法,但是当使用ToList() 完成它时,不幸的是,执行时间也最终达到了 4000 毫秒左右。
  • 请注意,var strList = Enumerable.Range(0, loops).Select(i =&gt; $"Loop{i}"); 只准备枚举。它没有被执行!要执行它,您必须 foreach 它或执行 ToList 或类似的。
猜你喜欢
  • 2019-06-26
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多