Continue to create, accelerate growth! This is the first day of my participation in the "Nuggets Daily New Plan · June Update Challenge", click to view the details of the event
I'm not sure if you've seen this form
Haven't seen it, consider collecting it
operate | Delay |
---|---|
execute an instruction | 1 ns |
L1 cache query | 0.5 ns |
Branch mispredict | 3 ns |
L2 cache query | 4 ns |
Mutex lock/unlock | 17 ns |
Send 2KB over a 1Gbps network | 44 ns |
main memory access | 100 ns |
Zippy compresses 1KB | 2,000 ns |
Read 1 MB sequentially from memory | 3,000 ns |
SSD random read | 16,000 ns |
Read 1 MB sequentially from SSD | 49,000 ns |
Round trip to the same data center | 500,000 ns |
Read 1 MB sequentially from disk | 825,000 ns |
disk addressing | 2,000,000 ns (2 ms) |
Packets sent from the US to Europe | 150,000,000 ns(150 ms) |
But sometimes just knowing these concepts is not enough
Since many times our choice is not between network transmission, memory, and hard disk, we certainly know that memory is greater than hard disk. This article is mainly to discuss the time-consuming of channels , atomic operations , and locks in the go language. First, we need to define the time-consuming. We define two coroutines to consume resources, and record the time-consuming after consuming 10,000 resources.
The test code is as follows:
// 通道
func Bgo(ch chan int, cnt chan int) {
for {
select {
case a := <-ch:
ch <- a + 1
if a >= 10000 {
cnt <- a + 1
return
}
case <-time.After(1 * time.Second):
cnt <- 7777
return
}
}
}
// 原子操作
func Cgo(count *int64) {
for {
atomic.AddInt64(count, 1)
if *count > 10000 {
return
}
}
}
// 锁
func Dgo(count *int64) {
defer lock.Unlock()
for {
lock.Lock()
*count = *count + 1
if *count > 10000 {
return
}
lock.Unlock()
}
}
复制代码
Recording time:
start = time.Now().UnixMicro()
ch <- 1
go Bgo(ch, cnt)
go Bgo(ch, cnt)
fmt.Println(<-cnt)
fmt.Println(time.Now().UnixMicro() - start)
// 两个协程原子操作
start = time.Now().UnixMicro()
var count int64 = 1
go Cgo(&count)
Cgo(&count)
fmt.Println(time.Now().UnixMicro() - start + count - 10001)
fmt.Println(count)
// 两个协程Mutex
start = time.Now().UnixNano()
var count1 int64 = 1
go Dgo(&count1)
Dgo(&count1)
fmt.Println(time.Now().UnixNano() - start + count1 - 10001)
fmt.Println(count1)
复制代码
in conclusion
From the conclusion, the time-consuming of the channel is the highest, the atomic operation is in the microsecond level, and the lock fluctuation is relatively large, and sometimes the nanosecond level cannot be counted.
This is also one of the reasons for this article. In my impression, the lock itself should not take so little time. Hope you guys can correct me.