Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | # |
| 4 | # Licensed to the Apache Software Foundation (ASF) under one |
| 5 | # or more contributor license agreements. See the NOTICE file |
| 6 | # distributed with this work for additional information |
| 7 | # regarding copyright ownership. The ASF licenses this file |
| 8 | # to you under the Apache License, Version 2.0 (the |
| 9 | # "License"); you may not use this file except in compliance |
| 10 | # with the License. You may obtain a copy of the License at |
| 11 | # |
| 12 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 13 | # |
| 14 | # Unless required by applicable law or agreed to in writing, |
| 15 | # software distributed under the License is distributed on an |
| 16 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 17 | # KIND, either express or implied. See the License for the |
| 18 | # specific language governing permissions and limitations |
| 19 | # under the License. |
| 20 | # |
| 21 | |
| 22 | r""" |
| 23 | PYTHONPATH=./gen-py:../../lib/py/build/lib... ./FastbinaryTest.py |
| 24 | """ |
| 25 | |
| 26 | # TODO(dreiss): Test error cases. Check for memory leaks. |
| 27 | |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 28 | from __future__ import print_function |
| 29 | |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 30 | import math |
Nobuaki Sukegawa | a3b88a0 | 2016-01-06 20:44:17 +0900 | [diff] [blame] | 31 | import os |
| 32 | import sys |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 33 | import timeit |
| 34 | |
| 35 | from copy import deepcopy |
| 36 | from pprint import pprint |
| 37 | |
| 38 | from thrift.transport import TTransport |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 39 | from thrift.protocol.TBinaryProtocol import TBinaryProtocol, TBinaryProtocolAccelerated |
| 40 | from thrift.protocol.TCompactProtocol import TCompactProtocol, TCompactProtocolAccelerated |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 41 | |
| 42 | from DebugProtoTest import Srv |
| 43 | from DebugProtoTest.ttypes import Backwards, Bonk, Empty, HolyMoley, OneOfEach, RandomStuff, Wrapper |
| 44 | |
| 45 | |
| 46 | class TDevNullTransport(TTransport.TTransportBase): |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 47 | def __init__(self): |
| 48 | pass |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 49 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 50 | def isOpen(self): |
| 51 | return True |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 52 | |
James E. King, III | 0ad20bd | 2017-09-30 15:44:16 -0700 | [diff] [blame] | 53 | |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 54 | ooe1 = OneOfEach() |
| 55 | ooe1.im_true = True |
| 56 | ooe1.im_false = False |
| 57 | ooe1.a_bite = 0xd6 |
| 58 | ooe1.integer16 = 27000 |
| 59 | ooe1.integer32 = 1 << 24 |
| 60 | ooe1.integer64 = 6000 * 1000 * 1000 |
| 61 | ooe1.double_precision = math.pi |
| 62 | ooe1.some_characters = "Debug THIS!" |
Nobuaki Sukegawa | a3b88a0 | 2016-01-06 20:44:17 +0900 | [diff] [blame] | 63 | ooe1.zomg_unicode = u"\xd7\n\a\t" |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 64 | |
| 65 | ooe2 = OneOfEach() |
| 66 | ooe2.integer16 = 16 |
| 67 | ooe2.integer32 = 32 |
| 68 | ooe2.integer64 = 64 |
| 69 | ooe2.double_precision = (math.sqrt(5) + 1) / 2 |
| 70 | ooe2.some_characters = ":R (me going \"rrrr\")" |
Nobuaki Sukegawa | a3b88a0 | 2016-01-06 20:44:17 +0900 | [diff] [blame] | 71 | ooe2.zomg_unicode = u"\xd3\x80\xe2\x85\xae\xce\x9d\x20"\ |
| 72 | u"\xd0\x9d\xce\xbf\xe2\x85\xbf\xd0\xbe"\ |
| 73 | u"\xc9\xa1\xd0\xb3\xd0\xb0\xcf\x81\xe2\x84\x8e"\ |
| 74 | u"\x20\xce\x91\x74\x74\xce\xb1\xe2\x85\xbd\xce\xba"\ |
| 75 | u"\xc7\x83\xe2\x80\xbc" |
| 76 | |
| 77 | if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 78 | ooe1.zomg_unicode = ooe1.zomg_unicode.encode('utf8') |
| 79 | ooe2.zomg_unicode = ooe2.zomg_unicode.encode('utf8') |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 80 | |
| 81 | hm = HolyMoley(**{"big": [], "contain": set(), "bonks": {}}) |
| 82 | hm.big.append(ooe1) |
| 83 | hm.big.append(ooe2) |
| 84 | hm.big[0].a_bite = 0x22 |
| 85 | hm.big[1].a_bite = 0x22 |
| 86 | |
| 87 | hm.contain.add(("and a one", "and a two")) |
| 88 | hm.contain.add(("then a one, two", "three!", "FOUR!")) |
Elvis Pranskevichus | 2d1fe88 | 2017-05-23 11:36:23 -0400 | [diff] [blame] | 89 | if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): |
| 90 | hm.contain.add((u"\xd7\n\a\t".encode('utf8'),)) |
| 91 | else: |
| 92 | hm.contain.add((u"\xd7\n\a\t",)) |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 93 | hm.contain.add(()) |
| 94 | |
| 95 | hm.bonks["nothing"] = [] |
| 96 | hm.bonks["something"] = [ |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 97 | Bonk(**{"type": 1, "message": "Wait."}), |
| 98 | Bonk(**{"type": 2, "message": "What?"}), |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 99 | ] |
| 100 | hm.bonks["poe"] = [ |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 101 | Bonk(**{"type": 3, "message": "quoth"}), |
| 102 | Bonk(**{"type": 4, "message": "the raven"}), |
| 103 | Bonk(**{"type": 5, "message": "nevermore"}), |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 104 | ] |
| 105 | |
| 106 | rs = RandomStuff() |
| 107 | rs.a = 1 |
| 108 | rs.b = 2 |
| 109 | rs.c = 3 |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 110 | rs.myintlist = list(range(20)) |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 111 | rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})} |
| 112 | rs.bigint = 124523452435 |
| 113 | rs.triple = 3.14 |
| 114 | |
| 115 | # make sure this splits two buffers in a buffered protocol |
| 116 | rshuge = RandomStuff() |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 117 | rshuge.myintlist = list(range(10000)) |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 118 | |
| 119 | my_zero = Srv.Janky_result(**{"success": 5}) |
| 120 | |
| 121 | |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 122 | class Test(object): |
| 123 | def __init__(self, fast, slow): |
| 124 | self._fast = fast |
| 125 | self._slow = slow |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 126 | |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 127 | def _check_write(self, o): |
| 128 | trans_fast = TTransport.TMemoryBuffer() |
| 129 | trans_slow = TTransport.TMemoryBuffer() |
Nobuaki Sukegawa | 7af189a | 2016-02-11 16:21:01 +0900 | [diff] [blame] | 130 | prot_fast = self._fast(trans_fast, fallback=False) |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 131 | prot_slow = self._slow(trans_slow) |
| 132 | |
| 133 | o.write(prot_fast) |
| 134 | o.write(prot_slow) |
| 135 | ORIG = trans_slow.getvalue() |
| 136 | MINE = trans_fast.getvalue() |
| 137 | if ORIG != MINE: |
| 138 | print("actual : %s\nexpected: %s" % (repr(MINE), repr(ORIG))) |
| 139 | raise Exception('write value mismatch') |
| 140 | |
| 141 | def _check_read(self, o): |
| 142 | prot = self._slow(TTransport.TMemoryBuffer()) |
| 143 | o.write(prot) |
| 144 | |
| 145 | slow_version_binary = prot.trans.getvalue() |
| 146 | |
| 147 | prot = self._fast( |
Nobuaki Sukegawa | 7af189a | 2016-02-11 16:21:01 +0900 | [diff] [blame] | 148 | TTransport.TMemoryBuffer(slow_version_binary), fallback=False) |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 149 | c = o.__class__() |
| 150 | c.read(prot) |
| 151 | if c != o: |
| 152 | print("actual : ") |
| 153 | pprint(repr(c)) |
| 154 | print("expected: ") |
| 155 | pprint(repr(o)) |
| 156 | raise Exception('read value mismatch') |
| 157 | |
| 158 | prot = self._fast( |
| 159 | TTransport.TBufferedTransport( |
Nobuaki Sukegawa | 7af189a | 2016-02-11 16:21:01 +0900 | [diff] [blame] | 160 | TTransport.TMemoryBuffer(slow_version_binary)), fallback=False) |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 161 | c = o.__class__() |
| 162 | c.read(prot) |
| 163 | if c != o: |
| 164 | print("actual : ") |
| 165 | pprint(repr(c)) |
| 166 | print("expected: ") |
| 167 | pprint(repr(o)) |
| 168 | raise Exception('read value mismatch') |
| 169 | |
| 170 | def do_test(self): |
| 171 | self._check_write(HolyMoley()) |
| 172 | self._check_read(HolyMoley()) |
| 173 | |
| 174 | self._check_write(hm) |
| 175 | no_set = deepcopy(hm) |
| 176 | no_set.contain = set() |
| 177 | self._check_read(no_set) |
| 178 | self._check_read(hm) |
| 179 | |
| 180 | self._check_write(rs) |
| 181 | self._check_read(rs) |
| 182 | |
| 183 | self._check_write(rshuge) |
| 184 | self._check_read(rshuge) |
| 185 | |
| 186 | self._check_write(my_zero) |
| 187 | self._check_read(my_zero) |
| 188 | |
| 189 | self._check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2})) |
| 190 | |
| 191 | # One case where the serialized form changes, but only superficially. |
| 192 | o = Backwards(**{"first_tag2": 4, "second_tag1": 2}) |
| 193 | trans_fast = TTransport.TMemoryBuffer() |
| 194 | trans_slow = TTransport.TMemoryBuffer() |
Nobuaki Sukegawa | 7af189a | 2016-02-11 16:21:01 +0900 | [diff] [blame] | 195 | prot_fast = self._fast(trans_fast, fallback=False) |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 196 | prot_slow = self._slow(trans_slow) |
| 197 | |
| 198 | o.write(prot_fast) |
| 199 | o.write(prot_slow) |
| 200 | ORIG = trans_slow.getvalue() |
| 201 | MINE = trans_fast.getvalue() |
| 202 | assert id(ORIG) != id(MINE) |
| 203 | |
Nobuaki Sukegawa | 7af189a | 2016-02-11 16:21:01 +0900 | [diff] [blame] | 204 | prot = self._fast(TTransport.TMemoryBuffer(), fallback=False) |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 205 | o.write(prot) |
| 206 | prot = self._slow( |
| 207 | TTransport.TMemoryBuffer(prot.trans.getvalue())) |
| 208 | c = o.__class__() |
| 209 | c.read(prot) |
| 210 | if c != o: |
| 211 | print("copy: ") |
| 212 | pprint(repr(c)) |
| 213 | print("orig: ") |
| 214 | pprint(repr(o)) |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 215 | |
| 216 | |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 217 | def do_test(fast, slow): |
| 218 | Test(fast, slow).do_test() |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 219 | |
| 220 | |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 221 | def do_benchmark(protocol, iters=5000, skip_slow=False): |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 222 | setup = """ |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 223 | from __main__ import hm, rs, TDevNullTransport |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 224 | from thrift.protocol.{0} import {0}{1} |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 225 | trans = TDevNullTransport() |
Nobuaki Sukegawa | 7af189a | 2016-02-11 16:21:01 +0900 | [diff] [blame] | 226 | prot = {0}{1}(trans{2}) |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 227 | """ |
| 228 | |
Nobuaki Sukegawa | 7af189a | 2016-02-11 16:21:01 +0900 | [diff] [blame] | 229 | setup_fast = setup.format(protocol, 'Accelerated', ', fallback=False') |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 230 | if not skip_slow: |
Nobuaki Sukegawa | 7af189a | 2016-02-11 16:21:01 +0900 | [diff] [blame] | 231 | setup_slow = setup.format(protocol, '', '') |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 232 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 233 | print("Starting Benchmarks") |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 234 | |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 235 | if not skip_slow: |
| 236 | print("HolyMoley Standard = %f" % |
| 237 | timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters)) |
| 238 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 239 | print("HolyMoley Acceler. = %f" % |
| 240 | timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters)) |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 241 | |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 242 | if not skip_slow: |
| 243 | print("FastStruct Standard = %f" % |
| 244 | timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters)) |
| 245 | |
Nobuaki Sukegawa | 10308cb | 2016-02-03 01:57:03 +0900 | [diff] [blame] | 246 | print("FastStruct Acceler. = %f" % |
| 247 | timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters)) |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 248 | |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 249 | |
Nobuaki Sukegawa | 7b89469 | 2015-12-23 21:45:06 +0900 | [diff] [blame] | 250 | if __name__ == '__main__': |
Nobuaki Sukegawa | 6525f6a | 2016-02-11 13:58:39 +0900 | [diff] [blame] | 251 | print('Testing TBinaryAccelerated') |
| 252 | do_test(TBinaryProtocolAccelerated, TBinaryProtocol) |
| 253 | do_benchmark('TBinaryProtocol') |
| 254 | print('Testing TCompactAccelerated') |
| 255 | do_test(TCompactProtocolAccelerated, TCompactProtocol) |
| 256 | do_benchmark('TCompactProtocol') |