Skip to content

Commit

Permalink
Benchmark event with CBOR encode/decode, checksum
Browse files Browse the repository at this point in the history
Signed-off-by: tobiasmo1 <[email protected]>
  • Loading branch information
tobiasmo1 committed Apr 22, 2019
0 parents commit 34c5cbd
Show file tree
Hide file tree
Showing 11 changed files with 307 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea
cmd/cmd
cmd/go_build_main_go
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# event-bench
1.) Clone repo locally

2.) `cd cmd`

3.) `go build`

4.) There are two ways to execute the program. To benchmark events generated without a binary value, simply call `./cmd`.
To generate a checksum for an event with a binary value, call `./cmd -b`

5.) Additional parameters:

param | type | description
======|======|========================
-i | int64 | Perform a number of iterations.
-b | bool | True = Generate binary events. False = Generate simple events.
-s | bool | True = When generating binary events, use 100kb image. False = 900kb image.
-p | bool | True = Print the encoded/decoded data.
-c | bool | True = Use contract client form of CBOR encoder/decoder. False = DSDK method/style.
Binary file added cmd/img/1080p_Istanbul_by_yusuf_fersat_5.JPG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added cmd/img/canine.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added cmd/img/lebowski.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
145 changes: 145 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package main

import (
"bufio"
"bytes"
"crypto/sha256"
"flag"
"fmt"
"io"
"log"
"os"
"time"

"github.com/edgexfoundry/go-mod-core-contracts/models"
"github.com/tobiasmo1/event-bench/events"
"github.com/ugorji/go/codec"
)

func main() {
var print bool
var useBinary bool
var coredataCBOR bool
var smallPayload bool
var iterations int64

flag.BoolVar(&print, "p", true, "Print encoded event, checksum, decoded values to stdout")
flag.BoolVar(&useBinary, "b", false, "Create event with binary payload")
flag.BoolVar(&smallPayload, "s", false, "When creating event use payload bytes of 100k (true) or 900k (false)")
flag.Int64Var(&iterations, "i", 5000, "Sequential iterations (for timing)")
flag.BoolVar(&coredataCBOR, "c", false, "Encode with method patterned after core-data (false = dsdk pattern)")
flag.Parse()

var data []byte
var err error
start := time.Now()
fmt.Printf("StartTime: %v\r\n", start)
var totalIterTime time.Duration
var totalEncodeTime time.Duration
var totalChecksumTime time.Duration
var totalDecodeTime time.Duration
var avgIterTime int64
var avgEncodeTime int64
var avgChecksumTime int64
var avgDecodeTime int64
for i := int64(0); i < iterations; i++ {
startIter := time.Now()
if useBinary {
// we are doing much more than just encode, but
startEncode := time.Now()
data, err = events.NewBinaryEvent(coredataCBOR, smallPayload)
deltaEncode := time.Since(startEncode)
totalEncodeTime += deltaEncode
avgEncodeTime = totalEncodeTime.Nanoseconds() / (i + 1)
fmt.Printf("\r\nCBOR Encode Time: %v\r\n", deltaEncode)
fmt.Printf("\r\nCBOR Avg Encode Time: %v\r\n", time.Duration(avgEncodeTime))
} else {
data, err = events.NewBasicEvent()
}
if err != nil {
fmt.Sprintln(err.Error())
return
}
// Calculate a checksum across encoded event data model
startChecksum := time.Now()
checksum := CalcChecksum(data)
deltaChecksum := time.Since(startChecksum)
totalChecksumTime += deltaChecksum
avgChecksumTime = totalChecksumTime.Nanoseconds() / (i + 1)
fmt.Printf("\r\nChecksum Time: %v\r\n", deltaChecksum)
fmt.Printf("\r\nChecksum Avg Time: %v\r\n", time.Duration(avgChecksumTime))

// Print actuals if desired
// This will substantially increase overall iteration timing.
if print {
fmt.Printf("Checksum: %x\r\n", checksum)
fmt.Printf("Current time: %v\r\n", events.MakeTimestamp())
fmt.Printf("Encoded data: \r\n")
os.Stdout.Write(data)
fmt.Printf("\r\n")
}
// decode data, read the event data model, add uuid and encode again..
//evt := models.Event{}
startDecode := time.Now()
evt, err := decodeEvent(data)
deltaDecode := time.Since(startDecode)
totalDecodeTime += deltaDecode
avgDecodeTime = totalDecodeTime.Nanoseconds() / (i + 1)
fmt.Printf("\r\nCBOR Decode Time: %v\r\n", deltaDecode)
fmt.Printf("\r\nCBOR Avg Decode Time: %v\r\n", time.Duration(avgDecodeTime))

if err != nil {
fmt.Printf("\r\nERROR Decoding: %v\r\n", err.Error())
}
if print {
fmt.Printf("\r\nDecoded data: %v\r\n", evt.String())
//os.Stdout.Write(evt)
}
deltaIter := time.Since(startIter)
totalIterTime += deltaIter
avgIterTime = totalIterTime.Nanoseconds() / (i + 1)
fmt.Printf("\r\nIteration Time: %v\r\n", deltaIter)
fmt.Printf("Average Iteration (encode+decode+checksum): %v\r\n", time.Duration(avgIterTime))
}
fmt.Printf("EndTime: %v\r\n", time.Now())
fmt.Printf("\r\nTOTAL Time taken for %v iterations: %v\r\n", iterations, time.Since(start))
}

func CalcChecksum(data []byte) [32]byte {
defer SampleTime(time.Now(), "CalcChecksum")
return sha256.Sum256(data)
}

