blob: db3ef8b4c5fb9aa7f0ce33014c400180608b5b97 [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!"))
88hm.contain.add(())
89
90hm.bonks["nothing"] = []
91hm.bonks["something"] = [
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090092 Bonk(**{"type": 1, "message": "Wait."}),
93 Bonk(**{"type": 2, "message": "What?"}),
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090094]
95hm.bonks["poe"] = [
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090096 Bonk(**{"type": 3, "message": "quoth"}),
97 Bonk(**{"type": 4, "message": "the raven"}),
98 Bonk(**{"type": 5, "message": "nevermore"}),
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090099]
100
101rs = RandomStuff()
102rs.a = 1
103rs.b = 2
104rs.c = 3
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900105rs.myintlist = list(range(20))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900106rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})}
107rs.bigint = 124523452435
108rs.triple = 3.14
109
110# make sure this splits two buffers in a buffered protocol
111rshuge = RandomStuff()
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900112rshuge.myintlist = list(range(10000))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900113
114my_zero = Srv.Janky_result(**{"success": 5})
115
116
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900117class Test(object):
118 def __init__(self, fast, slow):
119 self._fast = fast
120 self._slow = slow
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900121
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900122 def _check_write(self, o):
123 trans_fast = TTransport.TMemoryBuffer()
124 trans_slow = TTransport.TMemoryBuffer()
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900125 prot_fast = self._fast(trans_fast, fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900126 prot_slow = self._slow(trans_slow)
127
128 o.write(prot_fast)
129 o.write(prot_slow)
130 ORIG = trans_slow.getvalue()
131 MINE = trans_fast.getvalue()
132 if ORIG != MINE:
133 print("actual : %s\nexpected: %s" % (repr(MINE), repr(ORIG)))
134 raise Exception('write value mismatch')
135
136 def _check_read(self, o):
137 prot = self._slow(TTransport.TMemoryBuffer())
138 o.write(prot)
139
140 slow_version_binary = prot.trans.getvalue()
141
142 prot = self._fast(
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900143 TTransport.TMemoryBuffer(slow_version_binary), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900144 c = o.__class__()
145 c.read(prot)
146 if c != o:
147 print("actual : ")
148 pprint(repr(c))
149 print("expected: ")
150 pprint(repr(o))
151 raise Exception('read value mismatch')
152
153 prot = self._fast(
154 TTransport.TBufferedTransport(
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900155 TTransport.TMemoryBuffer(slow_version_binary)), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900156 c = o.__class__()
157 c.read(prot)
158 if c != o:
159 print("actual : ")
160 pprint(repr(c))
161 print("expected: ")
162 pprint(repr(o))
163 raise Exception('read value mismatch')
164
165 def do_test(self):
166 self._check_write(HolyMoley())
167 self._check_read(HolyMoley())
168
169 self._check_write(hm)
170 no_set = deepcopy(hm)
171 no_set.contain = set()
172 self._check_read(no_set)
173 self._check_read(hm)
174
175 self._check_write(rs)
176 self._check_read(rs)
177
178 self._check_write(rshuge)
179 self._check_read(rshuge)
180
181 self._check_write(my_zero)
182 self._check_read(my_zero)
183
184 self._check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2}))
185
186 # One case where the serialized form changes, but only superficially.
187 o = Backwards(**{"first_tag2": 4, "second_tag1": 2})
188 trans_fast = TTransport.TMemoryBuffer()
189 trans_slow = TTransport.TMemoryBuffer()
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900190 prot_fast = self._fast(trans_fast, fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900191 prot_slow = self._slow(trans_slow)
192
193 o.write(prot_fast)
194 o.write(prot_slow)
195 ORIG = trans_slow.getvalue()
196 MINE = trans_fast.getvalue()
197 assert id(ORIG) != id(MINE)
198
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900199 prot = self._fast(TTransport.TMemoryBuffer(), fallback=False)
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900200 o.write(prot)
201 prot = self._slow(
202 TTransport.TMemoryBuffer(prot.trans.getvalue()))
203 c = o.__class__()
204 c.read(prot)
205 if c != o:
206 print("copy: ")
207 pprint(repr(c))
208 print("orig: ")
209 pprint(repr(o))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900210
211
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900212def do_test(fast, slow):
213 Test(fast, slow).do_test()
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900214
215
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900216def do_benchmark(protocol, iters=5000, skip_slow=False):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900217 setup = """
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900218from __main__ import hm, rs, TDevNullTransport
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900219from thrift.protocol.{0} import {0}{1}
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900220trans = TDevNullTransport()
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900221prot = {0}{1}(trans{2})
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900222"""
223
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900224 setup_fast = setup.format(protocol, 'Accelerated', ', fallback=False')
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900225 if not skip_slow:
Nobuaki Sukegawa7af189a2016-02-11 16:21:01 +0900226 setup_slow = setup.format(protocol, '', '')
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900227
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900228 print("Starting Benchmarks")
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900229
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900230 if not skip_slow:
231 print("HolyMoley Standard = %f" %
232 timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters))
233
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900234 print("HolyMoley Acceler. = %f" %
235 timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900236
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900237 if not skip_slow:
238 print("FastStruct Standard = %f" %
239 timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters))
240
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900241 print("FastStruct Acceler. = %f" %
242 timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900243
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900244
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900245if __name__ == '__main__':
Nobuaki Sukegawa6525f6a2016-02-11 13:58:39 +0900246 print('Testing TBinaryAccelerated')
247 do_test(TBinaryProtocolAccelerated, TBinaryProtocol)
248 do_benchmark('TBinaryProtocol')
249 print('Testing TCompactAccelerated')
250 do_test(TCompactProtocolAccelerated, TCompactProtocol)
251 do_benchmark('TCompactProtocol')