|
|
List Size
|
Python
|
Haskell
|
Picat
|
|
|
1,000
|
1.171
|
Too Fast
|
Too Fast
|
|
10,000
|
36.251
|
Too Fast
|
0.797
| |
|
100,000
|
Too Slow
|
0.156
|
80.909
| |
|
1,000,000
|
Too Slow
|
1.328
|
Too Slow
| |
|
10,000,000
|
Stack Overflow
|
14.375
|
Too Slow
|
|
List Size
|
Python
|
Haskell
|
Picat
| |
|
100,000
|
0.122
|
Too Fast
|
Too Fast
| |
|
1,000,000
|
1.46
|
0.547
|
0.031
| |
|
10,000,000
|
Stack Overflow
|
6.219
|
0.328
|
# Python Implementation of Reverse import threading, sys, time # naive reverse for nested-tuples def naive_reverse_nt(nt): if nt == (): return () else: (head_single, tail_group) = nt return concat_nt(naive_reverse_nt(tail_group), (head_single, ())) #edef # caller of the tail recursive reverse def tailend_reverse_nt(nt): return tailend_reverse_nt_aux(nt, ()) #edef # tail recursive reverse for nested tuples def tailend_reverse_nt_aux(nt, acc): if nt == (): return acc else: (head_single, tail_group) = nt return tailend_reverse_nt_aux(tail_group, (head_single, acc)) #edef # creates a nested-tuple of a given size def create_nt(size): result = () for index in range(size, 0, -1): result = (index, result) return result #edef # concatenates two nested tuples def concat_nt(nt1, nt2): if nt1 == (): return nt2 else: (head_single, tail_group) = nt1 return (head_single, concat_nt(tail_group, nt2)) #edef def dummy(nt): if nt == (): return () else: (head_single, tail_group) = nt return dummy(tail_group) #edef class Timer(object): def __init__(self, verbose=False): self.verbose = verbose def __enter__(self): self.start = time.time() return self def __exit__(self, *args): self.end = time.time() self.secs = self.end - self.start self.msecs = self.secs * 1000 # millisecs if self.verbose: print ('elapsed time: %f ms' % self.msecs) #eclass class Benchmark: def __call__(self): self.bench("dummy", dummy, create_nt(1000000)) self.bench("naive reverse 1k", naive_reverse_nt, create_nt(1000)) self.bench("naive reverse 10k", naive_reverse_nt, create_nt(10000)) self.bench("tailend reverse 100k", tailend_reverse_nt, create_nt(100000)) self.bench("tailend reverse 1M", tailend_reverse_nt, create_nt(1000000)) #edef def bench(self, msg, call, arg): with Timer() as t: call(arg) print("%s : %s s" % (msg, t.secs)) #edef #eclass sys.setrecursionlimit(1500000) threading.stack_size(0xFFFFFFF) t = threading.Thread(target=Benchmark()) t.start() t.join() |
-- Haskell Implementation of Reverse import Text.Printf import Control.Exception import System.CPUTime naive_reverse [] = [] naive_reverse (h:t) = (naive_reverse t) ++ [h] tailend_reverse lst = tailend_reverse_aux [] lst tailend_reverse_aux acc [] = acc tailend_reverse_aux acc (h:t) = tailend_reverse_aux (h:acc) t time :: IO t -> IO t time fun = do start <- getCPUTime v <- fun end <- getCPUTime let diff = (fromIntegral (end - start)) / (10^12) printf "%0.6f secs\n" (diff::Double) return v bench fun funName siz = do printf "%s with %d: " (funName::[Char]) (siz::Int) let list = [1..siz] time $ fun list `seq` return () dummy [] = [] dummy (h:t) = dummy t main = do bench dummy "dummy" 10000000 bench naive_reverse "naive reverse 100k" 100000 bench naive_reverse "naive reverse 1M" 1000000 bench naive_reverse "naive reverse 10M" 10000000 bench tailend_reverse "tailend reverse 1M" 1000000 bench tailend_reverse "tailend reverse 10M" 10000000 |
% Picat Implementation of Reverse naive_reverse([]) = []. naive_reverse([H|T]) = naive_reverse(T) ++ [H]. tailend_reverse(List) = tailend_reverse_aux(List, []). tailend_reverse_aux([], Acc) = Acc. tailend_reverse_aux([H|T], Acc) = tailend_reverse_aux(T, [H|Acc]). dummy([]) = []. dummy([H|T]) = dummy(T). % to benchmark type the following into the interpreter: % _List=1..10000000, dummy(_List)=_RList % _List=1..10000, time(naive_reverse(_List)=_RList) % _List=1..100000, time(naive_reverse(_List)=_RList) % _List=1..1000000, time(tailend_reverse(_List)=_RList) % _List=1..10000000, time(tailend_reverse(_List)=_RList) |