run-bench.test 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. -- TODO: build some generic benchmark harness
  2. [case testBenchmarkTree]
  3. from typing import Optional
  4. class Node:
  5. def __init__(self, value: int) -> None:
  6. self.value = value
  7. self.left = None # type: Optional[Node]
  8. self.right = None # type: Optional[Node]
  9. def sum(self) -> int:
  10. left = 0
  11. if self.left is not None:
  12. left = self.left.sum()
  13. right = 0
  14. if self.right is not None:
  15. right = self.right.sum()
  16. return self.value + left + right
  17. def sum_tree(x: Optional[Node]) -> int:
  18. if x is None:
  19. return 0
  20. return x.value + sum_tree(x.left) + sum_tree(x.right)
  21. def build(n: int) -> Optional[Node]:
  22. if n == 0:
  23. return None
  24. x = Node(n)
  25. x.left = build(n - 1)
  26. x.right = x.left
  27. return x
  28. def bench_sum(x: Optional[Node]) -> None:
  29. for i in range(1000000):
  30. sum_tree(x)
  31. def bench_sum_method(x: Node) -> None:
  32. for i in range(1000000):
  33. x.sum()
  34. [file driver.py]
  35. from typing import Optional
  36. import native
  37. import interpreted
  38. from timeit import timeit
  39. from time import time
  40. import os
  41. def dumb_time(f):
  42. t0 = time()
  43. f()
  44. t1 = time()
  45. return t1 - t0
  46. def basic_test(m):
  47. tree = m.build(5)
  48. assert(m.sum_tree(tree) == 57)
  49. assert(tree.sum() == 57)
  50. return tree
  51. def test(m):
  52. tree = basic_test(m)
  53. g = {**globals(), **locals()}
  54. sum = timeit('m.sum_tree(tree)', globals=g)
  55. sum2 = timeit('tree.sum()', globals=g)
  56. fsum = dumb_time(lambda: m.bench_sum(tree))
  57. fsum2 = dumb_time(lambda: m.bench_sum_method(tree))
  58. build = timeit('m.build(5)', globals=g)
  59. return (sum, sum2, fsum, fsum2, build)
  60. # Basic functionality test
  61. basic_test(native)
  62. # Benchmark if we are benchmarking
  63. if os.environ.get('MYPYC_RUN_BENCH') == '1':
  64. nsum, nsum2, nfsum, nfsum2, nbuild = test(native)
  65. isum, isum2, ifsum, ifsum2, ibuild = test(interpreted)
  66. print(nsum, nsum2, nfsum, nbuild)
  67. print("Sum speedup:", isum/nsum)
  68. print("Sum method speedup:", isum2/nsum2)
  69. print("Sum (fast) speedup:", ifsum/nfsum)
  70. print("Sum (fast) method speedup:", ifsum2/nfsum2)
  71. print("Build speedup:", ibuild/nbuild)
  72. [case testBenchmarkVisitorTree]
  73. from mypy_extensions import trait
  74. from typing import cast, Generic, TypeVar, Any
  75. T = TypeVar('T')
  76. class Tree:
  77. def accept(self, v: 'TreeVisitor[T]') -> T:
  78. pass
  79. class Leaf(Tree):
  80. def accept(self, v: 'TreeVisitor[T]') -> T:
  81. return v.visit_leaf(self)
  82. class Node(Tree):
  83. def __init__(self, value: int, left: Tree, right: Tree) -> None:
  84. self.value = value
  85. self.left = left
  86. self.right = right
  87. def accept(self, v: 'TreeVisitor[T]') -> T:
  88. return v.visit_node(self)
  89. @trait
  90. class TreeVisitor(Generic[T]):
  91. def visit_leaf(self, x: Leaf) -> T: return cast(T, None)
  92. def visit_node(self, x: Node) -> T: return cast(T, None)
  93. class SumVisitor(TreeVisitor[int]):
  94. def sum(self, x: Tree) -> int:
  95. return x.accept(self)
  96. def visit_leaf(self, x: Leaf) -> int:
  97. return 0
  98. def visit_node(self, x: Node) -> int:
  99. return x.value + self.sum(x.left) + self.sum(x.right)
  100. def equal(x: Tree, y: Tree) -> bool:
  101. return EqualVisitor(x).equal(y)
  102. class EqualVisitor(TreeVisitor[bool]):
  103. def __init__(self, left: Tree) -> None:
  104. self.left = left
  105. def equal(self, right: Tree) -> bool:
  106. return right.accept(self)
  107. def visit_leaf(self, right: Leaf) -> bool:
  108. return isinstance(self.left, Leaf)
  109. def visit_node(self, right: Node) -> bool:
  110. if isinstance(self.left, Node):
  111. # our boolean stuff is crap
  112. if (self.left.value == right.value and equal(self.left.left, right.left)
  113. and equal(self.left.right, right.right)):
  114. return True
  115. return False
  116. def sum_tree(x: Tree) -> int:
  117. return SumVisitor().sum(x)
  118. def build(n: int) -> Tree:
  119. if n == 0:
  120. return Leaf()
  121. return Node(n, build(n - 1), build(n - 1))
  122. def bench_sum_tree(x: Tree) -> None:
  123. for i in range(100000):
  124. sum_tree(x)
  125. def bench_equal_tree(x: Tree, y: Tree) -> None:
  126. for i in range(100000):
  127. equal(x, y)
  128. [file driver.py]
  129. from typing import Optional
  130. import interpreted
  131. import native
  132. from timeit import timeit
  133. from time import time
  134. import os
  135. import sys
  136. # Side test: some stuff about MROs and generics
  137. if sys.version_info[:3] > (3, 5, 2):
  138. assert tuple(x.__name__ for x in interpreted.SumVisitor.mro()) == ('SumVisitor', 'TreeVisitor', 'Generic', 'object')
  139. assert tuple(x.__name__ for x in native.SumVisitor.mro()) == ('SumVisitor', 'TreeVisitor', 'Generic', 'object')
  140. assert str(native.TreeVisitor[native.T]) == "native.TreeVisitor[~T]"
  141. assert native.TreeVisitor.__name__ == "TreeVisitor"
  142. assert native.SumVisitor.__name__ == "SumVisitor"
  143. def dumb_time(f):
  144. t0 = time()
  145. f()
  146. t1 = time()
  147. return t1 - t0
  148. def basic_test(m):
  149. tree = m.build(5)
  150. tree2 = m.build(5)
  151. tree2.right.right.right.value = 10
  152. assert m.sum_tree(tree) == 57
  153. assert m.equal(tree, tree)
  154. assert not m.equal(tree, tree2)
  155. assert isinstance(native.SumVisitor(), native.TreeVisitor)
  156. return tree
  157. def test(m):
  158. tree = basic_test(m)
  159. g = {**globals(), **locals()}
  160. fsum = dumb_time(lambda: m.bench_sum_tree(tree))
  161. feq = dumb_time(lambda: m.bench_equal_tree(tree, tree))
  162. return fsum, feq
  163. basic_test(native)
  164. if os.environ.get('MYPYC_RUN_BENCH') == '1':
  165. nfsum, nfeq = test(native)
  166. ifsum, ifeq = test(interpreted)
  167. print(nfsum)
  168. print("Sum speedup:", ifsum/nfsum)
  169. print("Equal speedup:", ifeq/nfeq)