我写了一个快速而肮脏的测试来检查Go vs C#在并发查找访问方面的性能,并对结果感到惊讶。
这是一个非常简单的例子,我不是专家,但测试只是在地图上执行1,000,000次锁定/检查/添加/解锁操作,它只是单线程,因为我正在检查这些功能:< / p>
from django.utils.text import Truncator
s = "<div>Please truncate this</div>"
Truncator(s).words(2, html=True)
在C#中也是如此(通过LINQPad):
truncate = "read more %(truncated_text)s"
Truncator(s).words(2, html=True,truncate=truncate)
我总结两个集合的元素以确保它们匹配(499,999,500,000)并打印所花费的时间。结果如下:
我已经检查过无法初始化地图的大小,只能初始化容量,所以我想知道是否有什么办法可以改善Go地图的性能?
没有地图访问权限需要Go 32ms来执行1,000,000次锁定/解锁操作。
答案 0 :(得分:5)
[S] o我想知道我是否可以采取任何措施来改善围棋地图的表现?
不,没有。 Go基本上没有性能旋钮。
(请注意,Go的map
类型是一个非常通用且强大的哈希映射,它使用强加密哈希(如果可能)来防止攻击并强制随机键/迭代顺序。它是&#34 ;完全是通用的&#34;而不只是&#34;快速字典&#34;。)
完全正确:环境变量GOGC
到&#34;调和&#34; GC
答案 1 :(得分:3)
可能有一件事被忽视,并将整个练习转化为苹果和橙子:同步。在Go端,您使用Mutex,每次访问时都会转到内核。在C#端,你使用lock(){},它使用SpinLock的组合,只在需要时回退到内核调用。由于您的测试无论如何都是在单个线程中执行的,因此C#甚至不会进入内核。
在Go中不鼓励使用Mutex,而是应该使用通道进行同步。
一些建议: 1.如果要自己对地图/字典进行基准测试,请删除同步。 2.如果您希望对并发性能进行基准测试,请使用正确的构造和范例编写测试。
干杯!
答案 2 :(得分:1)
我使用Mono编译了你的C#示例,并在OS X上运行它,只是为了中和任何&#34;魔法&#34;微软可能已将其添加到Windows的Windows实现中。
对于这个特定的测试来说,C#确实比Go快,除非我们忽略了一些Go性能技巧:
dict.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
public class DictionaryTest
{
public static void Main()
{
var cache = new Dictionary<int, int>(1000000);
var sw = Stopwatch.StartNew();
for (var i = 0; i < 1000000; i++)
{
lock (cache)
{
int d;
if (cache.TryGetValue(i, out d) == false)
{
cache.Add(i, i);
}
}
}
sw.Stop();
Console.WriteLine(string.Format("{0}ms", sw.ElapsedMilliseconds));
var sum = 0L;
foreach (var kvp in cache)
{
sum += kvp.Value;
}
Console.WriteLine("Sum: " + sum);
}
}
如果您安装了Mono SDK,则可以使用mcs dict.cs
编译上述内容并使用mono dict.exe
执行。
我运行了几次,平均需要47毫秒,而Go版本的平均值为149毫秒。
答案 3 :(得分:1)
我发现如果将1000000缩小到100000,golang速度将从151.0087ms更改为10.0005ms(15.1乘以),而csharp版本从65ms更改为9ms(7.22乘以),因此这意味着golang的哈希图难以处理较大的地图?
我写了一个简单的go基准测试程序
new Vue({
//'#app' is the name of the parent componenet
el: '#app',
methods:{
// The e (can be any letter or word) here is the value that was emitted by the
// child(base-checkbox) to the parent(app)...and this case the value is Boolean
lovingVue(e){
console.log(e)
}
}
})
我得到了结果
func BenchmarkIntMapGet100(b *testing.B) {
count := 100
setupIntMap(b, count)
b.ResetTimer()
for i:=0; i<b.N; i++{
_, _ = intMap[i%count]
}
}