github.com/yandex/pandora@v0.5.32/core/schedule/line.go (about)

     1  package schedule
     2  
     3  import (
     4  	"math"
     5  	"time"
     6  
     7  	"github.com/yandex/pandora/core"
     8  )
     9  
    10  func NewLine(from, to float64, duration time.Duration) core.Schedule {
    11  	if from == to {
    12  		return NewConst(from, duration)
    13  	}
    14  	a := (to - from) / float64(duration/1e9)
    15  	b := from
    16  	xn := float64(duration) / 1e9
    17  	n := int64(a*xn*xn/2 + b*xn)
    18  	return NewDoAtSchedule(duration, n, lineDoAt(a, b))
    19  }
    20  
    21  type LineConfig struct {
    22  	From     float64       `validate:"min=0"`
    23  	To       float64       `validate:"min=0"`
    24  	Duration time.Duration `validate:"min-time=1ms"`
    25  }
    26  
    27  func NewLineConf(conf LineConfig) core.Schedule {
    28  	return NewLine(conf.From, conf.To, conf.Duration)
    29  }
    30  
    31  // x - duration from 0 to max.
    32  // RPS(x) = a * x + b // Line RPS schedule.
    33  // Number of shots from 0 to x = integral(RPS) from 0 to x = (a*x^2)/2 + b*x
    34  // Has shoot i. When it should be? i = (a*x^2)/2 + b*x => x = (sqrt(2*a*i + b^2) - b) / a
    35  func lineDoAt(a, b float64) func(i int64) time.Duration {
    36  	// Some common calculations.
    37  	twoA := 2 * a
    38  	bSquare := b * b
    39  	bilionDivA := 1e9 / a
    40  	return func(i int64) time.Duration {
    41  		//return time.Duration((math.Sqrt(2*a*float64(i)+b*b) - b) * 1e9 / a)
    42  		return time.Duration((math.Sqrt(twoA*float64(i)+bSquare) - b) * bilionDivA)
    43  	}
    44  }