- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我编写了一个小型 Go 库 ( go-patan ),用于收集某些变量的运行最小值/最大值/平均值/标准偏差。我将它与等效的 Java 实现 ( patan ) 进行了比较,令我惊讶的是 Java 实现要快得多。我想明白为什么。
该库基本上由一个简单的数据存储和一个序列化读取和写入的锁组成。这是代码片段:
type Store struct {
durations map[string]*Distribution
counters map[string]int64
samples map[string]*Distribution
lock *sync.Mutex
}
func (store *Store) addSample(key string, value int64) {
store.addToStore(store.samples, key, value)
}
func (store *Store) addDuration(key string, value int64) {
store.addToStore(store.durations, key, value)
}
func (store *Store) addToCounter(key string, value int64) {
store.lock.Lock()
defer store.lock.Unlock()
store.counters[key] = store.counters[key] + value
}
func (store *Store) addToStore(destination map[string]*Distribution, key string, value int64) {
store.lock.Lock()
defer store.lock.Unlock()
distribution, exists := destination[key]
if !exists {
distribution = NewDistribution()
destination[key] = distribution
}
distribution.addSample(value)
}
我已经对 GO 和 Java 实现( go-benchmark-gist 、 java-benchmark-gist )进行了基准测试,到目前为止 Java 胜出,但我不明白为什么:
Go Results:
10 threads with 20000 items took 133 millis
100 threads with 20000 items took 1809 millis
1000 threads with 20000 items took 17576 millis
10 threads with 200000 items took 1228 millis
100 threads with 200000 items took 17900 millis
Java Results:
10 threads with 20000 items takes 89 millis
100 threads with 20000 items takes 265 millis
1000 threads with 20000 items takes 2888 millis
10 threads with 200000 items takes 311 millis
100 threads with 200000 items takes 3067 millis
我已经使用 Go 的 pprof 分析了程序并生成了一个调用图 call-graph 。这表明它基本上所有时间都花在 sync.(*Mutex).Lock() 和 sync.(*Mutex).Unlock() 上。
根据分析器的 Top20 调用:
(pprof) top20
59110ms of 73890ms total (80.00%)
Dropped 22 nodes (cum <= 369.45ms)
Showing top 20 nodes out of 65 (cum >= 50220ms)
flat flat% sum% cum cum%
8900ms 12.04% 12.04% 8900ms 12.04% runtime.futex
7270ms 9.84% 21.88% 7270ms 9.84% runtime/internal/atomic.Xchg
7020ms 9.50% 31.38% 7020ms 9.50% runtime.procyield
4560ms 6.17% 37.56% 4560ms 6.17% sync/atomic.CompareAndSwapUint32
4400ms 5.95% 43.51% 4400ms 5.95% runtime/internal/atomic.Xadd
4210ms 5.70% 49.21% 22040ms 29.83% runtime.lock
3650ms 4.94% 54.15% 3650ms 4.94% runtime/internal/atomic.Cas
3260ms 4.41% 58.56% 3260ms 4.41% runtime/internal/atomic.Load
2220ms 3.00% 61.56% 22810ms 30.87% sync.(*Mutex).Lock
1870ms 2.53% 64.10% 1870ms 2.53% runtime.osyield
1540ms 2.08% 66.18% 16740ms 22.66% runtime.findrunnable
1430ms 1.94% 68.11% 1430ms 1.94% runtime.freedefer
1400ms 1.89% 70.01% 1400ms 1.89% sync/atomic.AddUint32
1250ms 1.69% 71.70% 1250ms 1.69% github.com/toefel18/go-patan/statistics/lockbased.(*Distribution).addSample
1240ms 1.68% 73.38% 3140ms 4.25% runtime.deferreturn
1070ms 1.45% 74.83% 6520ms 8.82% runtime.systemstack
1010ms 1.37% 76.19% 1010ms 1.37% runtime.newdefer
1000ms 1.35% 77.55% 1000ms 1.35% runtime.mapaccess1_faststr
950ms 1.29% 78.83% 15660ms 21.19% runtime.semacquire
860ms 1.16% 80.00% 50220ms 67.97% main.Benchmrk.func1
有人可以解释为什么在 Go 中锁定似乎比在 Java 中慢得多,我做错了什么?我还在 Go 中编写了一个基于 channel 的实现,但速度更慢。
最佳答案
最好避免在需要高性能的小函数中使用 defer
,因为它很昂贵。在大多数其他情况下,没有必要避免它,因为 defer
的成本被它周围的代码所抵消。
我还建议使用 lock sync.Mutex
而不是使用指针。指针会为程序员带来少量额外工作(初始化、nil
错误),并为垃圾收集器带来少量额外工作。
关于go - 为什么在 Go 中锁定比 Java 慢得多?很多时间花在 Mutex.Lock() Mutex.Unlock(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39815723/
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我试图理解不允许“解锁一个未锁定的互斥体”将导致不可预测的行为 w.r.t Linux 内核互斥体,当我查看代码时我没有看到任何与此相关的影响。 具体来说: /** * try to promote
我在 Go 中有一个 cli 应用程序(仍在开发中),源代码中没有任何更改,也没有对依赖项进行任何更改,但突然间它开始 panic panic: sync: unlock of unlocked mu
我正在使用ThreadSanitizer进行线程分析,并且收到一条警告,该警告使我对互斥锁的工作方式的理解非常困惑。我在Debian Stretch上使用gcc 6.3。 在一个类中,在一个线程中,我
在下面的代码片段中,我不确定是否在 InterruptedException 之后将 locked 设置为 false: private static Lock lock = new Reentran
我一直在尝试确定此函数的作用,但我似乎无法在 CComModule 类的 MSDN 文档中的任何地方找到它。 谁能告诉我它是干什么用的? 最佳答案 此函数用于 DllCanUnloadNow()才能正
我在Windows上安装Jenkins 2,安装后打开一个页面,URL为: http://localhost:8080/login?from=%2F 页面的内容是这样的: 问题: 如何“解锁 Jenk
我正在编写一个必须以两种方式修改列表的程序。尽管此实现完美运行,但它未能让第二个线程获取锁: Node head = new Node(new Object(), null); public stat
在这个示例代码中 http://botan.randombit.net/manual/fpe.html 我试图在 Visual C++ 托管包装器中使用一种方法,但我一直在“解锁”时遇到编译错误这是什
我注意到,当我有一个可以大量锁定和解锁线程的算法时,我的性能会受到相当大的影响。 有什么办法可以帮助减少开销吗?使用信号量会提高/降低效率吗? 谢谢 typedef struct _treenode{
我已经在Java应用程序中创建了单例redisson实例,用于与Redis服务器进行通信。 现在,使用此重做实例,我将获得一个锁,该锁在完成某些任务后将释放。但是在调用unlock方法之后,我仍然看到
我有两个触发器的任务。第一个从任何用户的登录开始 并无限期地每3分钟运行一次。 当“在工作站上解锁”时,第二个开始。我也要运行这个 每隔10分钟触发第二次触发,并在触发后无限期触发。我有 以下与“在工
如何在 UILabel 上制作类似于“滑动解锁”文本的动画? (文本渐变为左->右动画)然后文本颜色适应背景。 最佳答案 我认为实现这个效果的关键是CALayer mask .您可以将第二个 CALa
我们在 ReentrantLock 上调用“lock()”,线程显然不应该被卡在那里。 在调用“lock()”之前使用断点进行调试时,第一个线程将在那里停止,程序指针将指向“Thread.exit()
我正在尝试使用以下代码锁定线程: Lock lock = readLock ? getLock(key).readLock() : getLock(key).writeLock(); try {
我已经能够使用来自另一个堆栈溢出问题 (iPhone "slide to unlock" animation) 的代码来制作一些“滑动解锁”样式的文本脉冲。此刻,面具从左向右移动。我想反转它,让它不再
我正在尝试解决 thread-ring问题。在每个线程中,我读取 token 值 如果不是我的,则检查是否是程序结束 如果是则结束线程 否则,再次阅读并重复 如果它是我的(即有我的 id)然后获取写锁
我对 IOS 中的 UISliders 有疑问,您可以在多大程度上自定义它们? 我想在 iPhone 中实现类似“Unlock slider”的 slider 。 但似乎 IOS 没有提供任何“标准”
我想创建一个 jquery 脚本,其工作方式类似于 iPhone 的“滑动解锁”栏。我想要 2 个 div、容器和 slider 。我希望能够将 slider 拖动到右侧,当 slider 到达容器的
可能是一个基本问题? 1) 为什么互斥量应该在同一个线程上解锁?。我们有什么具体原因吗?2) 如果我理解正确的话,为什么要保留 pthraed_mutex_lock 而 sem_wait/sem_po
我是一名优秀的程序员,十分优秀!