Skip to content

Commit

Permalink
Hashrate Calc improvements:
Browse files Browse the repository at this point in the history
We now use the actual time span of the shares for the window size, capped at 10 minutes. This adapts better to varying share submission rates.
The weighting system now uses an exponential decay function, which gives more emphasis to recent shares while still considering older ones.
Error handling has been added to prevent a single miner's calculation from breaking the entire function.
We now store the calculated hashrate in the workerStats object for potential use elsewhere in the application.
The total hashrate is now reported with fixed decimal places for consistency.
These changes should provide a more accurate and robust hashrate calculation while maintaining good performance. The exponential decay weighting will make the hashrate more responsive to recent changes in a miner's performance.
  • Loading branch information
argonmining committed Aug 22, 2024
1 parent f720c90 commit 8d538ac
Showing 1 changed file with 45 additions and 30 deletions.
75 changes: 45 additions & 30 deletions src/stratum/sharesManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface WorkerStats {
varDiffWindow: number;
minDiff: number;
recentShares: Denque<{ timestamp: number, difficulty: number }>;
hashrate: number; // Added hashrate property
}

type MinerData = {
Expand Down Expand Up @@ -82,7 +83,8 @@ export class SharesManager {
varDiffSharesFound: 0,
varDiffWindow: 0,
minDiff: 1, // Set to initial difficulty
recentShares: new Denque<{ timestamp: number, difficulty: number }>() // Initialize denque correctly
recentShares: new Denque<{ timestamp: number, difficulty: number }>(), // Initialize denque correctly
hashrate: 0 // Initialize hashrate property
};
minerData.workerStats = workerStats;
if (DEBUG) this.monitoring.debug(`SharesManager: Created new worker stats for ${workerName}`);
Expand Down Expand Up @@ -130,7 +132,8 @@ export class SharesManager {
varDiffSharesFound: 0,
varDiffWindow: 0,
minDiff: currentDifficulty,
recentShares: new Denque<{ timestamp: number, difficulty: number }>() // Initialize recentShares
recentShares: new Denque<{ timestamp: number, difficulty: number }>(), // Initialize recentShares
hashrate: 0 // Initialize hashrate property
}
};
this.miners.set(address, minerData);
Expand Down Expand Up @@ -255,39 +258,52 @@ export class SharesManager {
calcHashRates() {
let totalHashRate = 0;
const baseWindowSize = 10 * 60 * 1000; // 10 minutes base window
const now = Date.now();

this.miners.forEach((minerData, address) => {
const now = Date.now();

// Adjust the window size dynamically based on miner's activity
const sharesCount = minerData.workerStats.recentShares.length;
const windowSize = Math.min(baseWindowSize, sharesCount * 1000); // Minimum 1 second per share, max 10 min

// Extract relevant shares from recentShares
const relevantShares = minerData.workerStats.recentShares.toArray().filter(share => now - share.timestamp <= windowSize);

if (relevantShares.length === 0) return;

// Weighted average based on time proximity
let totalDifficulty = 0;
let totalWeight = 0;
relevantShares.forEach((share, index) => {
const weight = 1 + (index / relevantShares.length); // More recent shares get more weight
totalDifficulty += share.difficulty * weight;
totalWeight += weight;
});

const avgDifficulty = totalDifficulty / totalWeight;
const timeDifference = (now - relevantShares[0].timestamp) / 1000; // in seconds

const workerHashRate = (avgDifficulty * relevantShares.length) / timeDifference;
metrics.updateGaugeValue(minerHashRateGauge, [minerData.workerStats.workerName, address], workerHashRate);
totalHashRate += workerHashRate;
try {
const workerStats = minerData.workerStats;
const recentShares = workerStats.recentShares.toArray();

if (recentShares.length === 0) return;

// Adjust the window size dynamically based on miner's activity
const oldestShareTime = recentShares[0].timestamp;
const windowSize = Math.min(baseWindowSize, now - oldestShareTime);

// Filter relevant shares
const relevantShares = recentShares.filter(share => now - share.timestamp <= windowSize);

if (relevantShares.length === 0) return;

// Calculate weighted average difficulty
let totalWeightedDifficulty = 0;
let totalWeight = 0;
relevantShares.forEach((share, index) => {
const age = (now - share.timestamp) / windowSize;
const weight = Math.exp(-5 * age); // Exponential decay
totalWeightedDifficulty += share.difficulty * weight;
totalWeight += weight;
});

const avgDifficulty = totalWeightedDifficulty / totalWeight;
const timeDifference = (now - relevantShares[relevantShares.length - 1].timestamp) / 1000; // in seconds

const workerHashRate = (avgDifficulty * relevantShares.length) / timeDifference;

metrics.updateGaugeValue(minerHashRateGauge, [workerStats.workerName, address], workerHashRate);
totalHashRate += workerHashRate;

// Update worker's hashrate in workerStats
workerStats.hashrate = workerHashRate;
} catch (error) {
this.monitoring.error(`Error calculating hashrate for miner ${address}: ${error}`);
}
});

metrics.updateGaugeValue(poolHashRateGauge, ['pool', this.poolAddress], totalHashRate);
if (DEBUG) {
this.monitoring.debug(`SharesManager: Total pool hash rate updated to ${totalHashRate} GH/s`);
this.monitoring.debug(`SharesManager: Total pool hash rate updated to ${totalHashRate.toFixed(6)} GH/s`);
}
}

Expand Down Expand Up @@ -352,7 +368,6 @@ export class SharesManager {
this.monitoring.debug(`SharesManager: VarDiff - Adjusting difficulty for ${stats.workerName} from ${stats.minDiff} to ${newDiff}`);
stats.minDiff = newDiff;
this.updateSocketDifficulty(address, newDiff);
varDiff.labels(stats.workerName).set(newDiff);
} else {
this.monitoring.debug(`SharesManager: VarDiff - No change in difficulty for ${stats.workerName} (current difficulty: ${stats.minDiff})`);
}
Expand Down

0 comments on commit 8d538ac

Please sign in to comment.