我的盒子上的速度约为 200MBps。显然还有改进的空间。
type randomDataMaker struct {
src rand.Source
}
func (r *randomDataMaker) Read(p []byte) (n int, err error) {
for i := range p {
p[i] = byte(r.src.Int63() & 0xff)
}
return len(p), nil
}
你只需使用io.CopyN
产生你想要的字符串。显然你可以在进入时调整字符集或其他什么。
这个模型的好处是它只是一个io.Reader
所以你可以用它来做任何东西。
测试如下:
func BenchmarkRandomDataMaker(b *testing.B) {
randomSrc := randomDataMaker{rand.NewSource(1028890720402726901)}
for i := 0; i < b.N; i++ {
b.SetBytes(int64(i))
_, err := io.CopyN(ioutil.Discard, &randomSrc, int64(i))
if err != nil {
b.Fatalf("Error copying at %v: %v", i, err)
}
}
}
在我的 2.2GHz i7 的一个核心上:
BenchmarkRandomDataMaker 50000 246512 ns/op 202.83 MB/s
EDIT
自从我编写基准测试以来,我认为我应该做明显的改进(减少随机调用的频率)。由于对 rand 的调用减少了 1/8,它的运行速度大约提高了 4 倍,尽管它更加丑陋:
新版本:
func (r *randomDataMaker) Read(p []byte) (n int, err error) {
todo := len(p)
offset := 0
for {
val := int64(r.src.Int63())
for i := 0; i < 8; i++ {
p[offset] = byte(val & 0xff)
todo--
if todo == 0 {
return len(p), nil
}
offset++
val >>= 8
}
}
panic("unreachable")
}
新基准:
BenchmarkRandomDataMaker 200000 251148 ns/op 796.34 MB/s
EDIT 2
删除了转换为字节中的掩码,因为它是多余的。更快地获得优惠:
BenchmarkRandomDataMaker 200000 231843 ns/op 862.64 MB/s
(这比实际工作容易多了sigh)
EDIT 3
今天 irc 中出现了这个问题,所以我发布了一个库。此外,我的实际基准测试工具虽然对于相对速度很有用,但其报告不够准确。
我创建randbo https://github.com/dustin/randbo您可以在任何需要的地方重复使用它们来生成随机流。