bitshares / bitshares1-core

Software to run the old chain (before 2015-10-13). Code for current chain is https://github.com/bitshares/bitshares-core
https://bitshares.org/
The Unlicense
219 stars 174 forks source link

Market history commands bad performance #1202

Open svk31 opened 9 years ago

svk31 commented 9 years ago

I'd like to add order histories to the bitsharesblocks asset pages but the performance of the above rpc call is making it impossible. Simply looping over the 25 or so market assets and getting the order history (only versus BTS) takes about 15 seconds on my personal computer. Would it be possible to add an index or otherwise speed up this call?

vikramrajkumar commented 9 years ago

@svk31 What is your primary use-case? For example: listing market history for all market-pegged assets over the last day's worth of blocks

Given the use case I'll see how we can arrange things in the backend.

vikramrajkumar commented 9 years ago

@valzav Do you use this command in the GUI? What is the normal use-case?

valzav commented 9 years ago

I use it to display blockhain orders history on the market page

vikramrajkumar commented 9 years ago

@valzav Do you show only the user's order history or all history? How many transactions do you limit it to?

valzav commented 9 years ago

I show both blockchain and user's history. blockchain_market_order_history's limit is 500

svk31 commented 9 years ago

@vikramrajkumar That sounds like a reasonable use case yea, I'd also like to use it for user issued assets. The most recent data is definitely most interesting here, querying by date as in blockchain_market_price_history would be useful for me but not essential.

Compared to the wallet use case the big difference for me is that I want to gather ALL the different combinations of quote and base assets, so it can get pretty heavy..

vikramrajkumar commented 9 years ago

Also blockchain_market_price_history: https://github.com/BitShares/web_wallet/issues/637#issuecomment-91795936

abitmore commented 9 years ago

We're using a structurestd::map<market_history_key(quote_id, base_id, granularity, start_time), value> to store market_price_history data, maybe it's the reason why the blockchain_market_price_history API is slow? It's said that iterating over large std::map object is slow (in compare with std:vector). Will it help if we change it to somewhat like this structure: std::map<market_history_key(quote_id, base_id, granularity), std::vector<pair<start_time, value>>>? In this way iterating will be much faster, looking up will be not slower if use a binary search algorithm inside the vector, and the cost for storing new data is almost constant.

abitmore commented 9 years ago

A B-tree scales better than a vector and provides similar sequential read performance.

abitmore commented 9 years ago

Some thoughts about blockchain_market_order_history:

Further thoughs:

abitmore commented 9 years ago

Some of my earlier thoughts are not accurate. The map is a container, which could be implemented using BST (binary search tree, which std::map uses) or other data structure (like B-tree). Fortunately it's easy to change the underlying data structure with current fc library if we need.

However, all these trees don't work well with big [skip_count] parameter, unless there is a children_count field maintained in every tree-node, or a global numeric market_trx_id added to every market transaction and maintain a dedicated index on it.

Can we change this parameter to [end_block_num] or [end_time]? Who're using [skip_count] with non-zero value? @svk31 @valzav

svk31 commented 9 years ago

I'm using 0 for the skip_count on my backend and it's the same in the web_wallet. I don't really see the usefulness of the skip count so I'm all for removing it.

Like I said above querying for dates would be useful but not essential, if the call is fast enough we can easily just filter based on dates on the frontend.

svk31 commented 9 years ago

While you're looking at this, could you look into why it takes so long for an order to appear in the order history? There's a delay of more than 20 minutes between the execution time of an order and the time when it finally appears in the results of blockchain_market_order_history.

This can be quite confusing when you've made an order in the wallet but the order does not appear in the order history until much later. It also means that information like low, high and latest price can be badly out of sync, as they're taken from the order history.

svk31 commented 9 years ago

On second thought I would prefer to have this command use dates instead of number of transactions for the query. The reason is you can never know how many transactions are in a day, so if you want to get the high and low for the last 24 hours you need to fetch a lot of transactions, hoping that you've got enough. For batch operations on low liquidity markets this means you'll probably be fetching order histories going way further than the 24 hours you're interested in.

abitmore commented 9 years ago

Pull request submitted, please review. The blockchain_market_order_history API has been rewritten. Test needed. @svk31 I prefer leave the behavior of this API as is, and add another time-range query API. Didn't have time to see why there is a delay yet.. Since the API has been rewritten I believe there should be no such issue again. I may have a look later. By the way, the low, high and latest pricing issue should have been fixed in #1300.