Skip to content

Commit

Permalink
Added more benchmarks and cleaned up
Browse files Browse the repository at this point in the history
  • Loading branch information
kelindar committed Oct 23, 2021
1 parent cd531f7 commit 436f94e
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 72 deletions.
108 changes: 50 additions & 58 deletions commit/buffer.go
Expand Up @@ -141,72 +141,64 @@ func (b *Buffer) PutAny(op OpType, idx uint32, value interface{}) {

// PutUint64 appends a uint64 value.
func (b *Buffer) PutUint64(op OpType, idx uint32, value uint64) {
b.writeChunk(idx)
delta := int32(idx) - b.last
b.last = int32(idx)
if delta == 1 {
delta := b.writeChunk(idx)
switch delta {
case 1:
b.buffer = append(b.buffer,
byte(op)|size8|isNext,
byte(value>>56), byte(value>>48), byte(value>>40), byte(value>>32),
byte(value>>24), byte(value>>16), byte(value>>8), byte(value),
)
return
default:
b.buffer = append(b.buffer,
byte(op)|size8,
byte(value>>56), byte(value>>48), byte(value>>40), byte(value>>32),
byte(value>>24), byte(value>>16), byte(value>>8), byte(value),
)
b.writeOffset(uint32(delta))
}

b.buffer = append(b.buffer,
byte(op)|size8,
byte(value>>56), byte(value>>48), byte(value>>40), byte(value>>32),
byte(value>>24), byte(value>>16), byte(value>>8), byte(value),
)
b.writeOffset(uint32(delta))
}

// PutUint32 appends a uint32 value.
func (b *Buffer) PutUint32(op OpType, idx uint32, value uint32) {
b.writeChunk(idx)
delta := int32(idx) - b.last
b.last = int32(idx)
if delta == 1 {
delta := b.writeChunk(idx)
switch delta {
case 1:
b.buffer = append(b.buffer,
byte(op)|size4|isNext,
byte(value>>24), byte(value>>16), byte(value>>8), byte(value),
)
return
default:
b.buffer = append(b.buffer,
byte(op)|size4,
byte(value>>24), byte(value>>16), byte(value>>8), byte(value),
)
b.writeOffset(uint32(delta))
}

b.buffer = append(b.buffer,
byte(op)|size4,
byte(value>>24), byte(value>>16), byte(value>>8), byte(value),
)
b.writeOffset(uint32(delta))
}

// PutUint16 appends a uint16 value.
func (b *Buffer) PutUint16(op OpType, idx uint32, value uint16) {
b.writeChunk(idx)
delta := int32(idx) - b.last
b.last = int32(idx)
if delta == 1 {
delta := b.writeChunk(idx)
switch delta {
case 1:
b.buffer = append(b.buffer, byte(op)|size2|isNext, byte(value>>8), byte(value))
return
default:
b.buffer = append(b.buffer, byte(op)|size2, byte(value>>8), byte(value))
b.writeOffset(uint32(delta))
}

b.buffer = append(b.buffer, byte(op)|size2, byte(value>>8), byte(value))
b.writeOffset(uint32(delta))
}

// PutOperation appends an operation type without a value.
func (b *Buffer) PutOperation(op OpType, idx uint32) {
b.writeChunk(idx)
delta := int32(idx) - b.last
b.last = int32(idx)
if delta == 1 {
delta := b.writeChunk(idx)
switch delta {
case 1:
b.buffer = append(b.buffer, byte(op)|size0|isNext)
return
default:
b.buffer = append(b.buffer, byte(op)|size0)
b.writeOffset(uint32(delta))
}

b.buffer = append(b.buffer, byte(op)|size0)
b.writeOffset(uint32(delta))
}

// PutBool appends a boolean value.
Expand Down Expand Up @@ -263,29 +255,25 @@ func (b *Buffer) PutUint(op OpType, idx uint32, value uint) {

// PutBytes appends a binary value.
func (b *Buffer) PutBytes(op OpType, idx uint32, value []byte) {
b.writeChunk(idx)
delta := int32(idx) - b.last
b.last = int32(idx)

// Write a 2-byte length (max 65K slices)
length := len(value)
if delta == 1 {
delta := b.writeChunk(idx)
length := len(value) // max 65K slices
switch delta {
case 1:
b.buffer = append(b.buffer,
byte(op)|size2|isString|isNext,
byte(length>>8), byte(length),
)
b.buffer = append(b.buffer, value...)
return
}

b.buffer = append(b.buffer,
byte(op)|size2|isString,
byte(length>>8), byte(length),
)
default:
b.buffer = append(b.buffer,
byte(op)|size2|isString,
byte(length>>8), byte(length),
)

// Write the the data itself and the offset
b.buffer = append(b.buffer, value...)
b.writeOffset(uint32(delta))
// Write the the data itself and the offset
b.buffer = append(b.buffer, value...)
b.writeOffset(uint32(delta))
}
}

// PutString appends a string value.
Expand All @@ -303,8 +291,8 @@ func (b *Buffer) writeOffset(delta uint32) {
b.buffer = append(b.buffer, byte(delta))
}

// writeChunk writes a chunk if changed
func (b *Buffer) writeChunk(idx uint32) {
// writeChunk writes a chunk if changed and returns the delta
func (b *Buffer) writeChunk(idx uint32) int32 {
if chunk := idx >> chunkShift; b.chunk != chunk {
b.chunk = chunk
b.chunks = append(b.chunks, header{
Expand All @@ -313,6 +301,10 @@ func (b *Buffer) writeChunk(idx uint32) {
Value: uint32(b.last),
})
}

delta := int32(idx) - b.last
b.last = int32(idx)
return delta
}

// toBytes converts a string to a byte slice without allocating.
Expand Down
71 changes: 61 additions & 10 deletions commit/buffer_test.go
Expand Up @@ -12,15 +12,30 @@ import (

/*
cpu: Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz
BenchmarkQueue/rw-u16-8 202 5891099 ns/op 7 B/op 0 allocs/op
BenchmarkQueue/rw-u32-8 200 5932520 ns/op 7 B/op 0 allocs/op
BenchmarkQueue/rw-u64-8 190 6192885 ns/op 8 B/op 0 allocs/op
BenchmarkQueue/rw-str-8 98 11060616 ns/op 15 B/op 0 allocs/op
BenchmarkQueue/rw-bool-8 213 5615013 ns/op 7 B/op 0 allocs/op
BenchmarkQueue/u16-rw-8 154 7691836 ns/op 19 B/op 0 allocs/op
BenchmarkQueue/u16-next-8 214 5542922 ns/op 7 B/op 0 allocs/op
BenchmarkQueue/u32-rw-8 152 7743216 ns/op 20 B/op 0 allocs/op
BenchmarkQueue/u32-next-8 212 5616605 ns/op 7 B/op 0 allocs/op
BenchmarkQueue/u64-rw-8 148 8000536 ns/op 20 B/op 0 allocs/op
BenchmarkQueue/u64-next-8 194 6126377 ns/op 7 B/op 0 allocs/op
BenchmarkQueue/str-rw-8 91 12935521 ns/op 33 B/op 0 allocs/op
BenchmarkQueue/str-next-8 98 10901156 ns/op 15 B/op 0 allocs/op
BenchmarkQueue/bool-rw-8 169 6950441 ns/op 18 B/op 0 allocs/op
BenchmarkQueue/bool-next-8 228 5195821 ns/op 6 B/op 0 allocs/op
*/
func BenchmarkQueue(b *testing.B) {
const count = 1000000
run("rw-u16", b, count, func(buf *Buffer, r *Reader) {

run("u16-rw", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count*2; i += 2 {
buf.PutUint16(Put, i, uint16(i))
}
for r.Seek(buf); r.Next(); {
_ = r.Uint16()
}
})

run("u16-next", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count; i++ {
buf.PutUint16(Put, i, uint16(i))
}
Expand All @@ -29,7 +44,16 @@ func BenchmarkQueue(b *testing.B) {
}
})

run("rw-u32", b, count, func(buf *Buffer, r *Reader) {
run("u32-rw", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count*2; i += 2 {
buf.PutUint32(Put, i, i)
}
for r.Seek(buf); r.Next(); {
_ = r.Uint32()
}
})

run("u32-next", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count; i++ {
buf.PutUint32(Put, i, i)
}
Expand All @@ -38,7 +62,16 @@ func BenchmarkQueue(b *testing.B) {
}
})

run("rw-u64", b, count, func(buf *Buffer, r *Reader) {
run("u64-rw", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count*2; i += 2 {
buf.PutUint64(Put, i, uint64(i))
}
for r.Seek(buf); r.Next(); {
_ = r.Uint64()
}
})

run("u64-next", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count; i++ {
buf.PutUint64(Put, i, uint64(i))
}
Expand All @@ -47,7 +80,16 @@ func BenchmarkQueue(b *testing.B) {
}
})

run("rw-str", b, count, func(buf *Buffer, r *Reader) {
run("str-rw", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count*2; i += 2 {
buf.PutString(Put, i, "hello world")
}
for r.Seek(buf); r.Next(); {
_ = r.String()
}
})

run("str-next", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count; i++ {
buf.PutString(Put, i, "hello world")
}
Expand All @@ -56,7 +98,16 @@ func BenchmarkQueue(b *testing.B) {
}
})

run("rw-bool", b, count, func(buf *Buffer, r *Reader) {
run("bool-rw", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count*2; i += 2 {
buf.PutBool(i, true)
}
for r.Seek(buf); r.Next(); {
_ = r.Bool()
}
})

run("bool-next", b, count, func(buf *Buffer, r *Reader) {
for i := uint32(0); i < count; i++ {
buf.PutBool(i, true)
}
Expand Down
7 changes: 3 additions & 4 deletions commit/reader.go
Expand Up @@ -13,9 +13,9 @@ import (
type Reader struct {
head int // The read position
i0, i1 int // The value start and end
Type OpType // The current operation type
buffer []byte // The log slice
Offset int32 // The current offset
Type OpType // The current operation type
start int32 // The start offset
}

Expand Down Expand Up @@ -329,20 +329,19 @@ func (r *Reader) readOffset() {
// readFixed reads the fixed-size value at the current position.
func (r *Reader) readFixed(v byte) {
size := int(1 << (v >> 4 & 0b11) & 0b1110)
r.Type = OpType(v & 0xf)
r.head++
r.i0 = r.head
r.head += size
r.i1 = r.head
r.Type = OpType(v & 0xf)
}

// readString reads the operation type and the value at the current position.
func (r *Reader) readString(v byte) {
_ = r.buffer[r.head+2]
size := int(r.buffer[r.head+2]) | int(r.buffer[r.head+1])<<8
r.Type = OpType(v & 0xf)
r.head += 3
r.i0 = r.head
r.head += size
r.i1 = r.head
r.Type = OpType(v & 0xf)
}

0 comments on commit 436f94e

Please sign in to comment.