Reuse the work buffer when verifying online accounts from the OnlineAccountsManager import queue.

This is a hopeful fix for extra memory usage since mempow activated, due to adding a lot of load to the garbage collector. It only applies to accounts verified from the import queue; the optimization hasn't been applied to block processing. But verifying online accounts when processing blocks is rare and generally would only last a short amount of time.
This commit is contained in:
CalDescent 2022-10-28 16:54:53 +01:00
parent 30cd56165a
commit b64c053531
3 changed files with 18 additions and 6 deletions

View File

@ -1072,7 +1072,7 @@ public class Block {
// Validate the rest
for (OnlineAccountData onlineAccount : onlineAccounts)
if (!OnlineAccountsManager.getInstance().verifyMemoryPoW(onlineAccount))
if (!OnlineAccountsManager.getInstance().verifyMemoryPoW(onlineAccount, null))
return ValidationResult.ONLINE_ACCOUNT_NONCE_INCORRECT;
// Cache the valid online accounts as they will likely be needed for the next block

View File

@ -72,6 +72,11 @@ public class OnlineAccountsManager {
public static final int POW_BUFFER_SIZE_TESTNET = 1 * 1024 * 1024; // bytes
public static final int POW_DIFFICULTY_TESTNET = 5; // leading zero bits
// IMPORTANT: if we ever need to dynamically modify the buffer size using a feature trigger, the
// pre-allocated buffer below will NOT work, and we should instead use a dynamically allocated
// one for the transition period.
private static long[] POW_VERIFY_WORK_BUFFER = new long[getPoWBufferSize() / 8];
private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(4, new NamedThreadFactory("OnlineAccounts"));
private volatile boolean isStopping = false;
@ -339,7 +344,7 @@ public class OnlineAccountsManager {
}
// Validate mempow
if (!getInstance().verifyMemoryPoW(onlineAccountData)) {
if (!getInstance().verifyMemoryPoW(onlineAccountData, POW_VERIFY_WORK_BUFFER)) {
LOGGER.trace(() -> String.format("Rejecting online reward-share for account %s due to invalid PoW nonce", mintingAccount.getAddress()));
return false;
}
@ -582,7 +587,7 @@ public class OnlineAccountsManager {
OnlineAccountData ourOnlineAccountData = new OnlineAccountData(onlineAccountsTimestamp, signature, publicKey, nonce);
// Make sure to verify before adding
if (verifyMemoryPoW(ourOnlineAccountData)) {
if (verifyMemoryPoW(ourOnlineAccountData, null)) {
ourOnlineAccounts.add(ourOnlineAccountData);
}
}
@ -637,7 +642,7 @@ public class OnlineAccountsManager {
return nonce;
}
public boolean verifyMemoryPoW(OnlineAccountData onlineAccountData) {
public boolean verifyMemoryPoW(OnlineAccountData onlineAccountData, long[] workBuffer) {
// Require a valid nonce value
if (onlineAccountData.getNonce() == null || onlineAccountData.getNonce() < 0) {
return false;
@ -653,7 +658,7 @@ public class OnlineAccountsManager {
}
// Verify the nonce
return MemoryPoW.verify2(mempowBytes, getPoWBufferSize(), getPoWDifficulty(), nonce);
return MemoryPoW.verify2(mempowBytes, workBuffer, getPoWBufferSize(), getPoWDifficulty(), nonce);
}

View File

@ -99,6 +99,10 @@ public class MemoryPoW {
}
public static boolean verify2(byte[] data, int workBufferLength, long difficulty, int nonce) {
return verify2(data, null, workBufferLength, difficulty, nonce);
}
public static boolean verify2(byte[] data, long[] workBuffer, int workBufferLength, long difficulty, int nonce) {
// Hash data with SHA256
byte[] hash = Crypto.digest(data);
@ -111,7 +115,10 @@ public class MemoryPoW {
byteBuffer = null;
int longBufferLength = workBufferLength / 8;
long[] workBuffer = new long[longBufferLength];
if (workBuffer == null)
workBuffer = new long[longBufferLength];
long[] state = new long[4];
long seed = 8682522807148012L;