类似于[a-zA-Z0-9]字符串:
na1dopW129T0anN28udaZ
或十六进制字符串:
8c6f78ac23b4a7b8c0182d
长期以来,我的意思是2K和更多字符。
这在我的盒子上大约有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.CopyN
这个模型的好处是,它只是一个,io.Reader因此您可以使用它制作任何东西。
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
编辑
自从编写基准测试以来,我认为我会做一些明显的改进(减少对随机性的呼唤)。使用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
编辑2
因为它是多余的,所以在强制转换为字节时使用了掩码。更快地得到了很多:
BenchmarkRandomDataMaker 200000 231843 ns/op 862.64 MB/s
(这是这么多比真正的工作更容易 叹息 )
编辑3
这是今天在irc中提出的,所以我发布了一个库。另外,我的实际基准测试工具虽然对相对速度有用,但其报告不够准确。
我创建了randbo,您可以在需要它们的地方重复使用它们以产生随机流。