blob: d231abf3d5794e00f2b71bc7ba71985c80296651 [file] [log] [blame]
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +09001#!/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
22r"""
23PYTHONPATH=./gen-py:../../lib/py/build/lib... ./FastbinaryTest.py
24"""
25
26# TODO(dreiss): Test error cases. Check for memory leaks.
27
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090028from __future__ import print_function
29
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090030import math
Nobuaki Sukegawaa3b88a02016-01-06 20:44:17 +090031import os
32import sys
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090033import timeit
34
35from copy import deepcopy
36from pprint import pprint
37
38from thrift.transport import TTransport
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +090039from thrift.protocol.TBinaryProtocol import TBinaryProtocol, TBinaryProtocolAccelerated
40from thrift.protocol.TCompactProtocol import TCompactProtocol, TCompactProtocolAccelerated
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090041
42from DebugProtoTest import Srv
43from DebugProtoTest.ttypes import Backwards, Bonk, Empty, HolyMoley, OneOfEach, RandomStuff, Wrapper
44
45
46class TDevNullTransport(TTransport.TTransportBase):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090047 def __init__(self):
48 pass
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090049
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090050 def isOpen(self):
51 return True
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090052
53ooe1 = OneOfEach()
54ooe1.im_true = True
55ooe1.im_false = False
56ooe1.a_bite = 0xd6
57ooe1.integer16 = 27000
58ooe1.integer32 = 1 << 24
59ooe1.integer64 = 6000 * 1000 * 1000
60ooe1.double_precision = math.pi
61ooe1.some_characters = "Debug THIS!"
Nobuaki Sukegawaa3b88a02016-01-06 20:44:17 +090062ooe1.zomg_unicode = u"\xd7\n\a\t"
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090063
64ooe2 = OneOfEach()
65ooe2.integer16 = 16
66ooe2.integer32 = 32
67ooe2.integer64 = 64
68ooe2.double_precision = (math.sqrt(5) + 1) / 2
69ooe2.some_characters = ":R (me going \"rrrr\")"
Nobuaki Sukegawaa3b88a02016-01-06 20:44:17 +090070ooe2.zomg_unicode = u"\xd3\x80\xe2\x85\xae\xce\x9d\x20"\
71 u"\xd0\x9d\xce\xbf\xe2\x85\xbf\xd0\xbe"\
72 u"\xc9\xa1\xd0\xb3\xd0\xb0\xcf\x81\xe2\x84\x8e"\
73 u"\x20\xce\x91\x74\x74\xce\xb1\xe2\x85\xbd\xce\xba"\
74 u"\xc7\x83\xe2\x80\xbc"
75
76if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090077 ooe1.zomg_unicode = ooe1.zomg_unicode.encode('utf8')
78 ooe2.zomg_unicode = ooe2.zomg_unicode.encode('utf8')
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090079
80hm = HolyMoley(**{"big": [], "contain": set(), "bonks": {}})
81hm.big.append(ooe1)
82hm.big.append(ooe2)
83hm.big[0].a_bite = 0x22
84hm.big[1].a_bite = 0x22
85
86hm.contain.add(("and a one", "and a two"))
87hm.contain.add(("then a one, two", "three!", "FOUR!"))
Elvis Pranskevichus2d1fe882017-05-23 11:36:23 -040088if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'):
89 hm.contain.add((u"\xd7\n\a\t".encode('utf8'),))
90else:
91 hm.contain.add((u"\xd7\n\a\t",))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090092hm.contain.add(())
93
94hm.bonks["nothing"] = []
95hm.bonks["something"] = [
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090096 Bonk(**{"type": 1, "message": "Wait."}),
97 Bonk(**{"type": 2, "message": "What?"}),
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090098]
99hm.bonks["poe"] = [
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900100 Bonk(**{"type": 3, "message": "quoth"}),
101 Bonk(**{"type": 4, "message": "the raven"}),
102 Bonk(**{"type": 5, "message": "nevermore"}),
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900103]
104
105rs = RandomStuff()
106rs.a = 1
107rs.b = 2
108rs.c = 3
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900109rs.myintlist = list(range(20))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900110rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})}
111rs.bigint = 124523452435
112rs.triple = 3.14
113
114# make sure this splits two buffers in a buffered protocol
115rshuge = RandomStuff()
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900116rshuge.myintlist = list(range(10000))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900117
118my_zero = Srv.Janky_result(**{"success": 5})
119
120
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900121class Test(object):
122 def __init__(self, fast, slow):
123 self._fast = fast
124 self._slow = slow
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900125
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900126 def _check_write(self, o):
127 trans_fast = TTransport.TMemoryBuffer()
128 trans_slow = TTransport.TMemoryBuffer()
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900129 prot_fast = self._fast(trans_fast, fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900130 prot_slow = self._slow(trans_slow)
131
132 o.write(prot_fast)
133 o.write(prot_slow)
134 ORIG = trans_slow.getvalue()
135 MINE = trans_fast.getvalue()
136 if ORIG != MINE:
137 print("actual : %s\nexpected: %s" % (repr(MINE), repr(ORIG)))
138 raise Exception('write value mismatch')
139
140 def _check_read(self, o):
141 prot = self._slow(TTransport.TMemoryBuffer())
142 o.write(prot)
143
144 slow_version_binary = prot.trans.getvalue()
145
146 prot = self._fast(
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900147 TTransport.TMemoryBuffer(slow_version_binary), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900148 c = o.__class__()
149 c.read(prot)
150 if c != o:
151 print("actual : ")
152 pprint(repr(c))
153 print("expected: ")
154 pprint(repr(o))
155 raise Exception('read value mismatch')
156
157 prot = self._fast(
158 TTransport.TBufferedTransport(
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900159 TTransport.TMemoryBuffer(slow_version_binary)), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900160 c = o.__class__()
161 c.read(prot)
162 if c != o:
163 print("actual : ")
164 pprint(repr(c))
165 print("expected: ")
166 pprint(repr(o))
167 raise Exception('read value mismatch')
168
169 def do_test(self):
170 self._check_write(HolyMoley())
171 self._check_read(HolyMoley())
172
173 self._check_write(hm)
174 no_set = deepcopy(hm)
175 no_set.contain = set()
176 self._check_read(no_set)
177 self._check_read(hm)
178
179 self._check_write(rs)
180 self._check_read(rs)
181
182 self._check_write(rshuge)
183 self._check_read(rshuge)
184
185 self._check_write(my_zero)
186 self._check_read(my_zero)
187
188 self._check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2}))
189
190 # One case where the serialized form changes, but only superficially.
191 o = Backwards(**{"first_tag2": 4, "second_tag1": 2})
192 trans_fast = TTransport.TMemoryBuffer()
193 trans_slow = TTransport.TMemoryBuffer()
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900194 prot_fast = self._fast(trans_fast, fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900195 prot_slow = self._slow(trans_slow)
196
197 o.write(prot_fast)
198 o.write(prot_slow)
199 ORIG = trans_slow.getvalue()
200 MINE = trans_fast.getvalue()
201 assert id(ORIG) != id(MINE)
202
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900203 prot = self._fast(TTransport.TMemoryBuffer(), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900204 o.write(prot)
205 prot = self._slow(
206 TTransport.TMemoryBuffer(prot.trans.getvalue()))
207 c = o.__class__()
208 c.read(prot)
209 if c != o:
210 print("copy: ")
211 pprint(repr(c))
212 print("orig: ")
213 pprint(repr(o))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900214
215
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900216def do_test(fast, slow):
217 Test(fast, slow).do_test()
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900218
219
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900220def do_benchmark(protocol, iters=5000, skip_slow=False):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900221 setup = """
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900222from __main__ import hm, rs, TDevNullTransport
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900223from thrift.protocol.{0} import {0}{1}
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900224trans = TDevNullTransport()
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900225prot = {0}{1}(trans{2})
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900226"""
227
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900228 setup_fast = setup.format(protocol, 'Accelerated', ', fallback=False')
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900229 if not skip_slow:
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900230 setup_slow = setup.format(protocol, '', '')
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900231
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900232 print("Starting Benchmarks")
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900233
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900234 if not skip_slow:
235 print("HolyMoley Standard = %f" %
236 timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters))
237
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900238 print("HolyMoley Acceler. = %f" %
239 timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900240
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900241 if not skip_slow:
242 print("FastStruct Standard = %f" %
243 timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters))
244
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900245 print("FastStruct Acceler. = %f" %
246 timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900247
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900248
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900249if __name__ == '__main__':
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900250 print('Testing TBinaryAccelerated')
251 do_test(TBinaryProtocolAccelerated, TBinaryProtocol)
252 do_benchmark('TBinaryProtocol')
253 print('Testing TCompactAccelerated')
254 do_test(TCompactProtocolAccelerated, TCompactProtocol)
255 do_benchmark('TCompactProtocol')