bisq-network / bisq

A decentralized bitcoin exchange network
https://bisq.network
GNU Affero General Public License v3.0
4.64k stars 1.26k forks source link

Speed up Vote Result display, cycle list item selection & JSON export #7092

Closed stejbac closed 1 month ago

stejbac commented 1 month ago

Alleviate some hotspots displaying the Vote Result table (under DAO / Governance) for the first time after application startup, selecting a cycle list item to display the evaluated proposals for that cycle, and exporting the vote result history JSON. Also fix a bug in the JSON export, where the BSQ stake of each submitted ballot list was not added to the respective voteWeight fields in the JSON, with them incorrectly showing the merit alone (thus, many of the individual vote weights show as zero).

--

The two main hotspots revealed by profiling were the signature verification of each Merit object in the DAO state, when computing the merit totals, and searching the BSQ wallet for blind vote txs to determine if the user voted in the given cycle. The former hotspot affects JSON generation and the initial display of the cycle table the first time the Vote Result view is activated. The latter hotspot is revealed upon selection of a cycle in the table.

To alleviate the former hotspot, the merit calculations were parallelised when calling VoteResultView.doFillCycleList() upon view activation, and ensuring each Merit object is considered only once during JSON export, by moving merit calculations to the outer loop of VoteResultView.getVotingHistoryJson().

The latter hotspot was eliminated by replacing linear searches of the BSQ wallet for a given txId with a lookup into an added cached map, BsqWalletService.walletTransactionsById, as well as removing some needless looping over all the evaluated proposals of the cycle.

A third hotspot computing a map of ballots by proposal txId was eliminated from the cycle selection and evaluated proposal table display, by instead computing the map only once upon view activation, renaming the method VoteResultView.doFillCycleList() to doFillCycleListAndBallotMap().

--

Before the changes in this PR, JProfiler shows the following call tree when activating the view for the first time: Screenshot from 2024-05-07 16-02-45

The best that I was able to do to speed this up was parallelise the merit calculations (and hence signature checking) somewhat. As the validity of the signatures affects the final merit sums, the expensive signature checks cannot easily be avoided.

--

Before the changes in this PR, JProfiler shows the following call tree when toggling between cycle list item selections ten times: Screenshot from 2024-05-07 16-11-48

After the changes, the following call tree is seen instead: Screenshot from 2024-05-07 16-14-27

As can be seen, most of the remaining hotspots are coming from JavaFX. (I tried to optimise the method GUIUtil.removeChildrenFromGridPaneRows to remove the next biggest hotspot, but was not really able to.)

--

Before the changes in this PR, JProfiler shows the following call tree when exporting the JSON: Screenshot from 2024-05-07 16-21-19

It took more than six minutes, so I stopped profiling part way through. After the changes, the following call tree is seen instead: Screenshot from 2024-05-07 16-24-10

Verifying Merit signatures is still the biggest hotspot, but now they are verified without repetition.

boring-cyborg[bot] commented 1 month ago

Thanks for opening this pull request!

Please check out our contributor checklist and check if Travis or Codacy found any issues with your PR. Also make sure your commits are signed, and that you applied Bisq's code style and formatting.

A maintainer will add an is:priority label to your PR if it is up for compensation. Please see our Bisq Q1 2020 Update post for more details.