From 9ce9ffc694395b29eed60c0c890554937acfe486 Mon Sep 17 00:00:00 2001 From: Steven Barclay Date: Wed, 10 May 2023 05:04:22 +0100 Subject: [PATCH] Use TemporalAdjusterModel cache to speed up BSQ supply view Use the previously added 'ChartDataModel.toCachedTimeIntervalFn' to additionally speed up some of the charts in the BSQ supply view, in particular the trade fees & total burned BSQ, via the DaoChartDataModel methods 'getBsqTradeFeeByInterval' & 'getTotalBurnedByInterval'. (The other changes in the BSQ supply, such as proofs of burn or issuance, are too infrequent to benefit from the LocalDate caching.) For this to work, the filtered BSQ txs must be streamed in chronological order, so provide local methods 'get[Burnt|Trade]FeeTxStream()', to use in place of the DaoStateService methods 'get[Burnt|Trade]FeeTxs()', which return unordered HashSets. --- .../economy/supply/dao/DaoChartDataModel.java | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/dao/DaoChartDataModel.java b/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/dao/DaoChartDataModel.java index 1ce0ed17fe..31df6cea73 100644 --- a/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/dao/DaoChartDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/dao/economy/supply/dao/DaoChartDataModel.java @@ -45,6 +45,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; @@ -76,7 +77,6 @@ public class DaoChartDataModel extends ChartDataModel { this.daoStateService = daoStateService; - // TODO getBlockTime is the bottleneck. Add a lookup map to daoState to fix that in a dedicated PR. blockTimeOfIssuanceFunction = memoize(issuance -> { int height = daoStateService.getStartHeightOfCurrentCycle(issuance.getChainHeight()).orElse(0); return daoStateService.getBlockTime(height); @@ -218,7 +218,7 @@ public class DaoChartDataModel extends ChartDataModel { return totalBurnedByInterval; } - totalBurnedByInterval = getBurntBsqByInterval(daoStateService.getBurntFeeTxs(), getDateFilter()); + totalBurnedByInterval = getBurntBsqByInterval(getBurntFeeTxStream(), getDateFilter()); return totalBurnedByInterval; } @@ -227,7 +227,7 @@ public class DaoChartDataModel extends ChartDataModel { return bsqTradeFeeByInterval; } - bsqTradeFeeByInterval = getBurntBsqByInterval(daoStateService.getTradeFeeTxs(), getDateFilter()); + bsqTradeFeeByInterval = getBurntBsqByInterval(getTradeFeeTxStream(), getDateFilter()); return bsqTradeFeeByInterval; } @@ -247,7 +247,7 @@ public class DaoChartDataModel extends ChartDataModel { return proofOfBurnByInterval; } - proofOfBurnByInterval = getBurntBsqByInterval(daoStateService.getProofOfBurnTxs(), getDateFilter()); + proofOfBurnByInterval = getBurntBsqByInterval(daoStateService.getProofOfBurnTxs().stream(), getDateFilter()); return proofOfBurnByInterval; } @@ -278,10 +278,9 @@ public class DaoChartDataModel extends ChartDataModel { // Tagging started Nov 2021 // opReturn data from BTC fees: 1701721206fe6b40777763de1c741f4fd2706d94775d Set proofOfBurnTxs = daoStateService.getProofOfBurnTxs(); - Set feeTxs = proofOfBurnTxs.stream() - .filter(tx -> "1701721206fe6b40777763de1c741f4fd2706d94775d".equals(Hex.encode(tx.getLastTxOutput().getOpReturnData()))) - .collect(Collectors.toSet()); - proofOfBurnFromBtcFeesByInterval = getBurntBsqByInterval(feeTxs, getDateFilter()); + Stream feeTxStream = proofOfBurnTxs.stream() + .filter(tx -> "1701721206fe6b40777763de1c741f4fd2706d94775d".equals(Hex.encode(tx.getLastTxOutput().getOpReturnData()))); + proofOfBurnFromBtcFeesByInterval = getBurntBsqByInterval(feeTxStream, getDateFilter()); return proofOfBurnFromBtcFeesByInterval; } @@ -293,11 +292,10 @@ public class DaoChartDataModel extends ChartDataModel { // Tagging started Nov 2021 // opReturn data from delayed payout txs: 1701e47e5d8030f444c182b5e243871ebbaeadb5e82f // opReturn data from BM trades with a trade who got reimbursed by the DAO : 1701293c488822f98e70e047012f46f5f1647f37deb7 - Set feeTxs = daoStateService.getProofOfBurnTxs().stream() + Stream feeTxStream = daoStateService.getProofOfBurnTxs().stream() .filter(e -> "1701e47e5d8030f444c182b5e243871ebbaeadb5e82f".equals(Hex.encode(e.getLastTxOutput().getOpReturnData())) || - "1701293c488822f98e70e047012f46f5f1647f37deb7".equals(Hex.encode(e.getLastTxOutput().getOpReturnData()))) - .collect(Collectors.toSet()); - proofOfBurnFromArbitrationByInterval = getBurntBsqByInterval(feeTxs, getDateFilter()); + "1701293c488822f98e70e047012f46f5f1647f37deb7".equals(Hex.encode(e.getLastTxOutput().getOpReturnData()))); + proofOfBurnFromArbitrationByInterval = getBurntBsqByInterval(feeTxStream, getDateFilter()); return proofOfBurnFromArbitrationByInterval; } @@ -310,7 +308,7 @@ public class DaoChartDataModel extends ChartDataModel { Collection issuanceSetForType = daoStateService.getIssuanceItems(); // get all issued and burnt BSQ, not just the filtered date range Map tmpIssuedByInterval = getIssuedBsqByInterval(issuanceSetForType, e -> true); - Map tmpBurnedByInterval = new TreeMap<>(getBurntBsqByInterval(daoStateService.getBurntFeeTxs(), e -> true) + Map tmpBurnedByInterval = new TreeMap<>(getBurntBsqByInterval(getBurntFeeTxStream(), e -> true) .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> -e.getValue()))); Map tmpSupplyByInterval = getMergedMap(tmpIssuedByInterval, tmpBurnedByInterval, Long::sum); @@ -367,9 +365,10 @@ public class DaoChartDataModel extends ChartDataModel { Long::sum)); } - private Map getBurntBsqByInterval(Collection txs, Predicate dateFilter) { - return txs.stream() - .collect(Collectors.groupingBy(tx -> toTimeInterval(Instant.ofEpochMilli(tx.getTime())))) + private Map getBurntBsqByInterval(Stream txStream, Predicate dateFilter) { + var toTimeIntervalFn = toCachedTimeIntervalFn(); + return txStream + .collect(Collectors.groupingBy(tx -> toTimeIntervalFn.applyAsLong(Instant.ofEpochMilli(tx.getTime())))) .entrySet() .stream() .filter(entry -> dateFilter.test(entry.getKey())) @@ -384,6 +383,20 @@ public class DaoChartDataModel extends ChartDataModel { return date -> date >= TAG_DATE.getTimeInMillis() / 1000; // we use seconds } + // TODO: Consider moving these two methods to DaoStateService: + + private Stream getBurntFeeTxStream() { + return daoStateService.getBlocks().stream() + .flatMap(b -> b.getTxs().stream()) + .filter(tx -> tx.getBurntFee() > 0); + } + + private Stream getTradeFeeTxStream() { + return daoStateService.getBlocks().stream() + .flatMap(b -> b.getTxs().stream()) + .filter(tx -> tx.getTxType() == TxType.PAY_TRADE_FEE); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Utils