---- On Thu, 14 Oct 2010 10:51:31 -0700 Eliot Miranda  wrote ---- 

>*No*.  Stack and OrderedCollection differ *usefully*.  Adding an item to a 
>Stack is always O(1).  Adding an item to an OrderedCollection is O(N) because 
>when the array overflows a new one must be allocated and the old objects 
>copied to the new.  Why not apply your speedups to OrderedCollection, or is 
>that not possible?  If not possible, then come up with a new name and add 
>that.  Please /don't/ change Stack.

Yes, that point was made in the prior discussion regarding Stack and its 
superclass in defense of having such a class at all when OrderedCollection is 
already there. Further, you are correct that I am suggesting we trade 
guaranteed O(1) complexity when pushing/popping for worst-case O(n) complexity. 
However, asymptotic analysis does not the whole story tell, as it ignores the 
underlying constants, and in the real world, when n is small enough, the 
constants *do* matter. As it turns out, "small enough" in this case means a 
Stack created with the default initial capacity of 10 grown incrementally into 
one big enough to hold 500,000-1,000,000  elements.

I ran the following benchmark with both versions, and the array-based Stack was 
~60% faster when grown big enough to contain 100,000 elements, slightly faster 
for 500,000 elements, and two to three times slower for a million elements:

s := nil.
Smalltalk garbageCollect.
[s := Stack new.
        100000 timesRepeat: [s push: #foo]] timeToRun.

s := nil.
Smalltalk garbageCollect.
[s := Stack new.
        500000 timesRepeat: [s push: #foo]] timeToRun.

s := nil.
Smalltalk garbageCollect.
[s := Stack new.
        1000000 timesRepeat: [s push: #foo]] timeToRun.

That means that even if you unknowingly create an enormous Stack without 
specifying the right size, you still come out ahead for at least the first 
500,000 elements. Of course, the Array-based stack never deallocates any of its 
memory, which means a worst case of 2 * n memory complexity (where n is the 
largest number of elements a given Stack ever held). But as I said in my 
initial post, most Stacks are small, and when they aren't, you often have 
enough information to choose an appropriate size. If you really need constant 
time and memory complexity, which I argue is the exception, why not just use 
LinkedList directly with #addLast: and #removeLast to simulate a Stack as 
people did and still do with OrderedCollection? The rueful requirement that 
LinkList elements inherit from Link is gone.

Stack, if it is to exist at all, should support *fast* push and pop operations. 
The current implementation does not. This one does, and should replace it.


_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

Reply via email to