github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/performance/benchmarks/results.go (about)

     1  // Copyright 2019 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"fmt"
    19  	"io"
    20  	"log"
    21  	"os"
    22  	"path/filepath"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/dolthub/dolt/go/libraries/utils/filesys"
    27  	"github.com/dolthub/dolt/go/store/types"
    28  )
    29  
    30  type result struct {
    31  	name    string
    32  	format  string
    33  	rows    int
    34  	columns int
    35  	br      testing.BenchmarkResult
    36  }
    37  
    38  // RDSImpl is a Dataset containing results of benchmarking
    39  type RSImpl struct {
    40  	// Schema defines the structure of the Dataset
    41  	Schema *SeedSchema
    42  
    43  	// Results are results of benchmarking
    44  	Results []result
    45  
    46  	// TableName is the name of the results table
    47  	TableName string
    48  
    49  	// w is the writer where the results will be written
    50  	w io.Writer
    51  }
    52  
    53  // NewRSImpl creates a new RSImpl
    54  func NewRSImpl(w io.Writer, sch *SeedSchema, results []result, tableName string) *RSImpl {
    55  	return &RSImpl{
    56  		Schema:    sch,
    57  		Results:   results,
    58  		TableName: tableName,
    59  		w:         w,
    60  	}
    61  }
    62  
    63  // GenerateData writes the results to a io.Writer
    64  func (rds *RSImpl) GenerateData() {
    65  	writeResultsToWriter(rds.w, rds.Results, rds.Schema.Columns, rds.TableName, rds.Schema.FileFormatExt)
    66  }
    67  
    68  // Change returns a DataSet that is a mutation of this Dataset by the given percentage
    69  func (rds *RSImpl) Change(pct float32) Dataset {
    70  	// TODO
    71  	return &RSImpl{}
    72  }
    73  
    74  func writeResultsToWriter(wc io.Writer, results []result, cols []*SeedColumn, tableName, format string) {
    75  	switch format {
    76  	case csvExt:
    77  		generateCSVResults(wc, results, cols, tableName, format)
    78  	default:
    79  		log.Fatalf("cannot generate results data, file format %s unsupported \n", format)
    80  	}
    81  }
    82  
    83  func generateCSVResults(wc io.Writer, results []result, cols []*SeedColumn, tableName, format string) {
    84  	header := makeCSVHeaderStr(cols, tableName, format)
    85  
    86  	_, err := wc.Write([]byte(header))
    87  	if err != nil {
    88  		log.Fatal(err)
    89  	}
    90  
    91  	for i, result := range results {
    92  		row := getResultsRow(result, cols)
    93  
    94  		_, err := wc.Write([]byte(formatRow(row, cols, i, len(results)-1, tableName, format)))
    95  		if err != nil {
    96  			log.Fatal(err)
    97  		}
    98  	}
    99  }
   100  
   101  func getResultsRow(res result, cols []*SeedColumn) []string {
   102  	row := make([]string, len(cols))
   103  
   104  	// set name
   105  	row[0] = res.name
   106  	// set format
   107  	row[1] = res.format
   108  	// set rows
   109  	row[2] = fmt.Sprintf("%d", res.rows)
   110  	// set cols
   111  	row[3] = fmt.Sprintf("%d", res.columns)
   112  	// set iterations
   113  	row[4] = fmt.Sprintf("%d", res.br.N)
   114  	// set time
   115  	row[5] = res.br.T.String()
   116  	// set bytes
   117  	row[6] = fmt.Sprintf("%v", res.br.Bytes)
   118  	// set mem_allocs
   119  	row[7] = fmt.Sprintf("%v", res.br.MemAllocs)
   120  	// set mem_bytes
   121  	row[8] = fmt.Sprintf("%v", res.br.MemBytes)
   122  	// set alloced_bytes_per_op
   123  	row[9] = fmt.Sprintf("%v", res.br.AllocedBytesPerOp())
   124  	//set allocs_per_op
   125  	row[10] = fmt.Sprintf("%v", res.br.AllocsPerOp())
   126  	// set datetime
   127  	t := time.Now()
   128  	row[11] = fmt.Sprintf("%04d-%02d-%02d %02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute())
   129  	return row
   130  }
   131  
   132  func genResultsCols() []*SeedColumn {
   133  	return []*SeedColumn{
   134  		NewSeedColumn("name", false, types.StringKind, supplied),
   135  		NewSeedColumn("format", false, types.StringKind, supplied),
   136  		NewSeedColumn("rows", false, types.StringKind, supplied),
   137  		NewSeedColumn("columns", false, types.StringKind, supplied),
   138  		NewSeedColumn("iterations", false, types.StringKind, supplied),
   139  		NewSeedColumn("time", false, types.TimestampKind, supplied),
   140  		NewSeedColumn("bytes", false, types.IntKind, supplied),
   141  		NewSeedColumn("mem_allocs", false, types.IntKind, supplied),
   142  		NewSeedColumn("mem_bytes", false, types.IntKind, supplied),
   143  		NewSeedColumn("alloced_bytes_per_op", false, types.StringKind, supplied),
   144  		NewSeedColumn("allocs_per_op", false, types.StringKind, supplied),
   145  		NewSeedColumn("date_time", false, types.StringKind, supplied),
   146  	}
   147  }
   148  
   149  func serializeResults(results []result, path, tableName, format string) {
   150  	var sch *SeedSchema
   151  	switch format {
   152  	case csvExt:
   153  		sch = NewSeedSchema(len(results), genResultsCols(), csvExt)
   154  	default:
   155  		log.Fatalf("cannot serialize results, unsupported file format %s \n", format)
   156  	}
   157  	now := time.Now()
   158  	fs := filesys.LocalFS
   159  	resultsFile := filepath.Join(path, fmt.Sprintf("benchmark_results-%04d-%02d-%02d%s", now.Year(), now.Month(), now.Day(), format))
   160  	wc, err := fs.OpenForWrite(resultsFile, os.ModePerm)
   161  	if err != nil {
   162  		log.Fatal(err)
   163  	}
   164  	defer wc.Close()
   165  
   166  	ds := NewRSImpl(wc, sch, results, tableName)
   167  	ds.GenerateData()
   168  }