-
Notifications
You must be signed in to change notification settings - Fork 367
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
404 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/binary" | ||
"flag" | ||
"fmt" | ||
"os" | ||
"sync" | ||
|
||
"github.com/gnolang/gno/benchmarking" | ||
"github.com/gnolang/gno/gnovm/pkg/gnolang" | ||
) | ||
|
||
const recordSize int = 10 | ||
|
||
var pathFlag = flag.String("path", "", "the path to the benchmark file") | ||
|
||
func main() { | ||
flag.Parse() | ||
|
||
file, err := os.Open(*pathFlag) | ||
if err != nil { | ||
panic("could not create benchmark file: " + err.Error()) | ||
} | ||
defer file.Close() | ||
|
||
inputCh := make(chan []byte, 10000) | ||
outputCh := make(chan string, 10000) | ||
wg := sync.WaitGroup{} | ||
numWorkers := 1 | ||
wg.Add(numWorkers) | ||
|
||
doneCh := make(chan struct{}) | ||
|
||
for i := 0; i < numWorkers; i++ { | ||
go func() { | ||
for { | ||
record, ok := <-inputCh | ||
if !ok { | ||
break | ||
} | ||
|
||
opName := gnolang.Op(record[0]).String() | ||
if record[1] != 0 { | ||
opName = benchmarking.StoreCodeString(record[1]) | ||
} | ||
|
||
elapsedTime := binary.LittleEndian.Uint32(record[2:]) | ||
size := binary.LittleEndian.Uint32(record[6:]) | ||
outputCh <- opName + "," + fmt.Sprint(elapsedTime) + "," + fmt.Sprint(size) | ||
} | ||
wg.Done() | ||
}() | ||
} | ||
|
||
go func() { | ||
out, err := os.Create("results.csv") | ||
if err != nil { | ||
panic("could not create readable output file: " + err.Error()) | ||
} | ||
defer out.Close() | ||
fmt.Fprintln(out, "op,elapsedTime,diskIOBytes") | ||
|
||
for { | ||
output, ok := <-outputCh | ||
if !ok { | ||
break | ||
} | ||
|
||
fmt.Fprintln(out, output) | ||
} | ||
|
||
out.Close() | ||
doneCh <- struct{}{} | ||
}() | ||
|
||
var i int | ||
|
||
bufSize := recordSize * 100000 | ||
buf := make([]byte, bufSize) | ||
|
||
for { | ||
nbytes, err := file.Read(buf) | ||
|
||
if err != nil && nbytes == 0 { | ||
break | ||
} | ||
n := nbytes / recordSize | ||
|
||
for j := 0; j < n; j++ { | ||
inputCh <- buf[j*recordSize : (j+1)*recordSize] | ||
} | ||
|
||
i += bufSize / recordSize | ||
if i%1000 == 0 { | ||
fmt.Println(i) | ||
} | ||
} | ||
|
||
close(inputCh) | ||
wg.Wait() | ||
close(outputCh) | ||
<-doneCh | ||
close(doneCh) | ||
|
||
fmt.Println("done") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package benchmarking | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
"os" | ||
"time" | ||
) | ||
|
||
var fileWriter *exporter | ||
|
||
func initExporter(fileName string) { | ||
file, err := os.Create(fileName) | ||
if err != nil { | ||
panic("could not create benchmark file: " + err.Error()) | ||
} | ||
|
||
fileWriter = &exporter{ | ||
file: file, | ||
} | ||
} | ||
|
||
type exporter struct { | ||
file *os.File | ||
} | ||
|
||
func (e *exporter) export(code Code, elapsedTime time.Duration, size uint32) { | ||
buf := []byte{code[0], code[1], 0, 0, 0, 0, 0, 0, 0, 0} | ||
binary.LittleEndian.PutUint32(buf[2:], uint32(elapsedTime)) | ||
binary.LittleEndian.PutUint32(buf[6:], size) | ||
_, err := e.file.Write(buf) | ||
if err != nil { | ||
panic("could not write to benchmark file: " + err.Error()) | ||
} | ||
} | ||
|
||
func (e *exporter) close() { | ||
e.file.Sync() | ||
e.file.Close() | ||
} | ||
|
||
func Finish() { | ||
fmt.Println("## StackSize: ", stackSize) | ||
|
||
fileWriter.close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package benchmarking | ||
|
||
func Init(filepath string) { | ||
initExporter(filepath) | ||
initStack() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package benchmarking | ||
|
||
import ( | ||
"time" | ||
) | ||
|
||
type measurement struct { | ||
*timer | ||
code Code | ||
allocation uint32 | ||
} | ||
|
||
func startNewMeasurement(code Code) *measurement { | ||
return &measurement{ | ||
timer: &timer{startTime: time.Now()}, | ||
code: code, | ||
} | ||
} | ||
|
||
func (m *measurement) pause() { | ||
m.stop() | ||
} | ||
|
||
func (m *measurement) resume() { | ||
m.start() | ||
} | ||
|
||
func (m *measurement) end(size uint32) { | ||
m.stop() | ||
if size != 0 && m.allocation != 0 { | ||
panic("measurement cannot have both allocation and size") | ||
} else if size == 0 { | ||
size = m.allocation | ||
} | ||
|
||
fileWriter.export(m.code, m.elapsedTime, size) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package benchmarking | ||
|
||
// store code | ||
const ( | ||
StoreGetObject byte = 0x01 // get value and unmarshl to object from store | ||
StoreSetObject byte = 0x02 // marshal object and set value in store | ||
StoreDeleteObject byte = 0x03 // delete value from store | ||
StoreGetPackage byte = 0x04 // get package from store | ||
StoreSetPackage byte = 0x05 // get package from store | ||
StoreGetType byte = 0x06 // get type from store | ||
StoreSetType byte = 0x07 // set type in store | ||
StoreGetBlockNode byte = 0x08 // get block node from store | ||
StoreSetBlockNode byte = 0x09 // set block node in store | ||
StoreAddMemPackage byte = 0x0A // add mempackage to store | ||
StoreGetMemPackage byte = 0x0B // get mempackage from store | ||
FinalizeTx byte = 0x0C // finalize realm transaction | ||
|
||
AminoMarshal byte = 0x0D // marshal go object to binary value | ||
AminoUnMarshal byte = 0x0E // unmarshl binary value to go object | ||
|
||
StoreGet byte = 0x0F // Get binary value by key | ||
StoreSet byte = 0x10 // Set binary value by key | ||
|
||
invalidStoreCode string = "StoreInvalid" | ||
) | ||
|
||
var storeCodeNames = []string{ | ||
invalidStoreCode, | ||
"StoreGetObject", | ||
"StoreSetObject", | ||
"StoreDeleteObject", | ||
"StoreGetPackage", | ||
"StoreSetPackage", | ||
"StoreGetType", | ||
"StoreSetType", | ||
"StoreGetBlockNode", | ||
"StoreSetBlockNode", | ||
"StoreAddMemPackage", | ||
"StoreGetMemPackage", | ||
"FinalizeTx", | ||
"AminoMarshal", | ||
"AminoUnMarshal", | ||
"StoreGet", | ||
"StoreSet", | ||
} | ||
|
||
type Code [2]byte | ||
|
||
func VMOpCode(opCode byte) Code { | ||
return [2]byte{opCode, 0x00} | ||
} | ||
|
||
func StoreCode(storeCode byte) Code { | ||
return [2]byte{0x00, storeCode} | ||
} | ||
|
||
func StoreCodeString(storeCode byte) string { | ||
if int(storeCode) >= len(storeCodeNames) { | ||
return invalidStoreCode | ||
} | ||
return storeCodeNames[storeCode] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
//go:build !benchmarkingops | ||
|
||
package benchmarking | ||
|
||
const OpsEnabled = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
//go:build benchmarkingops | ||
|
||
package benchmarking | ||
|
||
const OpsEnabled = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package benchmarking | ||
|
||
const initStackSize int = 64 | ||
|
||
var ( | ||
measurementStack []*measurement | ||
stackSize int | ||
) | ||
|
||
func initStack() { | ||
measurementStack = make([]*measurement, initStackSize) | ||
} | ||
|
||
func StartMeasurement(code Code) { | ||
if stackSize != 0 { | ||
measurementStack[stackSize-1].pause() | ||
} | ||
|
||
if stackSize == len(measurementStack) { | ||
newStack := make([]*measurement, stackSize*2) | ||
copy(newStack, measurementStack) | ||
measurementStack = newStack | ||
} | ||
|
||
measurementStack[stackSize] = startNewMeasurement(code) | ||
stackSize++ | ||
} | ||
|
||
// Pause pauses current measurement on the stack | ||
func Pause() { | ||
if stackSize != 0 { | ||
measurementStack[stackSize-1].pause() | ||
} | ||
} | ||
|
||
// Resume resumes current measurement on the stack | ||
func Resume() { | ||
if stackSize != 0 { | ||
measurementStack[stackSize-1].resume() | ||
} | ||
} | ||
|
||
// StopMeasurement ends the current measurement and resumes the previous one | ||
// if one exists. It accepts the number of bytes that were read/written to/from | ||
// the store. This value is zero if the operation is not a read or write. | ||
func StopMeasurement(size uint32) { | ||
if stackSize == 0 { | ||
return | ||
} | ||
|
||
measurementStack[stackSize-1].end(size) | ||
|
||
stackSize-- | ||
|
||
if stackSize != 0 { | ||
measurementStack[stackSize-1].resume() | ||
} | ||
} | ||
|
||
func RecordAllocation(size uint32) { | ||
if stackSize == 0 { | ||
return | ||
} | ||
|
||
measurementStack[stackSize-1].allocation += size | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
//go:build !benchmarkingstorage | ||
|
||
package benchmarking | ||
|
||
const StorageEnabled = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
//go:build benchmarkingstorage | ||
|
||
package benchmarking | ||
|
||
const StorageEnabled = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package benchmarking | ||
|
||
import "time" | ||
|
||
type timer struct { | ||
startTime time.Time | ||
elapsedTime time.Duration | ||
isStopped bool | ||
} | ||
|
||
func (t *timer) start() { | ||
t.startTime = time.Now() | ||
} | ||
|
||
func (t *timer) stop() { | ||
if t.isStopped { | ||
return | ||
} | ||
|
||
t.elapsedTime += time.Since(t.startTime) | ||
t.isStopped = true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.