Tcl Source Code

View Ticket
Login
Ticket UUID: 1366484
Title: patch: speed up lsort (follow on to 1360413)
Type: Patch Version: None
Submitter: afredd Created on: 2005-11-25 18:12:16
Subsystem: 17. Commands I-L Assigned To: dkf
Priority: 5 Medium Severity:
Status: Closed Last Modified: 2008-03-14 09:20:40
Resolution: Out of Date Closed By: sf-robot
    Closed on: 2008-03-14 02:20:40
Description:
Sorry about the repeated submission. (Doesn't seem 
like 'nobody' can upload a second file.)

Here's the percentage speed increase of the current 
patch done on a 8.5a3 on a 100 item list (on one 
particular run):

-ascii => 37 %
-ascii -unique => 36 %
-integer => 48 %
-integer -unique => 44 %
-real => 15 %
-real -unique  => 17 %
-index 1  => 50 %
-index 1 -unique => 48 %
-command compare_cmd => 0 %
-command compare_cmd -unique => 0 %

The saving is better with larger lists. Don't expect 
any saving when using -command, as the called tcl 
command takes the bulk of processing time. See the 
code for why -real and -unique are not quite as quick 
(but still quicker). The "-index $n -integer" is the 
best improver running in less than a third of the 
previous time for lists of more than a 100.

The patch is against the current HEAD (184). (I've not 
tested it - just ported across my 8.5a3 tested version 
into the HEAD copy. fingers crossed)
User Comments: sf-robot added on 2008-03-14 09:20:40:
Logged In: YES 
user_id=1312539
Originator: NO

This Tracker item was closed automatically by the system. It was
previously set to a Pending status, and the original submitter
did not respond within 14 days (the time period specified by
the administrator of this Tracker).

jenglish added on 2008-02-29 04:22:19:
Logged In: YES 
user_id=68433
Originator: NO

Recent [lsort] enhancements (2007-12-21 through 2007-12-26) incorporated (a different implementation of) the most important aspects of this patch (notably, the Schwarzian transform), while preserving the original algorithm.

afredd added on 2007-04-26 23:09:48:

File Deleted - 199797:

afredd added on 2007-04-26 23:07:36:

File Added - 226743: tclCmdIL.c#1.114-patch

Logged In: YES 
user_id=1386588
Originator: YES

Patch for 1.114 of tclCmdIL.c (current HEAD).
(NB. test cmdIL-3.4 will fail, but see previous comment)


File Added: tclCmdIL.c#1.114-patch

afredd added on 2006-10-24 23:20:23:

File Deleted - 171463: 



File Added - 199798: cmdIL.test-patch

afredd added on 2006-10-24 23:19:17:

File Added - 199797: tclCmdIL.c#1.90-patch

Logged In: YES 
user_id=1386588


Here's an updated patch that runs clean against against the current HEAD version.

Also a patch for cmdIL.test that:
a) splits the one test the patch fails: cmdIL-3.4
 (which is an error test that contains 2 errors,
 and the different implementations pick different ones to return)
 into 2 separate tests
b) some additional lsort tests for:
 * the documented special case of a single element list
   (which was really just documenting the old implementation rather
    than intended functionality)
 * a testcase that calls lsort from another lsort's -command procedure.
c) a test for -nocase using non-ASCII strings. This will fail, but see SW#1236896.

afredd added on 2006-03-19 20:57:12:

File Deleted - 158409: 



File Added - 171463: tclCmdIL.c#1.86-patch4

Logged In: YES 
user_id=1386588

Found a couple more minor enhancements that shave off
a few cycles here and there. Also cleaned up my code.
Changes:
1. Added SortElementCache struct.
2. Defined SORTELEMENTCACHE_HAS_REAL behaviour.
3. Only SelectObjFromSublist if (sortInfo.indexc != 0)
 ie. save N function calls in common case
4. Store a -comand's objc in sortInfo saves NlogN calls
 to Tcl_ListObjLength.
5. nonUniqueCount ensures final result list is always
 preallocated to the correct length. Although timing does
 not reveal any speed gain either way, it does at least
 ensure a long living result of lsort does not take up
 unused space.

afredd added on 2006-01-12 02:10:12:

File Added - 162984: perlsort.zip

afredd added on 2006-01-12 02:10:05:
Logged In: YES 
user_id=1386588

OK as promised :-)
Here's a zip file with a 8.5a3 tclCmdIL.c with Perl's
merge sort in. I've included some timing results
and a test script. NB. the sort is documented as being
stable.

*WARNING* this is not a patch (yeah - i know this probably
isn't the best place for it :-) but might be of interest
to someone.

So is it faster? .... Well, if the list has any
existing order, then yes. For rand()om data using a quick
comparator (ie. not -command!) then no.
It can be massively faster; it is usually not too far off.

Overall. I'm inclined not to go any further with this.
The perl sort uses slightly more memory, and is slower
for [lsort -integer $a_random_list_of_ints].
Not much point swapping the sort alg. if it is slower
in a potentially likely situation.

NB. while i'm here (and apologies for being OT)...
lsort could use a -numeric option
(or -bignum, or ...) that is equivalent to:

proc num_cmp {a b} {
 if {$a > $b} { return 1 }
 if {$a < $b} { return -1 }
 return 0
}
lsort -command num_cmp $num_list

as currently there is no builtin way to sort
either wides or the new big nums if they are
too big. Consider:

set l [list \
 [expr wide(100000000000000002)] \
 [expr wide(100000000000000001)] \
 [expr wide(100000000000000003)] \
]

puts [lsort -real $l] # wrong result
puts [lsort -integer $l] # integer too big

I feel a TIP coming on :-)

dgp added on 2005-12-10 23:30:14:
Logged In: YES 
user_id=80530


As you're exploring other
algorithms for [lsort],
take note that [lsort]
is documented to provide
a stable sort, and any 
changes need to preserve
that property.

afredd added on 2005-12-10 00:32:44:
Logged In: YES 
user_id=1386588

dkf> Can I delete the older patch from this ticket?

Sure. Thanks!

#1 Small point... the comment in there about running with 
SORTELEMENT_HAS_OBJPTR==0 on my old 350Mhz laptop should 
say "faster with lists of more than 1000 elements" (the tip 
over seems to be ~700). However, on my quick machine 
SORTELEMENT_HAS_OBJPTR==1 is very definately the better 
option.


#2 btw - i've been comparing the MergeSort alg. against the 
equivalent in Perl and Python. Tcl's does a significant 
number more *comparisons* - especially so for almost sorted 
data (a common case). In fact there's is O(N) for sorted 
data. I'm having a go at hacking Perl's sort alg. into 
tclCmdIL.c to get some benchmark figures. I undertand the 
resultant patch may not be acceptable, but it might be a 
trigger for further work. I'll post more later.
Cheers.

dkf added on 2005-12-09 23:34:32:
Logged In: YES 
user_id=79902

Can I delete the older patch from this ticket?

afredd added on 2005-12-03 00:27:08:

File Added - 158409: tclCmdIL.c-patch3

afredd added on 2005-12-03 00:27:07:
Logged In: YES 
user_id=1386588

Minor update on previous patch.
Main change is to preallocate the result object as a big 
enough list in the case of a non -unique lsort.

dkf added on 2005-11-28 16:12:23:
Logged In: YES 
user_id=79902

Only the registered submitter (or a tracker tech, i.e. a
maintainer) can manage attachments to a tracker entry.
That's just the way SF works (and I suppose I can see why,
even if it is inconvenient sometimes.)

afredd added on 2005-11-26 01:12:19:

File Added - 157534: patch2-tclCmdIL.c

Attachments: