summaryrefslogtreecommitdiff
path: root/src/vm/hillclimbing.h
blob: 9c85877ea4c562aff0a2f2bd728a7afa48851b50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//=========================================================================

//
// HillClimbing.h
//
// Defines classes for the ThreadPool's HillClimbing concurrency-optimization
// algorithm.
//

//=========================================================================

#ifndef _HILLCLIMBING_H
#define _HILLCLIMBING_H

#include "complex.h"
#include "random.h"

enum HillClimbingStateTransition 
{
    Warmup, 
    Initializing,
    RandomMove,
    ClimbingMove,
    ChangePoint,
    Stabilizing,
    Starvation, //used by ThreadpoolMgr
    ThreadTimedOut, //used by ThreadpoolMgr
    Undefined,
};


class HillClimbing	
{
private:
    int m_wavePeriod;
    int m_samplesToMeasure;
    double m_targetThroughputRatio;
    double m_targetSignalToNoiseRatio;
    double m_maxChangePerSecond;
    double m_maxChangePerSample;
    int m_maxThreadWaveMagnitude;
    DWORD m_sampleIntervalLow;
    double m_threadMagnitudeMultiplier;
    DWORD m_sampleIntervalHigh;
    double m_throughputErrorSmoothingFactor;
    double m_gainExponent;
    double m_maxSampleError;

    double m_currentControlSetting;
    LONGLONG m_totalSamples;
    int m_lastThreadCount;
    double m_elapsedSinceLastChange; //elapsed seconds since last thread count change
    double m_completionsSinceLastChange; //number of completions since last thread count change

    double m_averageThroughputNoise;

    double* m_samples;      //Circular buffer of the last m_samplesToMeasure samples
    double* m_threadCounts; //Thread counts effective at each of m_samples

    unsigned int m_currentSampleInterval;
    CLRRandom m_randomIntervalGenerator;

    int m_accumulatedCompletionCount;
    double m_accumulatedSampleDuration;

    void ChangeThreadCount(int newThreadCount, HillClimbingStateTransition transition);
    void LogTransition(int threadCount, double throughput, HillClimbingStateTransition transition);

    Complex GetWaveComponent(double* samples, int sampleCount, double period);

public:
    void Initialize();
    int Update(int currentThreadCount, double sampleDuration, int numCompletions, int* pNewSampleInterval);
    void ForceChange(int newThreadCount, HillClimbingStateTransition transition);
};

#define HillClimbingLogCapacity 200

struct HillClimbingLogEntry
{
    DWORD TickCount;
    HillClimbingStateTransition Transition;
    int NewControlSetting;
    int LastHistoryCount;
    float LastHistoryMean;
};

GARY_DECL(HillClimbingLogEntry, HillClimbingLog, HillClimbingLogCapacity);
GVAL_DECL(int, HillClimbingLogFirstIndex);
GVAL_DECL(int, HillClimbingLogSize);
typedef DPTR(HillClimbingLogEntry) PTR_HillClimbingLogEntry;

#endif