Vladimir Domnich
962da644af
It improves payload generation in our scenarios. Current implementation of scenarios generates single random payload at the start and then sends this same payload on every request. More realistic test is to generate unique payload for each request. However, this is an expensive operation that can easily cause a bottleneck on K6 side when we run multiple writing VUs. So instead we generate a random buffer with some extra bytes and then take slices of this buffer thus producing a random payload for each request. Signed-off-by: Vladimir Domnich <v.domnich@yadro.com>
77 lines
1.8 KiB
Go
77 lines
1.8 KiB
Go
package datagen
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"github.com/dop251/goja"
|
|
"go.k6.io/k6/js/modules"
|
|
)
|
|
|
|
type (
|
|
// Generator stores buffer of random bytes with some tail and returns data slices with
|
|
// an increasing offset so that we receive a different set of bytes after each call without
|
|
// re-generation of the entire buffer from scratch:
|
|
//
|
|
// [<----------size----------><-tail->]
|
|
// [<----------slice0-------->........]
|
|
// [.<----------slice1-------->.......]
|
|
// [..<----------slice2-------->......]
|
|
Generator struct {
|
|
vu modules.VU
|
|
size int
|
|
buf []byte
|
|
offset int
|
|
}
|
|
|
|
GenPayloadResponse struct {
|
|
Payload goja.ArrayBuffer
|
|
Hash string
|
|
}
|
|
)
|
|
|
|
// TailSize specifies number of extra random bytes in the buffer tail.
|
|
const TailSize = 1024
|
|
|
|
func init() {
|
|
rand.Seed(time.Now().UnixNano())
|
|
}
|
|
|
|
func NewGenerator(vu modules.VU, size int) Generator {
|
|
return Generator{vu: vu, size: size, buf: nil, offset: 0}
|
|
}
|
|
|
|
func (g *Generator) GenPayload(calcHash bool) GenPayloadResponse {
|
|
data := g.nextSlice()
|
|
|
|
dataHash := ""
|
|
if calcHash {
|
|
hashBytes := sha256.Sum256(data)
|
|
dataHash = hex.EncodeToString(hashBytes[:])
|
|
}
|
|
|
|
payload := g.vu.Runtime().NewArrayBuffer(data)
|
|
return GenPayloadResponse{Payload: payload, Hash: dataHash}
|
|
}
|
|
|
|
func (g *Generator) nextSlice() []byte {
|
|
if g.buf == nil {
|
|
// Allocate buffer with extra tail for sliding and populate it with random bytes
|
|
g.buf = make([]byte, g.size+TailSize)
|
|
rand.Read(g.buf) // Per docs, err is always nil here
|
|
}
|
|
|
|
result := g.buf[g.offset : g.offset+g.size]
|
|
|
|
// Shift the offset for the next call. If we've used our entire tail, then erase
|
|
// the buffer so that on the next call it is regenerated anew
|
|
g.offset += 1
|
|
if g.offset >= TailSize {
|
|
g.buf = nil
|
|
g.offset = 0
|
|
}
|
|
|
|
return result
|
|
}
|