04 February 2014
strace'ing Abe block explorer
Well there's your problem ---->
I've been working on setting up the Abe cryptocurrency block explorer on a 1GB VPS so I've been trying to squeeze out all the performance I can. I've had trouble since I don't know Python (which is whata Abe is written in), although this has been a good excuse to learn a little.
Basically I've set things up so Nginx is a reverse proxy for 4 Abe processes with monit keeping track and restarting Abe if needed.
The biggest speed problem is the Address lookups, there may be thousands of transactions to or from an address which causes slow DB queries and multi megabyte result pages. There is no pagination mechanism or even storage of the result set on the server side. That's a whole other issue to work on.
Returning the set I thought would be easy with Internet speeds what they are nowadays, it's the lookup in MySQL that I figured would be the problem.
Using mytop and Firebug's network timings display I could see that the query actually takes only a fraction of the response time for a large (~20K Transactions) result set. In fact the longest time was actually receiving the data, it took several minutes for 800K which is just not right.
So, I restarted Abe with strace, and while the server was sending some minor page in Abe, here's what I saw:
The response was being sent (at least inside the OS) as single byte calls to sendto(). So I began a long hunt for why, digging through Python docs and source code for self._write() in the os module.
In the end.... two square brackets fixed the problem:
Apparently with the brackets around a Python variable it is considered a list, instead of a string. When that variable is passed back to WSGIref as a "response iterable" as a string it's being considered a series of characters to iterate over. When it's passed as a list, it's considered a series of lines or something... it works better anyway.
Success! 8192Bytes at a time in sendto(). I found a address with ~35K transactions on it, Firebug shows 29.2 sec waiting, then 11.2 seconds to download 1.448 MBytes. Without the square brackets Abe never finishes.... as long as I ever waited.
On another note, looking at mytop, the query seems to take less time or at least not much more than it takes Abe to process the results of the query so maybe there is something to be gained there.