blob: 05c0bb6d15a0e4cd80fb4395eb9dd473646962c0 [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
James E. King, III0ad20bd2017-09-30 15:44:16 -070053
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090054ooe1 = OneOfEach()
55ooe1.im_true = True
56ooe1.im_false = False
57ooe1.a_bite = 0xd6
58ooe1.integer16 = 27000
59ooe1.integer32 = 1 << 24
60ooe1.integer64 = 6000 * 1000 * 1000
61ooe1.double_precision = math.pi
62ooe1.some_characters = "Debug THIS!"
Nobuaki Sukegawaa3b88a02016-01-06 20:44:17 +090063ooe1.zomg_unicode = u"\xd7\n\a\t"
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090064
65ooe2 = OneOfEach()
66ooe2.integer16 = 16
67ooe2.integer32 = 32
68ooe2.integer64 = 64
69ooe2.double_precision = (math.sqrt(5) + 1) / 2
70ooe2.some_characters = ":R (me going \"rrrr\")"
Nobuaki Sukegawaa3b88a02016-01-06 20:44:17 +090071ooe2.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
77if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090078 ooe1.zomg_unicode = ooe1.zomg_unicode.encode('utf8')
79 ooe2.zomg_unicode = ooe2.zomg_unicode.encode('utf8')
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090080
81hm = HolyMoley(**{"big": [], "contain": set(), "bonks": {}})
82hm.big.append(ooe1)
83hm.big.append(ooe2)
84hm.big[0].a_bite = 0x22
85hm.big[1].a_bite = 0x22
86
87hm.contain.add(("and a one", "and a two"))
88hm.contain.add(("then a one, two", "three!", "FOUR!"))
Elvis Pranskevichus2d1fe882017-05-23 11:36:23 -040089if 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'),))
91else:
92 hm.contain.add((u"\xd7\n\a\t",))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090093hm.contain.add(())
94
95hm.bonks["nothing"] = []
96hm.bonks["something"] = [
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090097 Bonk(**{"type": 1, "message": "Wait."}),
98 Bonk(**{"type": 2, "message": "What?"}),
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090099]
100hm.bonks["poe"] = [
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900101 Bonk(**{"type": 3, "message": "quoth"}),
102 Bonk(**{"type": 4, "message": "the raven"}),
103 Bonk(**{"type": 5, "message": "nevermore"}),
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900104]
105
106rs = RandomStuff()
107rs.a = 1
108rs.b = 2
109rs.c = 3
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900110rs.myintlist = list(range(20))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900111rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})}
112rs.bigint = 124523452435
113rs.triple = 3.14
114
115# make sure this splits two buffers in a buffered protocol
116rshuge = RandomStuff()
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900117rshuge.myintlist = list(range(10000))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900118
119my_zero = Srv.Janky_result(**{"success": 5})
120
121
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900122class Test(object):
123 def __init__(self, fast, slow):
124 self._fast = fast
125 self._slow = slow
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900126
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900127 def _check_write(self, o):
128 trans_fast = TTransport.TMemoryBuffer()
129 trans_slow = TTransport.TMemoryBuffer()
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900130 prot_fast = self._fast(trans_fast, fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900131 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 Sukegawa7af189a2016-02-11 16:21:01 +0900148 TTransport.TMemoryBuffer(slow_version_binary), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900149 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 Sukegawa7af189a2016-02-11 16:21:01 +0900160 TTransport.TMemoryBuffer(slow_version_binary)), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900161 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 Sukegawa7af189a2016-02-11 16:21:01 +0900195 prot_fast = self._fast(trans_fast, fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900196 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 Sukegawa7af189a2016-02-11 16:21:01 +0900204 prot = self._fast(TTransport.TMemoryBuffer(), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900205 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 Sukegawa7b894692015-12-23 21:45:06 +0900215
216
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900217def do_test(fast, slow):
218 Test(fast, slow).do_test()
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900219
220
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900221def do_benchmark(protocol, iters=5000, skip_slow=False):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900222 setup = """
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900223from __main__ import hm, rs, TDevNullTransport
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900224from thrift.protocol.{0} import {0}{1}
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900225trans = TDevNullTransport()
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900226prot = {0}{1}(trans{2})
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900227"""
228
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900229 setup_fast = setup.format(protocol, 'Accelerated', ', fallback=False')
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900230 if not skip_slow:
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900231 setup_slow = setup.format(protocol, '', '')
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900232
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900233 print("Starting Benchmarks")
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900234
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900235 if not skip_slow:
236 print("HolyMoley Standard = %f" %
237 timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters))
238
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900239 print("HolyMoley Acceler. = %f" %
240 timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900241
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900242 if not skip_slow:
243 print("FastStruct Standard = %f" %
244 timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters))
245
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900246 print("FastStruct Acceler. = %f" %
247 timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900248
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900249
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900250if __name__ == '__main__':
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900251 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')