Skip to content

Commit

Permalink
ethgas: new gasPriceHistogram implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
pkieltyka committed Oct 29, 2024
1 parent 6a28d10 commit 10cea80
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 22 deletions.
72 changes: 50 additions & 22 deletions ethgas/ethgas.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,36 +293,64 @@ func gasPriceHistogram(list []*big.Int) histogram {
return histogram{}
}

// Find min and max to determine bucket range
min := new(big.Int).Set(list[0])
hist := histogram{}
max := new(big.Int).Set(list[0])
for _, v := range list {
if v.Cmp(min) < 0 {
min.Set(v)
}
if v.Cmp(max) > 0 {
max.Set(v)
}
}

b1 := new(big.Int).Set(min)
b2 := new(big.Int).Add(min, BUCKET_RANGE)
h := uint64(0)
x := 0
// Calculate number of buckets needed
bucketCount := new(big.Int).Sub(max, min)
bucketCount.Div(bucketCount, BUCKET_RANGE)
bucketCount.Add(bucketCount, big.NewInt(1))

// Cap maximum number of buckets to prevent excessive memory usage
maxBuckets := 1000
if bucketCount.Cmp(big.NewInt(int64(maxBuckets))) > 0 {
bucketCount = big.NewInt(int64(maxBuckets))
}

// Initialize buckets
buckets := make(map[string]*histogramBucket)

// Distribute values into buckets
for _, v := range list {
gp := new(big.Int).Set(v)

fit:
if gp.Cmp(b1) >= 0 && gp.Cmp(b2) < 0 {
x++
if h == 0 {
h++
hist = append(hist, histogramBucket{value: new(big.Int).Set(b1), count: 1})
} else {
h++
hist[len(hist)-1].count = h
}
bucketIndex := new(big.Int).Sub(v, min)
bucketIndex.Div(bucketIndex, BUCKET_RANGE)

// Cap to maximum bucket if needed
if bucketIndex.Cmp(bucketCount) >= 0 {
bucketIndex.Set(bucketCount)
bucketIndex.Sub(bucketIndex, big.NewInt(1))
}

bucketValue := new(big.Int).Mul(bucketIndex, BUCKET_RANGE)
bucketValue.Add(bucketValue, min)

key := bucketValue.String()
if bucket, exists := buckets[key]; exists {
bucket.count++
} else {
h = 0
b1.Add(b1, BUCKET_RANGE)
b2.Add(b2, BUCKET_RANGE)
goto fit
buckets[key] = &histogramBucket{
value: new(big.Int).Set(bucketValue),
count: 1,
}
}
}

// trim over-paying outliers
// Convert map to slice
hist := make(histogram, 0, len(buckets))
for _, bucket := range buckets {
hist = append(hist, *bucket)
}

// Trim outliers and sort
hist2 := hist.trimOutliers()
sort.Slice(hist2, hist2.sortByValue)

Expand Down
142 changes: 142 additions & 0 deletions ethgas/histogram_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package ethgas

import (
"math/big"
"testing"

"github.com/stretchr/testify/require"
)

func TestGasPriceHistogram(t *testing.T) {
prices := []*big.Int{
big.NewInt(50194599653),
big.NewInt(51098044752),
big.NewInt(51098044752),
big.NewInt(52621431633),
big.NewInt(52751229408),
big.NewInt(52951916455),
big.NewInt(54247416415),
big.NewInt(55560857523),
big.NewInt(56143790224),
big.NewInt(56693739575),
big.NewInt(59908810569),
big.NewInt(64000000000),
big.NewInt(64000000000),
big.NewInt(64000000000),
big.NewInt(64000000000),
big.NewInt(64000000000),
big.NewInt(65252979548),
big.NewInt(65390806164),
big.NewInt(72816031286),
big.NewInt(73742998752),
big.NewInt(74736163398),
big.NewInt(74736163398),
big.NewInt(74736163398),
big.NewInt(74736163398),
big.NewInt(74736163398),
big.NewInt(75242863266),
big.NewInt(75990382873),
big.NewInt(75990382873),
big.NewInt(75990382873),
big.NewInt(76647067128),
big.NewInt(76647067128),
big.NewInt(76647077128),
big.NewInt(77413537799),
big.NewInt(77413537799),
big.NewInt(80250013656),
big.NewInt(80250013656),
big.NewInt(88021067710),
big.NewInt(94232293440),
big.NewInt(96831935030),
big.NewInt(113133907359),
big.NewInt(123049407008),
big.NewInt(127688602500),
big.NewInt(131193156896),
big.NewInt(131553579082),
big.NewInt(136066610534),
big.NewInt(138350648492),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(186000000000),
big.NewInt(272301328714),
big.NewInt(315000000000),
big.NewInt(315000000000),
big.NewInt(49130620939),
big.NewInt(49130620939),
big.NewInt(50194599653),
big.NewInt(51557452919),
big.NewInt(52539437403),
big.NewInt(52539437403),
big.NewInt(52621431633),
big.NewInt(52751229408),
big.NewInt(53300847192),
big.NewInt(53858781633),
big.NewInt(54247416415),
big.NewInt(55560857523),
big.NewInt(55637635843),
big.NewInt(55637635843),
big.NewInt(56143790224),
big.NewInt(63557452919),
big.NewInt(63557452919),
big.NewInt(63557452919),
big.NewInt(64000000000),
big.NewInt(64000000000),
big.NewInt(64000000000),
big.NewInt(64000000000),
big.NewInt(64000000000),
big.NewInt(65252979548),
big.NewInt(67122785457),
big.NewInt(68057452919),
big.NewInt(68057452919),
big.NewInt(68103952919),
big.NewInt(68103952919),
big.NewInt(69556191745),
big.NewInt(74509369374),
big.NewInt(74736163398),
big.NewInt(74736163398),
big.NewInt(74736163398),
big.NewInt(74736163398),
big.NewInt(74736163398),
big.NewInt(76647077128),
big.NewInt(77830927290),
big.NewInt(78251192494),
big.NewInt(81466263488),
big.NewInt(82077513316),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(83557452919),
big.NewInt(88021067710),
big.NewInt(113133907359),
big.NewInt(115789746359),
big.NewInt(126557452919),
big.NewInt(126557452919),
big.NewInt(131193156896),
big.NewInt(131553579082),
big.NewInt(149246055419),
}

hist := gasPriceHistogram(prices)
require.Equal(t, 19, len(hist))
}

0 comments on commit 10cea80

Please sign in to comment.