出于纯粹的教育目的,我创建了一个base58包。它将使用bitcoin base58 symbol chart对uint64
进行编码/解码,例如:
b58 := Encode(100) // return 2j
num := Decode("2j") // return 100
在创建this附带的第一个测试时:
func TestEncode(t *testing.T) {
var i uint64
for i = 0; i <= (1<<64 - 1); i++ {
b58 := Encode(i)
num := Decode(b58)
if num != i {
t.Fatalf("Expecting %d for %s", i, b58)
}
}
}
这个“天真”的实现,尝试将所有范围从uint64(从0到18,446,744,073,709,551,615)转换为base58,然后再转换回uint64,但需要花费太多时间。
为了更好地理解go如何处理并发性我想知道如何使用通道或goroutines并以最有效的方式在整个uint64范围内执行迭代?
数据是否可以通过块并行处理,如果是,如何完成此操作?
提前致谢。
更新:
在@Adrien的答案中提到,单向是使用t.Parallel(),但这仅适用于测试包时,无论如何,通过实现它我发现它明显更慢,它并行运行,但没有速度增益。
据我所知,完整uint64
可能需要数年时间,但我想要找到/现在是一个频道或goroutine可能有助于加快这一过程(使用小范围进行测试1<<16
)可能通过使用类似https://play.golang.org/p/9U22NfrXeq之类的东西作为例子。
问题不是关于如何测试包是关于什么算法,技术可以用于通过使用并发更快地迭代。
答案 0 :(得分:1)
此功能内置于Go testing
包中,格式为T.Parallel
:
func TestEncode(t *testing.T) {
var i uint64
for i = 0; i <= (1<<64 - 1); i++ {
t.Run(fmt.Sprintf("%d",i), func(t *testing.T) {
j := i // Copy to local var - important
t.Parallel() // Mark test as parallelizable
b58 := Encode(j)
num := Decode(b58)
if num != j {
t.Fatalf("Expecting %d for %s", j, b58)
}
})
}
}
答案 1 :(得分:0)
我提出了这个解决方案:
package main
import (
"fmt"
"time"
"github.com/nbari/base58"
)
func encode(i uint64) {
x := base58.Encode(i)
fmt.Printf("%d = %s\n", i, x)
time.Sleep(time.Second)
}
func main() {
concurrency := 4
sem := make(chan struct{}, concurrency)
for i, val := uint64(0), uint64(1<<16); i <= val; i++ {
sem <- struct{}{}
go func(i uint64) {
defer func() { <-sem }()
encode(i)
}(i)
}
for i := 0; i < cap(sem); i++ {
sem <- struct{}{}
}
}
基本上,启动4个worker并调用encode函数,注意/了解更多这种行为,添加一个sleep,以便数据可以打印成4个块。
此外,这些答案帮助我更好地理解并发理解:https://stackoverflow.com/a/18405460/1135424
如果有更好的方法,请告诉我。