...

Source file src/go.mongodb.org/mongo-driver/benchmark/harness_case.go

Documentation: go.mongodb.org/mongo-driver/benchmark

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package benchmark
     8  
     9  import (
    10  	"context"
    11  	"errors"
    12  	"fmt"
    13  	"path/filepath"
    14  	"reflect"
    15  	"runtime"
    16  	"strings"
    17  	"time"
    18  )
    19  
    20  type CaseDefinition struct {
    21  	Bench              BenchCase
    22  	Count              int
    23  	Size               int
    24  	RequiredIterations int
    25  	Runtime            time.Duration
    26  
    27  	cumulativeRuntime time.Duration
    28  	elapsed           time.Duration
    29  	startAt           time.Time
    30  	isRunning         bool
    31  }
    32  
    33  // TimerManager is a subset of the testing.B tool, used to manage
    34  // setup code.
    35  type TimerManager interface {
    36  	ResetTimer()
    37  	StartTimer()
    38  	StopTimer()
    39  }
    40  
    41  func (c *CaseDefinition) ResetTimer() {
    42  	c.startAt = time.Now()
    43  	c.elapsed = 0
    44  	c.isRunning = true
    45  }
    46  
    47  func (c *CaseDefinition) StartTimer() {
    48  	c.startAt = time.Now()
    49  	c.isRunning = true
    50  }
    51  
    52  func (c *CaseDefinition) StopTimer() {
    53  	if !c.isRunning {
    54  		return
    55  	}
    56  	c.elapsed += time.Since(c.startAt)
    57  	c.isRunning = false
    58  }
    59  
    60  func (c *CaseDefinition) Run(ctx context.Context) *BenchResult {
    61  	out := &BenchResult{
    62  		Trials:     1,
    63  		DataSize:   c.Size,
    64  		Name:       c.Name(),
    65  		Operations: c.Count,
    66  	}
    67  	var cancel context.CancelFunc
    68  	ctx, cancel = context.WithTimeout(ctx, 2*ExecutionTimeout)
    69  	defer cancel()
    70  
    71  	fmt.Println("=== RUN", out.Name)
    72  	if c.RequiredIterations == 0 {
    73  		c.RequiredIterations = MinIterations
    74  	}
    75  
    76  benchRepeat:
    77  	for {
    78  		if ctx.Err() != nil {
    79  			break
    80  		}
    81  		if c.cumulativeRuntime >= c.Runtime {
    82  			if out.Trials >= c.RequiredIterations {
    83  				break
    84  			} else if c.cumulativeRuntime >= ExecutionTimeout {
    85  				break
    86  			}
    87  		}
    88  
    89  		res := Result{
    90  			Iterations: c.Count,
    91  		}
    92  
    93  		c.StartTimer()
    94  		res.Error = c.Bench(ctx, c, c.Count)
    95  		c.StopTimer()
    96  		res.Duration = c.elapsed
    97  		c.cumulativeRuntime += res.Duration
    98  
    99  		switch {
   100  		case errors.Is(res.Error, context.DeadlineExceeded):
   101  			break benchRepeat
   102  		case errors.Is(res.Error, context.Canceled):
   103  			break benchRepeat
   104  		case res.Error == nil:
   105  			out.Trials++
   106  			c.elapsed = 0
   107  			out.Raw = append(out.Raw, res)
   108  		default:
   109  			continue
   110  		}
   111  
   112  	}
   113  
   114  	out.Duration = out.totalDuration()
   115  	fmt.Printf("    --- REPORT: count=%d trials=%d requiredTrials=%d runtime=%s\n",
   116  		c.Count, out.Trials, c.RequiredIterations, c.Runtime)
   117  	if out.HasErrors() {
   118  		fmt.Printf("    --- ERRORS: %s\n", strings.Join(out.errReport(), "\n       "))
   119  		fmt.Printf("--- FAIL: %s (%s)\n", out.Name, out.roundedRuntime())
   120  	} else {
   121  		fmt.Printf("--- PASS: %s (%s)\n", out.Name, out.roundedRuntime())
   122  	}
   123  
   124  	return out
   125  
   126  }
   127  
   128  func (c *CaseDefinition) String() string {
   129  	return fmt.Sprintf("name=%s, count=%d, runtime=%s timeout=%s",
   130  		c.Name(), c.Count, c.Runtime, ExecutionTimeout)
   131  }
   132  
   133  func (c *CaseDefinition) Name() string { return getName(c.Bench) }
   134  func getName(i interface{}) string {
   135  	n := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
   136  	parts := strings.Split(n, ".")
   137  	if len(parts) > 1 {
   138  		return parts[len(parts)-1]
   139  	}
   140  
   141  	return n
   142  
   143  }
   144  
   145  func getProjectRoot() string { return filepath.Dir(getDirectoryOfFile()) }
   146  
   147  func getDirectoryOfFile() string {
   148  	_, file, _, _ := runtime.Caller(1)
   149  
   150  	return filepath.Dir(file)
   151  }
   152  

View as plain text