func decodeEvent(encodedData []byte) (models.Event, error) {
var err error
useBufferedReader := true
evt := models.Event{}
if (useBufferedReader) {
err = decodeBinaryValueBufferedReader(bytes.NewReader(encodedData), &evt)
} else {
err = decodeBinaryValue(encodedData, &evt)
}
return evt, err
}

// Directly perform efficient zero copy decode from byte slice
func decodeBinaryValue(encodedData []byte,/* reader io.Reader,*/ value interface{}) error {
var h codec.Handle = new(codec.CborHandle)
var dec *codec.Decoder = codec.NewDecoderBytes(encodedData, h)
var err error = dec.Decode(value)
return err
}

// Provide a buffered reader for go-codec performance
func decodeBinaryValueBufferedReader(reader io.Reader, value interface{}) error {
var bufReader = bufio.NewReader(reader)
var h codec.Handle = new(codec.CborHandle)
var dec *codec.Decoder = codec.NewDecoder(bufReader, h)
var err error = dec.Decode(value)
return err
}

func SampleTime(t time.Time, name string) {
elapsed := time.Since(t)
log.Printf("SampleTime: [%s] took %s\n", name, elapsed)
}
21 changes: 21 additions & 0 deletions events/basic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package events

import (
"encoding/json"
"github.com/edgexfoundry/go-mod-core-contracts/models"
)

func NewBasicEvent() (data []byte, err error) {
timestamp := MakeTimestamp()
deviceName := "RandomDevice-1"
evt := models.Event{ Created:timestamp, Modified:timestamp, Device:deviceName }
readings := []models.Reading{}
readings = append(readings, models.Reading{Created:timestamp, Modified:timestamp, Device:deviceName, Name:"Reading1", Value:"ABC"})
readings = append(readings, models.Reading{Created:timestamp, Modified:timestamp, Device:deviceName, Name:"Reading2", Value:"123"})
evt.Readings = readings
data, err = json.Marshal(evt)
if err != nil {
return
}
return
}
87 changes: 87 additions & 0 deletions events/binary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package events

import (
"bufio"
"bytes"
"io"
"os"
"path/filepath"

"github.com/edgexfoundry/go-mod-core-contracts/models"
"github.com/ugorji/go/codec"
)

func NewBinaryEvent(coredataCBOR bool, smallPayload bool) (data []byte, err error) {
imgPath, err := findPath()
if err != nil {
return
}
if smallPayload { // 100k
imgPath += "/lebowski.jpg"
} else { //900k (medium)
imgPath += "/1080p_Istanbul_by_yusuf_fersat_5.JPG"
}

file, err := os.Open(imgPath)
if err != nil {
return
}
defer file.Close()

fileInfo, _ := file.Stat()
bytes := make([]byte, fileInfo.Size())

// read file into bytes
buffer := bufio.NewReader(file)
_, err = buffer.Read(bytes)

timestamp := MakeTimestamp()
deviceName := "RandomDevice-2"
evt := models.Event{ Created:timestamp, Modified:timestamp, Device:deviceName }
readings := []models.Reading{}
readings = append(readings, models.Reading{Created:timestamp, Modified:timestamp, Device:deviceName, Name:"Reading2", Value:"789"})
readings = append(readings, models.Reading{Created:timestamp, Modified:timestamp, Device:deviceName, Name:"Reading1", Value:"XYZ"})
readings = append(readings, models.Reading{Created:timestamp, Modified:timestamp, Device:deviceName, Name:"Reading1", BinaryValue:bytes})
evt.Readings = readings

/* Simple form */
if coredataCBOR {
var handle codec.CborHandle
data = make([]byte, 0, 64)
enc := codec.NewEncoderBytes(&data, &handle)
err = enc.Encode(evt)
} else {
data, _ = encodeBinaryValue(evt)
}
return
}

func findPath() (path string, err error) {
exec, err := os.Executable()
if err != nil {
return
}
path = filepath.Dir(exec)
path += "/img"
return
}

func encodeBinaryValue(value interface{}) (encodedData []byte, err error) {
buf := new(bytes.Buffer)
hCbor := new(codec.CborHandle)
enc := codec.NewEncoder(buf, hCbor)
err = enc.Encode(value)
if err == nil {
encodedData = buf.Bytes()
}
return encodedData, err
}

func decodeBinaryValue(reader io.Reader, value interface{}) error {
// Provide a buffered reader for go-codec performance
var bufReader = bufio.NewReader(reader)
var h codec.Handle = new(codec.CborHandle)
var dec *codec.Decoder = codec.NewDecoder(bufReader, h)
var err error = dec.Decode(value)
return err
}
7 changes: 7 additions & 0 deletions events/time.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package events

import "time"

func MakeTimestamp() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/tobiasmo1/event-bench

require (
github.com/edgexfoundry/go-mod-core-contracts v0.0.0-20190418185811-6fa3b1fed53b
github.com/ugorji/go v1.1.4
)

replace github.com/edgexfoundry/go-mod-core-contracts => /home/tobiasmo/dev/edgexfoundry/go-mod-core-contracts-tobiasmo1
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edgexfoundry/go-mod-core-contracts v0.0.0-20190418185811-6fa3b1fed53b h1:+AHu/KXjRvTqsFppY2Iue7Bd2qaxf/TXMH6ydptPQpA=
github.com/edgexfoundry/go-mod-core-contracts v0.0.0-20190418185811-6fa3b1fed53b/go.mod h1:yVAVTeH1lbp+3YG2V7sq3iIerZj94lC0rZX1sryGfTY=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s=
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs=
github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20190316192920-e2bddce071ad h1:Zu1a3eNI3eJefas3yuL6HAKy6eMhRCQFdtZQLC21l6U=
github.com/ugorji/go/codec v0.0.0-20190316192920-e2bddce071ad/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA=

0 comments on commit 34c5cbd

Please sign in to comment.