| 1 | #!/usr/bin/env python2
|
| 2 | """
|
| 3 | container_types.py
|
| 4 | """
|
| 5 | from __future__ import print_function
|
| 6 |
|
| 7 | import os
|
| 8 | from mycpp import mylib
|
| 9 | from mycpp.mylib import log
|
| 10 |
|
| 11 | from typing import List, Tuple
|
| 12 |
|
| 13 |
|
| 14 | def IfDemo(i):
|
| 15 | # type: (int) -> None
|
| 16 |
|
| 17 | if i == 1:
|
| 18 | print('one')
|
| 19 | elif i == 2:
|
| 20 | print('two')
|
| 21 | elif i == 3:
|
| 22 | print('three')
|
| 23 | elif i == 4:
|
| 24 | pass # no-op
|
| 25 | else:
|
| 26 | print('other number')
|
| 27 |
|
| 28 |
|
| 29 | class ParseError(Exception):
|
| 30 |
|
| 31 | def __init__(self, reason):
|
| 32 | # type: (str) -> None
|
| 33 | self.reason = reason
|
| 34 |
|
| 35 |
|
| 36 | def f(s):
|
| 37 | # type: (str) -> str
|
| 38 |
|
| 39 | if s[0] == 'f':
|
| 40 | raise ParseError('started with f')
|
| 41 | return s
|
| 42 |
|
| 43 |
|
| 44 | def ExceptDemo():
|
| 45 | # type: () -> None
|
| 46 |
|
| 47 | result = ''
|
| 48 | tmp = ['foo', 'bar']
|
| 49 | for prog in tmp:
|
| 50 | try:
|
| 51 | result = f(prog)
|
| 52 | except ParseError as e:
|
| 53 | log('error: %s', e.reason)
|
| 54 | continue
|
| 55 | log('result = %s', result)
|
| 56 |
|
| 57 |
|
| 58 | def run_tests():
|
| 59 | # type: () -> None
|
| 60 |
|
| 61 | tmp = [1, 2, 3, 4, 5]
|
| 62 | for i in tmp:
|
| 63 | IfDemo(i)
|
| 64 |
|
| 65 | log('')
|
| 66 | ExceptDemo()
|
| 67 |
|
| 68 |
|
| 69 | def run_benchmarks():
|
| 70 | # type: () -> None
|
| 71 |
|
| 72 | # BUG: we only get 8191 exceptions instead of 100,000? I think this must be
|
| 73 | # because of 'throw Alloc<ParseError>? TODO: Should exceptions throw by
|
| 74 | # value?
|
| 75 | n = 100000
|
| 76 |
|
| 77 | # C++ exceptions are slower than Python! Woah.
|
| 78 |
|
| 79 | result = ''
|
| 80 | num_exceptions = 0
|
| 81 | i = 0
|
| 82 |
|
| 83 | # Even one failure makes C++ slower! Otherwise it's faster.
|
| 84 | cases = ['fail', 'ok', 'ok', 'ok']
|
| 85 |
|
| 86 | # 870 ms in C++, 366 ms in Python
|
| 87 | #cases = ['fail', 'fail', 'fail', 'fail']
|
| 88 |
|
| 89 | # 26 ms in C++, 70 ms in Python
|
| 90 | # OK it is inverted! Exceptions are really expensive.
|
| 91 | #cases = ['ok', 'ok', 'ok', 'ok']
|
| 92 |
|
| 93 | while i < n:
|
| 94 | for prog in cases:
|
| 95 | try:
|
| 96 | result = f(prog)
|
| 97 | except ParseError as e:
|
| 98 | num_exceptions += 1
|
| 99 | continue
|
| 100 | i += 1
|
| 101 |
|
| 102 | mylib.MaybeCollect() # manual GC point
|
| 103 |
|
| 104 | log('num_exceptions = %d', num_exceptions)
|
| 105 | log('Ran %d iterations of try/except', n)
|
| 106 |
|
| 107 |
|
| 108 | if __name__ == '__main__':
|
| 109 | if os.getenv('BENCHMARK'):
|
| 110 | log('Benchmarking...')
|
| 111 | run_benchmarks()
|
| 112 | else:
|
| 113 | run_tests()
|