func (e *UnitEngine) MarkUnitRunning(id string) time.Duration {
	e.mu.Lock()
	defer e.mu.Unlock()
	state, exists := e.startingUnits[id]
	if !exists {
		log.Logger().Errorf("unit %s cannot be found in the starting pool\n", id)
		return time.Duration(0)
	}
	delete(e.startingUnits, id)
	state.actualStartTime = time.Now()
	e.runningUnits[id] = state
	e.startedStats = append(e.startedStats, e.genStatsLine(id, state.actualStartTime.Sub(state.startRequestTime)))
	return state.actualStartTime.Sub(state.startRequestTime)
}
MarkUnitRunning collects the timestamps of the start operation for an unit
package unit
import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"sync"
	"time"
	"github.com/giantswarm/nomi/definition"
	"github.com/giantswarm/nomi/log"
)
type stats []statsLine
type event struct {
	Cmd       string
	Args      []string
	StartTime float64
	EndTime   float64
}
type UnitEngine struct {
	benchmark definition.BenchmarkDef
	SpawnFunc func(string) error
	StopFunc  func(string) error
	startingUnits map[string]UnitState
	runningUnits  map[string]UnitState
	stoppingUnits map[string]UnitState
	stoppedUnits  map[string]UnitState
	eventLog []event
	startedStats stats
	stoppedStats stats
	machineStats map[string][]processStatsLine
	startTime time.Time
	mu *sync.Mutex
}
type processStatsLine struct {
	Process   string
	TimeStamp float64
	CPUUsage  float64
	RSS       int
}
type statsLine struct {
	ID             string
	StartTime      float64
	CompletionTime float64
	Delay          float64
	StartingCount  int
	RunningCount   int
	StoppingCount  int
	StoppedCount   int
}
var Verbose bool
func (l statsLine) toSSV() string {
	return fmt.Sprintf("%s %f %f %d %d %d %d",
		l.ID,
		l.StartTime,
		l.Delay,
		l.StartingCount,
		l.RunningCount,
		l.StoppingCount,
		l.StoppedCount)
}
func NewEngine(def definition.BenchmarkDef, verbose bool) (*UnitEngine, error) {
	Verbose = verbose
	return &UnitEngine{
		mu:            new(sync.Mutex),
		benchmark:     def,
		startingUnits: map[string]UnitState{},
		runningUnits:  map[string]UnitState{},
		stoppingUnits: map[string]UnitState{},
		stoppedUnits:  map[string]UnitState{},
		startedStats:  stats{},
		stoppedStats:  stats{},
		eventLog:      []event{},
		machineStats:  map[string][]processStatsLine{},
	}, nil
}
func (e *UnitEngine) InstanceGroupSize() int {
	return e.benchmark.InstanceGroupSize
}
func (e *UnitEngine) Run() {
	defer e.stopAll()
	var (
		emptyStart         definition.Start
		emptyFloat         definition.Float
		emptyExpectRunning definition.ExpectRunning
	)
	e.startTime = time.Now()
	for _, instruction := range e.benchmark.Instructions {
		if instruction.Start != emptyStart {
			go func(obj definition.Start) {
				startTime := time.Now()
				e.start(obj)
				e.logCommand("start", []string{fmt.Sprintf("%d", instruction.Start.Max), fmt.Sprintf("%d", instruction.Start.Interval)}, startTime, time.Now())
			}(instruction.Start)
		}
		if instruction.Float != emptyFloat {
			startTime := time.Now()
			e.float(instruction.Float)
			e.logCommand("float", []string{fmt.Sprintf("%d", instruction.Float.Rate), fmt.Sprintf("%v", instruction.Float.Duration)}, startTime, time.Now())
		}
		if instruction.Sleep != 0 {
			startTime := time.Now()
			time.Sleep(time.Duration(instruction.Sleep) * time.Second)
			e.logCommand("sleep", []string{fmt.Sprintf("%d", instruction.Sleep)}, startTime, time.Now())
		}
		if instruction.ExpectRunning != emptyExpectRunning {
			startTime := time.Now()
			e.expectRunning(instruction.ExpectRunning)
			e.logCommand("expect-running", []string{fmt.Sprintf("%s", instruction.ExpectRunning.Symbol), fmt.Sprintf("%d", instruction.ExpectRunning.Amount)}, startTime, time.Now())
		}
		if instruction.Stop != "" {
			startTime := time.Now()
			e.stopAll()
			e.logCommand("stop-all", []string{fmt.Sprintf("%s", instruction.Stop)}, startTime, time.Now())
		}
	}
}