Skip to content

Commit

Permalink
Add breakdown of fraud detection timings. #460
Browse files Browse the repository at this point in the history
  • Loading branch information
juliangruber committed Feb 17, 2025
1 parent 733c5b9 commit ce532c9
Showing 1 changed file with 43 additions and 4 deletions.
47 changes: 43 additions & 4 deletions lib/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export const evaluate = async ({

const started = Date.now()

const { committees } = await runFraudDetection({
const { committees, timings: fraudDetectionTimings } = await runFraudDetection({
roundIndex,
measurements,
sparkRoundDetails,
Expand Down Expand Up @@ -143,6 +143,9 @@ export const evaluate = async ({
point.intField('honest_measurements', measurementsToReward.length)
point.intField('set_scores_duration_ms', setScoresDuration)
point.intField('fraud_detection_duration_ms', fraudDetectionDuration)
for (const { influxField, duration } of fraudDetectionTimings) {
point.intField(`fraud_detection_timings_${influxField}_ms`, duration)
}

for (const [type, count] of Object.entries(evaluationOutcomes)) {
point.intField(`measurements_${type}`, count)
Expand Down Expand Up @@ -236,6 +239,7 @@ export const evaluate = async ({
* @param {import('./typings.js').RoundDetails} args.sparkRoundDetails
* @param {number} args.requiredCommitteeSize
* @param {Pick<Console, 'log' | 'error'>} args.logger
* @returns {Promise<{committees: import('./committee.js').Committee[], timings: {influxField: string, duration: number}[]}>}
*/
export const runFraudDetection = async ({
roundIndex,
Expand All @@ -244,6 +248,29 @@ export const runFraudDetection = async ({
requiredCommitteeSize,
logger
}) => {
const timings = {
taskBuilding: {
influxField: 'task_building',
start: null,
end: null
},
taskingEvaluation: {
influxField: 'tasking_evaluation',
start: null,
end: null
},
inetGroupsEvaluation: {
influxField: 'inet_groups_evaluation',
start: null,
end: null
},
majorityEvaluation: {
influxField: 'majority_evaluation',
start: null,
end: null
}
}

const randomness = await pRetry(
() => getRandomnessForSparkRound(Number(sparkRoundDetails.startEpoch)),
{
Expand All @@ -254,17 +281,18 @@ export const runFraudDetection = async ({
}
)

const taskBuildingStarted = Date.now()
timings.taskBuilding.start = new Date()
const tasksAllowedForStations = await getTasksAllowedForStations(
sparkRoundDetails,
randomness,
measurements
)
timings.taskBuilding.end = new Date()

logger.log(
'EVALUATE ROUND %s: built per-node task lists in %sms [Tasks=%s;TN=%s;Nodes=%s]',
roundIndex,
Date.now() - taskBuildingStarted,
timings.taskBuilding.end - timings.taskBuilding.start,
sparkRoundDetails.retrievalTasks.length,
sparkRoundDetails.maxTasksPerNode,
tasksAllowedForStations.size
Expand All @@ -274,6 +302,7 @@ export const runFraudDetection = async ({
// 1. Filter out measurements not belonging to any valid task in this round
// or missing some of the required fields like `inet_group`
//
timings.taskingEvaluation.start = new Date()
for (const m of measurements) {
// sanity checks to get nicer errors if we forget to set required fields in unit tests
assert(typeof m.inet_group === 'string', 'missing inet_group')
Expand All @@ -294,10 +323,12 @@ export const runFraudDetection = async ({
m.taskingEvaluation = 'TASK_WRONG_NODE'
}
}
timings.taskingEvaluation.end = new Date()

//
// 2. Accept only maxTasksPerNode measurements from each inet group
//
timings.inetGroupsEvaluation.start = new Date()
/** @type {Map<string, Measurement[]>} */
const inetGroups = new Map()
for (const m of measurements) {
Expand Down Expand Up @@ -364,10 +395,12 @@ export const runFraudDetection = async ({
debug(' pa: %s h: %s task: %s - REWARD', m.participantAddress, h, taskId)
}
}
timings.inetGroupsEvaluation.end = new Date()

//
// 3. Group measurements to per-task committees and find majority result
//
timings.majorityEvaluation.start = new Date()

// PERFORMANCE: Avoid duplicating the array of measurements because there are
// hundreds of thousands of them. All the function groupMeasurementsToCommittees
Expand All @@ -384,6 +417,7 @@ export const runFraudDetection = async ({
for (const c of committees.values()) {
c.evaluate({ requiredCommitteeSize })
}
timings.majorityEvaluation.end = new Date()

if (debug.enabled) {
for (const m of measurements) {
Expand All @@ -399,7 +433,12 @@ export const runFraudDetection = async ({
}
}

return { committees: Array.from(committees.values()) }
return {
committees: Array.from(committees.values()),
timings: Object
.values(timings)
.map(({ influxField, start, end }) => ({ influxField, duration: end - start }))
}
}

/**
Expand Down

0 comments on commit ce532c9

Please sign in to comment.