symbian-qemu-0.9.1-12/python-2.6.1/Lib/test/sortperf.py
changeset 1 2fb8b9db1c86
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symbian-qemu-0.9.1-12/python-2.6.1/Lib/test/sortperf.py	Fri Jul 31 15:01:17 2009 +0100
@@ -0,0 +1,169 @@
+"""Sort performance test.
+
+See main() for command line syntax.
+See tabulate() for output format.
+
+"""
+
+import sys
+import time
+import random
+import marshal
+import tempfile
+import os
+
+td = tempfile.gettempdir()
+
+def randfloats(n):
+    """Return a list of n random floats in [0, 1)."""
+    # Generating floats is expensive, so this writes them out to a file in
+    # a temp directory.  If the file already exists, it just reads them
+    # back in and shuffles them a bit.
+    fn = os.path.join(td, "rr%06d" % n)
+    try:
+        fp = open(fn, "rb")
+    except IOError:
+        r = random.random
+        result = [r() for i in xrange(n)]
+        try:
+            try:
+                fp = open(fn, "wb")
+                marshal.dump(result, fp)
+                fp.close()
+                fp = None
+            finally:
+                if fp:
+                    try:
+                        os.unlink(fn)
+                    except os.error:
+                        pass
+        except IOError, msg:
+            print "can't write", fn, ":", msg
+    else:
+        result = marshal.load(fp)
+        fp.close()
+        # Shuffle it a bit...
+        for i in range(10):
+            i = random.randrange(n)
+            temp = result[:i]
+            del result[:i]
+            temp.reverse()
+            result.extend(temp)
+            del temp
+    assert len(result) == n
+    return result
+
+def flush():
+    sys.stdout.flush()
+
+def doit(L):
+    t0 = time.clock()
+    L.sort()
+    t1 = time.clock()
+    print "%6.2f" % (t1-t0),
+    flush()
+
+def tabulate(r):
+    """Tabulate sort speed for lists of various sizes.
+
+    The sizes are 2**i for i in r (the argument, a list).
+
+    The output displays i, 2**i, and the time to sort arrays of 2**i
+    floating point numbers with the following properties:
+
+    *sort: random data
+    \sort: descending data
+    /sort: ascending data
+    3sort: ascending, then 3 random exchanges
+    +sort: ascending, then 10 random at the end
+    %sort: ascending, then randomly replace 1% of the elements w/ random values
+    ~sort: many duplicates
+    =sort: all equal
+    !sort: worst case scenario
+
+    """
+    cases = tuple([ch + "sort" for ch in r"*\/3+%~=!"])
+    fmt = ("%2s %7s" + " %6s"*len(cases))
+    print fmt % (("i", "2**i") + cases)
+    for i in r:
+        n = 1 << i
+        L = randfloats(n)
+        print "%2d %7d" % (i, n),
+        flush()
+        doit(L) # *sort
+        L.reverse()
+        doit(L) # \sort
+        doit(L) # /sort
+
+        # Do 3 random exchanges.
+        for dummy in range(3):
+            i1 = random.randrange(n)
+            i2 = random.randrange(n)
+            L[i1], L[i2] = L[i2], L[i1]
+        doit(L) # 3sort
+
+        # Replace the last 10 with random floats.
+        if n >= 10:
+            L[-10:] = [random.random() for dummy in range(10)]
+        doit(L) # +sort
+
+        # Replace 1% of the elements at random.
+        for dummy in xrange(n // 100):
+            L[random.randrange(n)] = random.random()
+        doit(L) # %sort
+
+        # Arrange for lots of duplicates.
+        if n > 4:
+            del L[4:]
+            L = L * (n // 4)
+            # Force the elements to be distinct objects, else timings can be
+            # artificially low.
+            L = map(lambda x: --x, L)
+        doit(L) # ~sort
+        del L
+
+        # All equal.  Again, force the elements to be distinct objects.
+        L = map(abs, [-0.5] * n)
+        doit(L) # =sort
+        del L
+
+        # This one looks like [3, 2, 1, 0, 0, 1, 2, 3].  It was a bad case
+        # for an older implementation of quicksort, which used the median
+        # of the first, last and middle elements as the pivot.
+        half = n // 2
+        L = range(half - 1, -1, -1)
+        L.extend(range(half))
+        # Force to float, so that the timings are comparable.  This is
+        # significantly faster if we leave tham as ints.
+        L = map(float, L)
+        doit(L) # !sort
+        print
+
+def main():
+    """Main program when invoked as a script.
+
+    One argument: tabulate a single row.
+    Two arguments: tabulate a range (inclusive).
+    Extra arguments are used to seed the random generator.
+
+    """
+    # default range (inclusive)
+    k1 = 15
+    k2 = 20
+    if sys.argv[1:]:
+        # one argument: single point
+        k1 = k2 = int(sys.argv[1])
+        if sys.argv[2:]:
+            # two arguments: specify range
+            k2 = int(sys.argv[2])
+            if sys.argv[3:]:
+                # derive random seed from remaining arguments
+                x = 1
+                for a in sys.argv[3:]:
+                    x = 69069 * x + hash(a)
+                random.seed(x)
+    r = range(k1, k2+1)                 # include the end point
+    tabulate(r)
+
+if __name__ == '__main__':
+    main()