mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 23:06:39 +01:00
Fix cubic time bug in BondedRolesRepository.update()
Alleviate a cubic time bug during the update of the bonded roles repository, reducing it to quadratic running time. On Mainnet, this gives a roughly ten-fold speedup and should allow better scaling in the event that many new bonded roles are added. Replace calls to 'BondedRolesRepository.findBondedAssetByHash' with a lookup into a lazily initialised map of bonded assets (Roles) by hash (reset at the start of each call to 'BondRepository.update()' to prevent stale caching). This avoids rescanning the roles list for every pair of roles and lockup tx outputs, thus reducing the number of steps (to highest order) from: #roles * #roles * #lockup-tx-outputs to: #roles * #lockup-tx-outputs (The logs show 2 or 3 calls to 'BondedRepository.update()' every time a new block arrives, and while this was only taking around a second or so on Mainnet, it could potentially grow to something problematic with cubic scaling in the number of bonded roles.)
This commit is contained in:
parent
0a1df44daf
commit
3a97953152
2 changed files with 15 additions and 10 deletions
|
@ -28,6 +28,8 @@ import bisq.core.dao.state.model.blockchain.Tx;
|
|||
import bisq.core.dao.state.model.blockchain.TxOutput;
|
||||
import bisq.core.dao.state.model.blockchain.TxType;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionInput;
|
||||
|
@ -141,8 +143,9 @@ public abstract class BondRepository<B extends Bond<T>, T extends BondedAsset> i
|
|||
protected final DaoStateService daoStateService;
|
||||
protected final BsqWalletService bsqWalletService;
|
||||
|
||||
// This map is just for convenience. The data which are used to fill the map are stored in the DaoState (role, txs).
|
||||
// These maps are just for convenience. The data which are used to fill the maps are stored in the DaoState (role, txs).
|
||||
protected final Map<String, B> bondByUidMap = new HashMap<>();
|
||||
private Map<ByteString, T> bondedAssetByHashMap;
|
||||
@Getter
|
||||
protected final ObservableList<B> bonds = FXCollections.observableArrayList();
|
||||
|
||||
|
@ -212,9 +215,16 @@ public abstract class BondRepository<B extends Bond<T>, T extends BondedAsset> i
|
|||
|
||||
protected abstract Stream<T> getBondedAssetStream();
|
||||
|
||||
protected Map<ByteString, T> getBondedAssetByHashMap() {
|
||||
return bondedAssetByHashMap != null ? bondedAssetByHashMap
|
||||
: (bondedAssetByHashMap = getBondedAssetStream()
|
||||
.collect(Collectors.toMap(a -> ByteString.copyFrom(a.getHash()), a -> a, (a, b) -> a)));
|
||||
}
|
||||
|
||||
protected void update() {
|
||||
long ts = System.currentTimeMillis();
|
||||
log.debug("update");
|
||||
bondedAssetByHashMap = null;
|
||||
getBondedAssetStream().forEach(bondedAsset -> {
|
||||
String uid = bondedAsset.getUid();
|
||||
B bond = bondByUidMap.computeIfAbsent(uid, u -> createBond(bondedAsset));
|
||||
|
|
|
@ -27,12 +27,13 @@ import bisq.core.dao.state.model.governance.Proposal;
|
|||
import bisq.core.dao.state.model.governance.Role;
|
||||
import bisq.core.dao.state.model.governance.RoleProposal;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
@ -107,18 +108,12 @@ public class BondedRolesRepository extends BondRepository<BondedRole, Role> {
|
|||
// We used the hash of the bonded bondedAsset object as our hash in OpReturn of the lock up tx to have a
|
||||
// unique binding of the tx to the data object.
|
||||
byte[] hash = BondConsensus.getHashFromOpReturnData(opReturnData);
|
||||
Optional<Role> candidate = findBondedAssetByHash(hash);
|
||||
if (candidate.isPresent() && bondedAsset.equals(candidate.get()))
|
||||
Role candidateOrNull = getBondedAssetByHashMap().get(ByteString.copyFrom(hash));
|
||||
if (bondedAsset.equals(candidateOrNull))
|
||||
applyBondState(daoStateService, bond, lockupTx, lockupTxOutput);
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<Role> findBondedAssetByHash(byte[] hash) {
|
||||
return getBondedAssetStream()
|
||||
.filter(bondedAsset -> Arrays.equals(bondedAsset.getHash(), hash))
|
||||
.findAny();
|
||||
}
|
||||
|
||||
private Stream<RoleProposal> getBondedRoleProposalStream() {
|
||||
return daoStateService.getEvaluatedProposalList().stream()
|
||||
.filter(evaluatedProposal -> evaluatedProposal.getProposal() instanceof RoleProposal)
|
||||
|
|
Loading…
Add table
Reference in a new issue