Add covariance
Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai>
This commit is contained in:
parent
2caa7164a6
commit
29f5f451b3
@ -249,6 +249,14 @@ func (cov1 *covar) Covariance() float64 {
|
||||
return cov1.c / (cov1.n - 1)
|
||||
}
|
||||
|
||||
func (cov1 *covar) Variance() float64 {
|
||||
return cov1.m2 / (cov1.n - 1)
|
||||
}
|
||||
|
||||
func (v1 *covar) Stddev() float64 {
|
||||
return math.Sqrt(v1.Variance())
|
||||
}
|
||||
|
||||
func (cov1 *covar) AddPoint(x, y float64) {
|
||||
cov1.n += 1
|
||||
dx := x - cov1.meanX
|
||||
@ -279,11 +287,12 @@ func (cov1 *covar) Combine(cov2 *covar) {
|
||||
if cov2.n == 1 {
|
||||
cov1.AddPoint(cov2.meanX, cov2.meanY)
|
||||
}
|
||||
|
||||
out := covar{}
|
||||
out.n = cov1.n + cov2.n
|
||||
|
||||
dx := cov1.meanX - cov2.meanX
|
||||
out.meanX = cov1.meanX + dx*cov2.n/out.n
|
||||
out.meanX = cov1.meanX - dx*cov2.n/out.n
|
||||
out.m2 = cov1.m2 + cov2.m2 + dx*dx*cov1.n*cov2.n/out.n
|
||||
|
||||
dy := cov1.meanY - cov2.meanY
|
||||
@ -293,6 +302,13 @@ func (cov1 *covar) Combine(cov2 *covar) {
|
||||
*cov1 = out
|
||||
}
|
||||
|
||||
func (cov1 *covar) A() float64 {
|
||||
return cov1.Covariance() / cov1.Variance()
|
||||
}
|
||||
func (cov1 *covar) B() float64 {
|
||||
return cov1.meanY - cov1.meanX*cov1.A()
|
||||
}
|
||||
|
||||
type meanVar struct {
|
||||
n float64
|
||||
mean float64
|
||||
@ -347,15 +363,22 @@ func (v1 *meanVar) Combine(v2 *meanVar) {
|
||||
}
|
||||
|
||||
func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) {
|
||||
for _, gc := range et.GasCharges {
|
||||
for i, gc := range et.GasCharges {
|
||||
name := gc.Name
|
||||
if name == "OnIpldGetStart" {
|
||||
continue
|
||||
}
|
||||
tt := float64(gc.TimeTaken.Nanoseconds())
|
||||
if name == "OnIpldGet" {
|
||||
prev := et.GasCharges[i-1]
|
||||
if prev.Name != "OnIpldGetStart" {
|
||||
log.Warn("OnIpldGet without OnIpldGetStart")
|
||||
}
|
||||
tt += float64(prev.TimeTaken.Nanoseconds())
|
||||
}
|
||||
if eString, ok := gc.Extra.(string); ok {
|
||||
name += "-" + eString
|
||||
} else if eInt, ok := gc.Extra.(float64); ok {
|
||||
// handle scaling
|
||||
_ = eInt
|
||||
}
|
||||
|
||||
compGas := gc.VirtualComputeGas
|
||||
if compGas == 0 {
|
||||
compGas = 1
|
||||
@ -365,9 +388,19 @@ func tallyGasCharges(charges map[string]*stats, et types.ExecutionTrace) {
|
||||
s = new(stats)
|
||||
charges[name] = s
|
||||
}
|
||||
s.timeTaken.AddPoint(float64(gc.TimeTaken.Nanoseconds()))
|
||||
|
||||
ratio := float64(gc.TimeTaken.Nanoseconds()) / float64(compGas) * GasPerNs
|
||||
if extra, ok := gc.Extra.(float64); ok {
|
||||
if s.extraCovar == nil {
|
||||
s.extraCovar = &covar{}
|
||||
s.extra = &meanVar{}
|
||||
}
|
||||
s.extraCovar.AddPoint(extra, tt)
|
||||
s.extra.AddPoint(extra)
|
||||
}
|
||||
|
||||
s.timeTaken.AddPoint(tt)
|
||||
|
||||
ratio := tt / float64(compGas) * GasPerNs
|
||||
s.gasRatio.AddPoint(ratio)
|
||||
}
|
||||
for _, sub := range et.Subcalls {
|
||||
@ -491,6 +524,15 @@ var importAnalyzeCmd = &cli.Command{
|
||||
}
|
||||
s.timeTaken.Combine(&v.timeTaken)
|
||||
s.gasRatio.Combine(&v.gasRatio)
|
||||
|
||||
if v.extra != nil {
|
||||
if s.extra == nil {
|
||||
s.extra = &meanVar{}
|
||||
s.extraCovar = &covar{}
|
||||
}
|
||||
s.extra.Combine(v.extra)
|
||||
s.extraCovar.Combine(v.extraCovar)
|
||||
}
|
||||
}
|
||||
totalTime += res.totalTime
|
||||
}
|
||||
@ -504,7 +546,13 @@ var importAnalyzeCmd = &cli.Command{
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
s := charges[k]
|
||||
fmt.Printf("%s: incr by %f~%f\n", k, s.gasRatio.mean, s.gasRatio.Stddev())
|
||||
fmt.Printf("%s: incr by %f~%f; tt %f~%f\n", k, s.gasRatio.Mean(), s.gasRatio.Stddev(),
|
||||
s.timeTaken.Mean(), s.timeTaken.Stddev())
|
||||
if s.extra != nil {
|
||||
fmt.Printf("\t covar: %f, tt = %f * extra + %f\n", s.extraCovar.Covariance(),
|
||||
s.extraCovar.A(), s.extraCovar.B())
|
||||
fmt.Printf("\t extra: %f~%f\n", s.extra.Mean(), s.extra.Stddev())
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(invocs, func(i, j int) bool {
|
||||
|
@ -1,26 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStats(t *testing.T) {
|
||||
func TestMeanVar(t *testing.T) {
|
||||
N := 16
|
||||
ss := make([]*stats, N)
|
||||
ss := make([]*meanVar, N)
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
for i := 0; i < N; i++ {
|
||||
ss[i] = &stats{}
|
||||
ss[i] = &meanVar{}
|
||||
maxJ := rng.Intn(1000)
|
||||
for j := 0; j < maxJ; j++ {
|
||||
ss[i].AddPoint(rng.NormFloat64()*5 + 500)
|
||||
}
|
||||
t.Logf("mean: %f, stddev: %f, count %f", ss[i].mean, math.Sqrt(ss[i].variance()), ss[i].count)
|
||||
t.Logf("mean: %f, stddev: %f, count %f", ss[i].mean, ss[i].Stddev(), ss[i].n)
|
||||
}
|
||||
out := &stats{}
|
||||
out := &meanVar{}
|
||||
for i := 0; i < N; i++ {
|
||||
out.Combine(ss[i])
|
||||
t.Logf("combine: mean: %f, stddev: %f", out.mean, math.Sqrt(out.variance()))
|
||||
t.Logf("combine: mean: %f, stddev: %f", out.mean, out.Stddev())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCovar(t *testing.T) {
|
||||
N := 16
|
||||
ss := make([]*covar, N)
|
||||
rng := rand.New(rand.NewSource(1))
|
||||
for i := 0; i < N; i++ {
|
||||
ss[i] = &covar{}
|
||||
maxJ := rng.Intn(1000) + 500
|
||||
for j := 0; j < maxJ; j++ {
|
||||
x := rng.NormFloat64()*5 + 500
|
||||
ss[i].AddPoint(x, x*(rng.NormFloat64()/10+2)-rng.NormFloat64()-1000)
|
||||
}
|
||||
t.Logf("covar: %f, y = %f*x+%f @%.0f", ss[i].Covariance(), ss[i].A(), ss[i].B(), ss[i].n)
|
||||
}
|
||||
out := &covar{}
|
||||
for i := 0; i < N; i++ {
|
||||
out.Combine(ss[i])
|
||||
t.Logf("combine: covar: %f, y = %f*x+%f", ss[i].Covariance(), ss[i].A(), ss[i].B())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user