Discussion:
qsort can get very slow
Urs Janßen
2012-02-18 01:45:10 UTC
Permalink
On Sat, Feb 18, 2012 at 03:13:22AM +0400, Valeriy E. Ushakov wrote:

fullquote as I Cc tin-dev
tin uses qsort() for sorting. While qsort is generally quick, its
worst case performance is known to be bad.
Opening gmane.comp.lang.lua.general on news.gmane.org takes ages
(>1min spent in sorting article on my oldish 400MHz powerpc) because
mailing list archives were, apparently, fed to the newsgroup out of
order, so mail from 90s is somwhere in the middle, after mail from
early 2000s. This triggers qsort worst-case slowdown.
As a brute force hack I changed my tin to use heapsort, that
guarantees O(n*log(n)). That _dramatically_ improved user experience
for me. gmane.comp.lang.lua.general opens in sane time now and I
don't see noticeable slowdown elsewhere.
qsort() is provided by c99, so I can see while using it is convenient.
heapsort() is available in NetBSD libc, so this s/qsort/heapsort/ hack
was easy for me. I'm not sure what would be an acceptable solution
for general use.
I don't see a big win over here (Linux on a Pentium 4) in what I
assume is normal usage (but I also see that filtering/sorting _is_
faster). quick and dirty test case:

enter a group with 88510 articles, group is read via nntp from remote
server (100mbit uplink), my normal filter file (around 50 complex rules)
is used, quit tin once all the filtering is done (press 'Q' during
filtering),
[01:14:48.858233] LISTGROUP gmane.comp.lang.lua.general
[01:15:27.924200] QUIT
= 39.065967 secs.
[01:16:30.504984] LISTGROUP gmane.comp.lang.lua.general
[01:17:05.069478] QUIT
= 35.564494 secs.

the heapsort version is about 3.5 secs faster most of the time is
spent for fetching data via nntp.

An acceptable solution for general should IMHO look like (after someone
did some more testing with just timing the sorting with more data):

configure check for qsort compatible heapsort in libc like it
is done for qsort with CF_COMPTYPE (aclocal.m4).

if heapsort is found use that, otherwise stick to qsort.

or if we like to benefit from the speed improvement (if there is any
notable) of heapsort over qsort on systems where heapsort is not
present in libc provide a heapsort fallback implementation (i.e. the
one used in *BSDs libc).

urs
--
"Only whimps use tape backup: _real_ men just upload their important stuff
on ftp, and let the rest of the world mirror it ;)" - Linus
Urs Janßen
2012-02-19 12:17:14 UTC
Permalink
$ time tin -g gmane gmane.comp.lang.lua.general
gives
real 1m1.770s
user 0m15.600s
sys 0m2.261s
vs.
real 2m32.274s
user 1m58.352s
sys 0m2.303s
Where the time in the original version with qsort is spent between
Group gmane.comp.lang.lua.general ('q' to quit)... 99% (0:00 remaining)
and
Threading articles ...
The machine is B&W G3 running NetBSD/macppc
cpu0 at mainbus0: 750 (Revision 2.2), ID 0 (primary)
cpu0: HID0 8090c0a4<EMCP,DOZE,DPM,ICE,DCE,SGE,BTIC,BHT>, powersave: 1
cpu0: 400.00 MHz, no-parity 1MB WT L2 cache (PB SRAM) at 2:1 ratio
With the attached patch configure looks for system heapsort() (but is
doesn't check if it is qsort(3)-api compatible) and if not found the
heapsort() from heapsort.c is used (switching back to qsort can be done
via the tin_sort degine in tin.h).

This is not well tested and should either be switched into a runtime
option or at least a configure option (--enable-heapsort or whatever)
and the configure check for a system heapsort should also check if the
one found is sort(3)-api compatible.

urs
--
"Only whimps use tape backup: _real_ men just upload their important stuff
on ftp, and let the rest of the world mirror it ;)" - Linus
Thomas Dickey
2012-02-19 13:46:28 UTC
Permalink
Post by Urs Janßen
With the attached patch configure looks for system heapsort() (but is
I didn't see an attachment.
Post by Urs Janßen
doesn't check if it is qsort(3)-api compatible) and if not found the
heapsort() from heapsort.c is used (switching back to qsort can be done
via the tin_sort degine in tin.h).
This is not well tested and should either be switched into a runtime
option or at least a configure option (--enable-heapsort or whatever)
and the configure check for a system heapsort should also check if the
one found is sort(3)-api compatible.
sounds right...
--
Thomas E. Dickey <***@invisible-island.net>
http://invisible-island.net
ftp://invisible-island.net
Urs Janßen
2012-02-19 14:42:02 UTC
Permalink
why ever the attachment was missing from the last mail, here it is...
Thomas Dickey
2012-02-19 15:00:57 UTC
Permalink
Post by Urs Janßen
why ever the attachment was missing from the last mail, here it is...
thanks. I'll take a look today regarding the option and (I have as
usual some updates to configure macros which might be useful).
--
Thomas E. Dickey <***@invisible-island.net>
http://invisible-island.net
ftp://invisible-island.net
Thomas Dickey
2012-02-20 10:46:46 UTC
Permalink
Post by Thomas Dickey
Post by Urs Janßen
why ever the attachment was missing from the last mail, here it is...
thanks. I'll take a look today regarding the option and (I have as
usual some updates to configure macros which might be useful).
here's the part with the option added (am starting to work on the other
part...)
--
Thomas E. Dickey <***@invisible-island.net>
http://invisible-island.net
ftp://invisible-island.net
Thomas Dickey
2012-02-20 11:54:52 UTC
Permalink
Post by Thomas Dickey
Post by Thomas Dickey
Post by Urs Janßen
why ever the attachment was missing from the last mail, here it is...
thanks. I'll take a look today regarding the option and (I have as
usual some updates to configure macros which might be useful).
here's the part with the option added (am starting to work on the other
part...)
oops - I see that with it disabled, the code still refers to heapsort.

That aspect should be recoded as a function pointer which is configurable
after building (will work on that this evening).
--
Thomas E. Dickey <***@invisible-island.net>
http://invisible-island.net
ftp://invisible-island.net
Loading...