Avoid repeated scanning for swap trades via BsqTxListItem ctor

Precompute and pass a map of txIds to BsqSwapTrade instances to the
BsqTxListItem constructor in 'BsqTxView.updateList()', in place of the
tradable repository, so that the tradables don't need to be repeatedly
scanned to find the optional matching BSQ swap trade for each BSQ tx.

This fixes a quadratic time bug and significantly speeds up the BSQ tx
view load for users with many past trades.
This commit is contained in:
Steven Barclay 2023-03-08 14:23:15 +08:00
parent 3fa6b25789
commit e18b1e833d
No known key found for this signature in database
GPG Key ID: 9FED6BF1176D500B
2 changed files with 18 additions and 18 deletions

View File

@ -18,7 +18,6 @@
package bisq.desktop.main.dao.wallet.tx; package bisq.desktop.main.dao.wallet.tx;
import bisq.desktop.components.TxConfidenceListItem; import bisq.desktop.components.TxConfidenceListItem;
import bisq.desktop.main.funds.transactions.TradableRepository;
import bisq.desktop.util.DisplayUtils; import bisq.desktop.util.DisplayUtils;
import bisq.core.btc.wallet.BsqWalletService; import bisq.core.btc.wallet.BsqWalletService;
@ -36,6 +35,7 @@ import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionOutput; import org.bitcoinj.core.TransactionOutput;
import java.util.Date; import java.util.Date;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -66,7 +66,7 @@ class BsqTxListItem extends TxConfidenceListItem {
DaoFacade daoFacade, DaoFacade daoFacade,
Date date, Date date,
BsqFormatter bsqFormatter, BsqFormatter bsqFormatter,
TradableRepository tradableRepository) { Map<String, BsqSwapTrade> swapTradeByTxIdMap) {
super(transaction, bsqWalletService); super(transaction, bsqWalletService);
this.daoFacade = daoFacade; this.daoFacade = daoFacade;
@ -133,12 +133,7 @@ class BsqTxListItem extends TxConfidenceListItem {
else else
address = ""; address = "";
optionalBsqTrade = Optional.ofNullable(swapTradeByTxIdMap.get(txId));
optionalBsqTrade = tradableRepository.getAll().stream()
.filter(tradable -> tradable instanceof BsqSwapTrade)
.map(tradable -> (BsqSwapTrade) tradable)
.filter(tradable -> txId.equals(tradable.getTxId()))
.findFirst();
} }
BsqTxListItem() { BsqTxListItem() {

View File

@ -87,6 +87,7 @@ import javafx.util.Callback;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -351,17 +352,21 @@ public class BsqTxView extends ActivatableView<GridPane, Void> implements BsqBal
observableList.forEach(BsqTxListItem::cleanup); observableList.forEach(BsqTxListItem::cleanup);
List<Transaction> walletTransactions = bsqWalletService.getClonedWalletTransactions(); List<Transaction> walletTransactions = bsqWalletService.getClonedWalletTransactions();
Map<String, BsqSwapTrade> swapTradeByTxIdMap = tradableRepository.getAll().stream()
.filter(tradable -> tradable instanceof BsqSwapTrade)
.map(t -> (BsqSwapTrade) t)
.collect(Collectors.toMap(BsqSwapTrade::getTxId, t -> t));
List<BsqTxListItem> items = walletTransactions.stream() List<BsqTxListItem> items = walletTransactions.stream()
.map(transaction -> { .map(transaction -> new BsqTxListItem(transaction,
return new BsqTxListItem(transaction,
bsqWalletService, bsqWalletService,
btcWalletService, btcWalletService,
daoFacade, daoFacade,
// Use tx.getIncludedInBestChainAt() when available, otherwise use tx.getUpdateTime() // Use tx.getIncludedInBestChainAt() when available, otherwise use tx.getUpdateTime()
transaction.getIncludedInBestChainAt() != null ? transaction.getIncludedInBestChainAt() : transaction.getUpdateTime(), transaction.getIncludedInBestChainAt() != null ? transaction.getIncludedInBestChainAt() : transaction.getUpdateTime(),
bsqFormatter, bsqFormatter,
tradableRepository); swapTradeByTxIdMap)
}) )
.collect(Collectors.toList()); .collect(Collectors.toList());
observableList.setAll(items); observableList.setAll(items);
} }