Skip to content

Commit b0c89b4

Browse files
authored
Merge branch 'main' into 24398-quiescence-follow-up
2 parents ef674c8 + bc67352 commit b0c89b4

File tree

6 files changed

+109
-45
lines changed

6 files changed

+109
-45
lines changed

platform-sdk/consensus-hashgraph-impl/src/main/java/org/hiero/consensus/hashgraph/impl/EventImpl.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.hiero.consensus.hashgraph.impl.consensus.CandidateWitness;
1212
import org.hiero.consensus.hashgraph.impl.consensus.DeGen;
1313
import org.hiero.consensus.hashgraph.impl.consensus.LocalConsensusGeneration;
14+
import org.hiero.consensus.hashgraph.impl.metrics.Sequencer;
1415
import org.hiero.consensus.model.event.EventDescriptorWrapper;
1516
import org.hiero.consensus.model.event.LinkedEvent;
1617
import org.hiero.consensus.model.event.PlatformEvent;
@@ -77,6 +78,9 @@ public class EventImpl extends LinkedEvent<EventImpl> implements Clearable {
7778
/** The deterministic generation, see {@link DeGen} */
7879
private int deGen = 0;
7980

81+
/** A unique sequence number determining the order in which this event was processed */
82+
private long sequence = Sequencer.NO_SEQUENCE;
83+
8084
/**
8185
* Constructor
8286
*
@@ -519,6 +523,24 @@ public void setDeGen(final int deGen) {
519523
this.deGen = deGen;
520524
}
521525

526+
/**
527+
* Get the sequence number of this event, which determines the order in which this event was processed.
528+
*
529+
* @return the sequence number of this event
530+
*/
531+
public long getSequence() {
532+
return sequence;
533+
}
534+
535+
/**
536+
* Set the sequence number of this event, which determines the order in which this event was processed.
537+
*
538+
* @param sequence the sequence number to set
539+
*/
540+
public void setSequence(final long sequence) {
541+
this.sequence = sequence;
542+
}
543+
522544
//
523545
// Overrides
524546
//

platform-sdk/consensus-hashgraph-impl/src/main/java/org/hiero/consensus/hashgraph/impl/consensus/ConsensusImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ private List<EventImpl> getStronglySeenInPreviousRound(final EventImpl event) {
713713
.map(EventImpl::getBaseEvent)
714714
.toList();
715715
// all rounds before this round are now decided, and appropriate events marked consensus
716-
consensusMetrics.consensusReachedOnRound();
716+
consensusMetrics.consensusReachedOnRound(decidedRoundNumber);
717717

718718
// lastConsensusTime is updated above with the last transaction in the last event that reached consensus
719719
// if no events reach consensus, then we need to calculate the lastConsensusTime differently

platform-sdk/consensus-hashgraph-impl/src/main/java/org/hiero/consensus/hashgraph/impl/metrics/ConsensusMetrics.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ public interface ConsensusMetrics {
3232

3333
/**
3434
* Update a statistics accumulator a round has reached consensus.
35+
* @param round the round number that reached consensus
3536
*/
36-
void consensusReachedOnRound();
37+
void consensusReachedOnRound(final long round);
3738

3839
/**
3940
* Update a statistics accumulator when an event reaches consensus
@@ -69,20 +70,6 @@ public interface ConsensusMetrics {
6970
*/
7071
void roundIncrementedByStronglySeen();
7172

72-
/**
73-
* Returns the average difference in creation time and consensus time for self events.
74-
*
75-
* @return the weighted mean
76-
*/
77-
double getAvgSelfCreatedTimestamp();
78-
79-
/**
80-
* Returns the average difference in creation time and consensus time for other events.
81-
*
82-
* @return weighted mean
83-
*/
84-
double getAvgOtherReceivedTimestamp();
85-
8673
/**
8774
* Report the weight of the judges when a round comes to consensus.
8875
*

platform-sdk/consensus-hashgraph-impl/src/main/java/org/hiero/consensus/hashgraph/impl/metrics/ConsensusMetricsImpl.java

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ public class ConsensusMetricsImpl implements ConsensusMetrics {
9999

100100
private final Counter roundIncrementedByStronglySeen;
101101

102+
private final AverageAndMax numVotingRounds;
103+
private final AverageAndMax numEventsAddedUntilConsensus;
104+
private final AverageAndMax graphDepthUntilConsensus;
105+
102106
private final NodeId selfId;
103107

104108
/**
@@ -112,6 +116,8 @@ public class ConsensusMetricsImpl implements ConsensusMetrics {
112116
*/
113117
private static volatile long lastRoundNumber = -1;
114118

119+
private final Sequencer sequencer = new Sequencer();
120+
115121
/**
116122
* Constructor of {@code ConsensusMetricsImpl}
117123
*
@@ -146,6 +152,25 @@ public ConsensusMetricsImpl(final NodeId selfId, final Metrics metrics) {
146152
+ "created",
147153
FORMAT_4_2);
148154
roundIncrementedByStronglySeen = metrics.getOrCreate(ROUND_INCREMENT_STRONGLY_SEEN_CONFIG);
155+
156+
numVotingRounds = new AverageAndMax(
157+
metrics,
158+
INTERNAL_CATEGORY,
159+
"numVotingRounds",
160+
"number of voting rounds until consensus is reached",
161+
FORMAT_10_3);
162+
numEventsAddedUntilConsensus = new AverageAndMax(
163+
metrics,
164+
INTERNAL_CATEGORY,
165+
"numEventsAddedUntilConsensus",
166+
"after adding event E, how many events are added before E reaches consensus",
167+
FORMAT_10_3);
168+
graphDepthUntilConsensus = new AverageAndMax(
169+
metrics,
170+
INTERNAL_CATEGORY,
171+
"graphDepthUntilConsensus",
172+
"depth of the graph needed to reach consensus (in generations)",
173+
FORMAT_10_3);
149174
}
150175

151176
/**
@@ -154,6 +179,7 @@ public ConsensusMetricsImpl(final NodeId selfId, final Metrics metrics) {
154179
@Override
155180
public void addedEvent(final EventImpl event) {
156181
// this method is only ever called by 1 thread, so no need for locks
182+
sequencer.assignSequenceNumber(event);
157183
if (!Objects.equals(selfId, event.getCreatorId())
158184
&& event.getRoundCreated() > lastRoundNumber) { // if first event in a round
159185
final Instant now = Instant.now();
@@ -192,15 +218,29 @@ public void lastFamousInRound(final EventImpl event) {
192218
* {@inheritDoc}
193219
*/
194220
@Override
195-
public void consensusReachedOnRound() {
221+
public void consensusReachedOnRound(final long round) {
196222
roundsPerSecond.cycle();
223+
final EventImpl lastEventAdded = sequencer.getLastEventAdded();
224+
if (lastEventAdded != null) {
225+
// we have reached consensus for a round, so the last event that we added decided fame
226+
// the difference between the round number of the event that decided fame and the consensus round gives us
227+
// the number of voting rounds that were needed to reach consensus for this round
228+
numVotingRounds.update(lastEventAdded.getRoundCreated() - round);
229+
}
197230
}
198231

199232
/**
200233
* {@inheritDoc}
201234
*/
202235
@Override
203236
public void consensusReached(final EventImpl event) {
237+
final EventImpl lastEventAdded = sequencer.getLastEventAdded();
238+
if (lastEventAdded != null) {
239+
// this should never be null
240+
// but if there is a bug, its better to not have metrics than to throw an NPE
241+
numEventsAddedUntilConsensus.update(lastEventAdded.getSequence() - event.getSequence());
242+
graphDepthUntilConsensus.update(lastEventAdded.getDeGen() - event.getDeGen());
243+
}
204244
// Keep a running average of how many seconds from when I first know of an event
205245
// until it achieves consensus. Actually, keep two such averages: one for events I
206246
// create, and one for events I receive.
@@ -237,23 +277,7 @@ public void dotProductTime(final long nanoTime) {
237277
* {@inheritDoc}
238278
*/
239279
@Override
240-
public double getAvgSelfCreatedTimestamp() {
241-
return avgSelfCreatedTimestamp.get();
242-
}
243-
244-
/**
245-
* {@inheritDoc}
246-
*/
247-
@Override
248-
public double getAvgOtherReceivedTimestamp() {
249-
return avgOtherReceivedTimestamp.get();
250-
}
251-
252-
/**
253-
* {@inheritDoc}
254-
*/
255-
@Override
256-
public void judgeWeights(long weight) {
280+
public void judgeWeights(final long weight) {
257281
avgJudgesWeight.update(weight);
258282
}
259283

platform-sdk/consensus-hashgraph-impl/src/main/java/org/hiero/consensus/hashgraph/impl/metrics/NoOpConsensusMetrics.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public void lastFamousInRound(final EventImpl event) {
2020
}
2121

2222
@Override
23-
public void consensusReachedOnRound() {
23+
public void consensusReachedOnRound(final long round) {
2424
// no-op
2525
}
2626

@@ -34,16 +34,6 @@ public void dotProductTime(final long nanoTime) {
3434
// no-op
3535
}
3636

37-
@Override
38-
public double getAvgSelfCreatedTimestamp() {
39-
return 0;
40-
}
41-
42-
@Override
43-
public double getAvgOtherReceivedTimestamp() {
44-
return 0;
45-
}
46-
4737
@Override
4838
public void judgeWeights(long weight) {
4939
// no-op
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
package org.hiero.consensus.hashgraph.impl.metrics;
3+
4+
import edu.umd.cs.findbugs.annotations.NonNull;
5+
import edu.umd.cs.findbugs.annotations.Nullable;
6+
import org.hiero.consensus.hashgraph.impl.EventImpl;
7+
8+
/**
9+
* Assigns an auto-incrementing sequence number to events as they are added to the system. This is used for metrics purposes.
10+
*/
11+
public class Sequencer {
12+
/** The first sequence number assigned to an event. */
13+
public static final long FIRST_SEQUENCE = 1L;
14+
/** A sequence number that indicates that the event has not been assigned a sequence number. */
15+
public static final long NO_SEQUENCE = -1L;
16+
/** The next sequence number to assign to an event. */
17+
private long nextIndex = FIRST_SEQUENCE;
18+
/** The last event that was added to the system. */
19+
private EventImpl lastEventAdded = null;
20+
21+
/**
22+
* Assigns a sequence number to the given event and updates the last event added. The sequence number is assigned
23+
* in the order that events are added to the system.
24+
*
25+
* @param event the event to assign a sequence number to
26+
*/
27+
public void assignSequenceNumber(@NonNull final EventImpl event) {
28+
event.setSequence(nextIndex);
29+
nextIndex++;
30+
lastEventAdded = event;
31+
}
32+
33+
/**
34+
* Gets the last event that was added to the system
35+
*
36+
* @return the last event that was added to the system, or null if no events have been added
37+
*/
38+
public @Nullable EventImpl getLastEventAdded() {
39+
return lastEventAdded;
40+
}
41+
}

0 commit comments

Comments
 (0)