Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

metrics: Synchronous metrics #29775

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
zeim839 wants to merge 4 commits into ethereum:master
base: master
Choose a base branch
Loading
from zeim839:synchronous-metrics

Conversation

@zeim839
Copy link
Contributor

@zeim839 zeim839 commented May 14, 2024
edited
Loading

This pull-request is based on #27918, which was not accepted because go-ethereum/metrics was being refactored at the time.

It removes concurrent EWMAs and Meters; rates are synchronously computed whenever Update() or Snapshot() are called. We introduce sampling periods to imitate clock ticks: events arriving within a 5s period are accumulated in an 'uncounted' variable, which is used to calculate the EWMA per-second rate once the 5s period elapses.

// NewEWMA constructs a new EWMA with the given alpha and sampling period.
func NewEWMA(alpha float64, period time.Duration) EWMA {
	return &StandardEWMA{alpha: alpha, period: period, ts: time.Now()}
}
// We imitate the current implementation by specifying 5-second clock ticks.
// Updates that arrive within 5s of each other are accumulated, and the EWMA
// is updated once the next 5s interval begins.
func NewEWMA1() EWMA {
 // create an EWMA with a 5-second sampling period.
	return NewEWMA(1-math.Exp(-5.0/60.0/1), 5*time.Second)
}
m := NewEWMA1()
m.Update(10)
// Returns 0 because a whole sampling period has not yet elapsed, the EWMA is
// still accumulating events.
fmt.Println(m.Snapshot().Rate())
for range time.Tick(5 * time.Seconds) {
 // Rate will begin at 10 and then exponentially decline. Rate is only manually
 // updated whenever Snapshot() or Update() is called, no need for a clock.
 fmt.Println(m1.Snapshot().Rate())
}

Consequently, Timer and Meter (which use EWMAs) Stop()'s are removed because they are not handled by a concurrent routine. To maintain consistency, Meter is also modified so that its rateMean is updated only once per 5s (i.e. it changes in tandem with the underlying EWMAs):

// Mark records the occurrence of n events.
func (m *StandardMeter) Mark(n int64) {
	m.mutex.Lock()
	defer m.mutex.Unlock()
	// Synchronize rateMean so that it's only updated after
	// a sampling period elapses.
	if elapsed := time.Since(m.lastMark); elapsed >= 5*time.Second {
		m.lastMark = m.lastMark.Add(elapsed)
		m.count += m.uncounted
		m.uncounted = 0
	}
	m.uncounted += n
	m.a1.Update(n)
	m.a5.Update(n)
	m.a15.Update(n)
}

Testing has also been modified, such that expected EWMA values are calculated by unit tests instead of having to cross-check hardcoded values.

Why?

In the worst case, complexity remains the same and you're computing EWMAs every 5 seconds (but without a separate goroutine).

In the best case, stale EWMAs are garbage collected (you dont have to worry about calling Stop()) and you've saved yourself some processing power.

@zeim839 zeim839 changed the title (削除) Synchronous metrics (削除ここまで) (追記) metrics: Synchronous metrics (追記ここまで) May 14, 2024
@zeim839 zeim839 marked this pull request as ready for review May 14, 2024 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /