[IMPROVED] Unified user speed statistics

* [ADDED] getUserMiningStats to fetch all speed related data
 * Uses global cache if available, falls back to local query and then
   local caches
* [REMOVED] getUserHashrate, getUserSharerate, getUserAvgShareDifficulty
* [UPDATED] All code occurences for the above to use the new system

Probably won't change much since global cache was already used but does
help on the Dashboard since we combine at least 2 calls into one.
This commit is contained in:
Sebastian Grewe 2014-02-26 09:27:32 +01:00
parent d82ff63006
commit 78619c1427
7 changed files with 38 additions and 95 deletions

View File

@ -489,47 +489,6 @@ class Statistics extends Base {
}
}
/**
* Fetch total user hashrate based on shares and archived shares
* @param $username string username
* @param $account_id int account id
* @return data integer Current Hashrate in khash/s
**/
public function getUserHashrate($username, $account_id=NULL, $interval=180) {
$this->debug->append("STA " . __METHOD__, 4);
// Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL
if ($this->getGetCache() && $data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) {
if (array_key_exists($account_id, $data['data']))
return $data['data'][$account_id]['hashrate'];
// We have no cached value, we return defaults
return 0;
}
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare("
SELECT
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
FROM (
SELECT
id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM
shares
WHERE username LIKE ?
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
AND our_result = 'Y'
UNION
SELECT
share_id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM
shares_archive
WHERE username LIKE ?
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
AND our_result = 'Y') AS temp");
$username = $username . ".%";
if ($this->checkStmt($stmt) && $stmt->bind_param("isisi", $interval, $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() )
return $this->memcache->setCache(__FUNCTION__ . $account_id, (float)$result->fetch_object()->hashrate);
return $this->sqlError();
}
public function getUserUnpaidPPSShares($username, $account_id=NULL, $last_paid_pps_id) {
$this->debug->append("STA " . __METHOD__, 4);
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
@ -546,60 +505,32 @@ class Statistics extends Base {
return $this->sqlError();
}
/**
* Get average share difficulty across all workers for user
* @param username string username
* @param $account_id int account id
* @param interval int Data interval in seconds
* @return double Share difficulty or 0
**/
public function getUserShareDifficulty($username, $account_id=NULL, $interval=180) {
$this->debug->append("STA " . __METHOD__, 4);
// Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL
if ($this->getGetCache() && $data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) {
if (array_key_exists($account_id, $data['data']))
return $data['data'][$account_id]['avgsharediff'];
// We have no cached value, we return defaults
return 0;
}
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare("
SELECT
IFNULL(AVG(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS avgsharediff,
COUNT(s.id) AS total
FROM " . $this->share->getTableName() . " AS s
WHERE username LIKE ?
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
AND our_result = 'Y'
");
$username = $username . ".%";
if ($this->checkStmt($stmt) && $stmt->bind_param("si", $username, $interval) && $stmt->execute() && $result = $stmt->get_result() )
return $this->memcache->setCache(__FUNCTION__ . $account_id, (float)$result->fetch_object()->avgsharediff);
return $this->sqlError();
}
/**
* Get Shares per x interval by user
* @param username string username
* @param $account_id int account id
* @return data integer Current Sharerate in shares/s
**/
public function getUserSharerate($username, $account_id=NULL, $interval=180) {
public function getUserMiningStats($username, $account_id=NULL, $interval=180) {
$this->debug->append("STA " . __METHOD__, 4);
// Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL
if ($this->getGetCache() && $data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) {
if (array_key_exists($account_id, $data['data']))
return $data['data'][$account_id]['sharerate'];
// We have no cached value, we return defaults
return 0;
if (array_key_exists($account_id, $data['data'])) {
$retData['hashrate'] = $data['data'][$account_id]['hashrate'];
$retData['sharerate'] = $data['data'][$account_id]['sharerate'];
$retData['avgsharediff'] = $data['data'][$account_id]['avgsharediff'];
return $retData;
}
}
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare("
SELECT
IFNULL(COUNT(*) / ?, 0) AS sharerate
IFNULL(COUNT(*) / ?, 0) AS sharerate,
IFNULL(ROUND(SUM(difficulty) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000, 2), 0) AS hashrate,
IFNULL(AVG(difficulty), 0) AS avgsharediff
FROM (
SELECT
id
id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM
shares
WHERE username LIKE ?
@ -607,7 +538,7 @@ class Statistics extends Base {
AND our_result = 'Y'
UNION
SELECT
share_id
share_id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM
shares_archive
WHERE username LIKE ?
@ -615,8 +546,8 @@ class Statistics extends Base {
AND our_result = 'Y'
) AS temp");
$username = $username . ".%";
if ($this->checkStmt($stmt) && $stmt->bind_param("isisi", $interval, $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() )
return $this->memcache->setCache(__FUNCTION__ . $account_id, (float)$result->fetch_object()->sharerate);
if ($this->checkStmt($stmt) && $stmt->bind_param("iisisi", $interval, $interval, $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() )
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_assoc());
return $this->sqlError();
}

View File

@ -58,11 +58,12 @@ if (isset($_REQUEST['filter'])) {
$aBalance = $transaction->getBalance($aUser['id']);
$aUser['balance'] = $aBalance['confirmed'];
$aUser['signup_timestamp'] = $user->getSignupTime($aUser['id']);
$aUser['hashrate'] = $statistics->getUserHashrate($aUser['username'], $aUser['id']);
$aUserMiningStats = $statistics->getUserMiningStats($aUser['username'], $aUser['id']);
$aUser['hashrate'] = $aUserMiningStats['hashrate'];
if ($config['payout_system'] == 'pps') {
$aUser['sharerate'] = $statistics->getUserSharerate($aUser['username'], $aUser['id']);
$aUser['difficulty'] = $statistics->getUserShareDifficulty($aUser['username'], $aUser['id']);
$aUser['sharerate'] = $aUserMiningStats['sharerate'];
$aUser['difficulty'] = $aUserMiningStats['avgsharediff'];
$aUser['estimates'] = $statistics->getUserEstimates($aUser['sharerate'], $aUser['difficulty'], $user->getUserDonatePercent($aUser['id']), $user->getUserNoFee($aUser['id']), $statistics->getPPSValue());
} else {
$aUser['estimates'] = $statistics->getUserEstimates($aRoundShares, $aUser['shares'], $aUser['donate_percent'], $aUser['no_fees']);

View File

@ -43,9 +43,10 @@ if ( ! $dNetworkHashrateModifier = $setting->getValue('statistics_network_hashra
$statistics->setGetCache(false);
$dPoolHashrate = $statistics->getCurrentHashrate($interval);
if ($dPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $dPoolHashrate;
$dPersonalHashrate = $statistics->getUserHashrate($username, $user_id, $interval);
$dPersonalSharerate = $statistics->getUserSharerate($username, $user_id, $interval);
$dPersonalShareDifficulty = $statistics->getUserShareDifficulty($username, $user_id, $interval);
$aUserMiningStats = $statistics->getUserMiningStats($username, $user_id, $interval);
$dPersonalHashrate = $aUserMiningStats['hashrate'];
$dPersonalSharerate = $aUserMiningStats['sharerate'];
$dPersonalShareDifficulty = $aUserMiningStats['avgsharediff'];
$statistics->setGetCache(true);
// Use caches for this one

View File

@ -13,7 +13,8 @@ if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interva
// Gather un-cached data
$statistics->setGetCache(false);
$hashrate = $statistics->getUserHashrate($username, $user_id, $interval);
$aUserMiningStats = $statistics->getUserMiningStats($username, $user_id, $interval);
$hashrate = $aUserMiningStats['hashrate'];
$statistics->setGetCache(true);
// Output JSON

View File

@ -13,7 +13,8 @@ if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interva
// Gather un-cached data
$statistics->setGetCache(false);
$sharerate = $statistics->getUserSharerate($username, $user_id, $interval);
$aUserMiningStats = $statistics->getUserMiningStats($username, $user_id, $interval);
$sharerate = $aUserMiningStats['sharerate'];
$statistics->setGetCache(true);
// Output JSON format

View File

@ -7,15 +7,22 @@ $api->isActive();
// Check user token
$user_id = $api->checkAccess($user->checkApiKey($_REQUEST['api_key']), @$_REQUEST['id']);
$username = $user->getUsername($user_id);
// Fetch some settings
if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interval = 300;
// Fetch transaction summary
$aTransactionSummary = $transaction->getTransactionSummary($user_id);
// User mining status
$aUserMiningStats = $statistics->getUserMiningStats($username, $user_id, $interval);
// Output JSON format
$data = array(
'username' => $username,
'shares' => $statistics->getUserShares($username, $user_id),
'hashrate' => $statistics->getUserHashrate($username, $user_id),
'sharerate' => $statistics->getUserSharerate($username, $user_id)
'hashrate' => $aUserMiningStats['hashrate'],
'sharerate' => $aUserMiningStats['sharerate']
);
echo $api->get_json($data);

View File

@ -133,9 +133,10 @@ if (@$_SESSION['USERDATA']['id']) {
// Other userdata that we can cache savely
$aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['username'], $_SESSION['USERDATA']['id']);
$aGlobal['userdata']['rawhashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['username'], $_SESSION['USERDATA']['id']);
$aUserMiningStats = $statistics->getUserMiningStats($_SESSION['USERDATA']['username'], $_SESSION['USERDATA']['id']);
$aGlobal['userdata']['rawhashrate'] = $aUserMiningStats['hashrate'];
$aGlobal['userdata']['hashrate'] = $aGlobal['userdata']['rawhashrate'] * $dPersonalHashrateModifier;
$aGlobal['userdata']['sharerate'] = $statistics->getUserSharerate($_SESSION['USERDATA']['username'], $_SESSION['USERDATA']['id']);
$aGlobal['userdata']['sharerate'] = $aUserMiningStats['sharerate'];
switch ($config['payout_system']) {
case 'prop':