k8s.io/perf-tests/clusterloader2@v0.0.0-20240304094227-64bdb12da87e/pkg/measurement/common/timer.go (about)

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package common
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  	"time"
    23  
    24  	"k8s.io/klog/v2"
    25  	"k8s.io/perf-tests/clusterloader2/pkg/measurement"
    26  	measurementutil "k8s.io/perf-tests/clusterloader2/pkg/measurement/util"
    27  	"k8s.io/perf-tests/clusterloader2/pkg/util"
    28  )
    29  
    30  const (
    31  	timerMeasurementName = "Timer"
    32  )
    33  
    34  func init() {
    35  	if err := measurement.Register(timerMeasurementName, createTimerMeasurment); err != nil {
    36  		klog.Fatalf("Cannot register %s: %v", timerMeasurementName, err)
    37  	}
    38  }
    39  
    40  func createTimerMeasurment() measurement.Measurement {
    41  	return &timer{
    42  		startTimes: make(map[string]time.Time),
    43  		durations:  make(map[string]time.Duration),
    44  	}
    45  }
    46  
    47  type timer struct {
    48  	lock       sync.Mutex
    49  	startTimes map[string]time.Time
    50  	durations  map[string]time.Duration
    51  }
    52  
    53  // Execute supports two actions. start - which start timer. stop - which stops timer
    54  // and collects time duration between start and stop.
    55  // Both start and stop actions require label parameter to be provided.
    56  // Gather action logs a measurement for all collected phases durations.
    57  func (t *timer) Execute(config *measurement.Config) ([]measurement.Summary, error) {
    58  	action, err := util.GetString(config.Params, "action")
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	t.lock.Lock()
    64  	defer t.lock.Unlock()
    65  	switch action {
    66  	case "start":
    67  		label, err := util.GetString(config.Params, "label")
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  		t.startTimes[label] = time.Now()
    72  	case "stop":
    73  		label, err := util.GetString(config.Params, "label")
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  		startTime, ok := t.startTimes[label]
    78  		if !ok {
    79  			return nil, fmt.Errorf("uninitialized timer %s", label)
    80  		}
    81  		duration := time.Since(startTime)
    82  		klog.V(0).Infof("%s: %s - %v", t, label, duration)
    83  		t.durations[label] = duration
    84  		delete(t.startTimes, label)
    85  	case "gather":
    86  		result := measurementutil.PerfData{
    87  			Version: "v1",
    88  			DataItems: []measurementutil.DataItem{{
    89  				Unit:   "s",
    90  				Labels: map[string]string{"test": "phases"},
    91  				Data:   make(map[string]float64)}}}
    92  
    93  		for label, duration := range t.durations {
    94  			result.DataItems[0].Data[label] = duration.Seconds()
    95  		}
    96  		content, err := util.PrettyPrintJSON(result)
    97  		if err != nil {
    98  			return nil, err
    99  		}
   100  		summary := measurement.CreateSummary(timerMeasurementName, "json", content)
   101  		return []measurement.Summary{summary}, nil
   102  	default:
   103  		return nil, fmt.Errorf("unknown action %s", action)
   104  	}
   105  	return nil, nil
   106  }
   107  
   108  // Dispose cleans up after the measurement.
   109  func (t *timer) Dispose() {}
   110  
   111  // String returns string representation of this measurement.
   112  func (*timer) String() string {
   113  	return timerMeasurementName
   114  }