blob: 9d258fdbfcbf56775ca038c185700841a1b86281 [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
28import math
Nobuaki Sukegawaa3b88a02016-01-06 20:44:17 +090029import os
30import sys
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090031import timeit
32
33from copy import deepcopy
34from pprint import pprint
35
36from thrift.transport import TTransport
37from thrift.protocol import TBinaryProtocol
38
39from DebugProtoTest import Srv
40from DebugProtoTest.ttypes import Backwards, Bonk, Empty, HolyMoley, OneOfEach, RandomStuff, Wrapper
41
42
43class TDevNullTransport(TTransport.TTransportBase):
44 def __init__(self):
45 pass
46
47 def isOpen(self):
48 return True
49
50ooe1 = OneOfEach()
51ooe1.im_true = True
52ooe1.im_false = False
53ooe1.a_bite = 0xd6
54ooe1.integer16 = 27000
55ooe1.integer32 = 1 << 24
56ooe1.integer64 = 6000 * 1000 * 1000
57ooe1.double_precision = math.pi
58ooe1.some_characters = "Debug THIS!"
Nobuaki Sukegawaa3b88a02016-01-06 20:44:17 +090059ooe1.zomg_unicode = u"\xd7\n\a\t"
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090060
61ooe2 = OneOfEach()
62ooe2.integer16 = 16
63ooe2.integer32 = 32
64ooe2.integer64 = 64
65ooe2.double_precision = (math.sqrt(5) + 1) / 2
66ooe2.some_characters = ":R (me going \"rrrr\")"
Nobuaki Sukegawaa3b88a02016-01-06 20:44:17 +090067ooe2.zomg_unicode = u"\xd3\x80\xe2\x85\xae\xce\x9d\x20"\
68 u"\xd0\x9d\xce\xbf\xe2\x85\xbf\xd0\xbe"\
69 u"\xc9\xa1\xd0\xb3\xd0\xb0\xcf\x81\xe2\x84\x8e"\
70 u"\x20\xce\x91\x74\x74\xce\xb1\xe2\x85\xbd\xce\xba"\
71 u"\xc7\x83\xe2\x80\xbc"
72
73if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'):
74 ooe1.zomg_unicode = ooe1.zomg_unicode.encode('utf8')
75 ooe2.zomg_unicode = ooe2.zomg_unicode.encode('utf8')
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090076
77hm = HolyMoley(**{"big": [], "contain": set(), "bonks": {}})
78hm.big.append(ooe1)
79hm.big.append(ooe2)
80hm.big[0].a_bite = 0x22
81hm.big[1].a_bite = 0x22
82
83hm.contain.add(("and a one", "and a two"))
84hm.contain.add(("then a one, two", "three!", "FOUR!"))
85hm.contain.add(())
86
87hm.bonks["nothing"] = []
88hm.bonks["something"] = [
89 Bonk(**{"type": 1, "message": "Wait."}),
90 Bonk(**{"type": 2, "message": "What?"}),
91]
92hm.bonks["poe"] = [
93 Bonk(**{"type": 3, "message": "quoth"}),
94 Bonk(**{"type": 4, "message": "the raven"}),
95 Bonk(**{"type": 5, "message": "nevermore"}),
96]
97
98rs = RandomStuff()
99rs.a = 1
100rs.b = 2
101rs.c = 3
102rs.myintlist = range(20)
103rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})}
104rs.bigint = 124523452435
105rs.triple = 3.14
106
107# make sure this splits two buffers in a buffered protocol
108rshuge = RandomStuff()
109rshuge.myintlist = range(10000)
110
111my_zero = Srv.Janky_result(**{"success": 5})
112
113
114def check_write(o):
115 trans_fast = TTransport.TMemoryBuffer()
116 trans_slow = TTransport.TMemoryBuffer()
117 prot_fast = TBinaryProtocol.TBinaryProtocolAccelerated(trans_fast)
118 prot_slow = TBinaryProtocol.TBinaryProtocol(trans_slow)
119
120 o.write(prot_fast)
121 o.write(prot_slow)
122 ORIG = trans_slow.getvalue()
123 MINE = trans_fast.getvalue()
124 if ORIG != MINE:
125 print("mine: %s\norig: %s" % (repr(MINE), repr(ORIG)))
126
127
128def check_read(o):
129 prot = TBinaryProtocol.TBinaryProtocol(TTransport.TMemoryBuffer())
130 o.write(prot)
131
132 slow_version_binary = prot.trans.getvalue()
133
134 prot = TBinaryProtocol.TBinaryProtocolAccelerated(
135 TTransport.TMemoryBuffer(slow_version_binary))
136 c = o.__class__()
137 c.read(prot)
138 if c != o:
139 print("copy: ")
140 pprint(eval(repr(c)))
141 print("orig: ")
142 pprint(eval(repr(o)))
143
144 prot = TBinaryProtocol.TBinaryProtocolAccelerated(
145 TTransport.TBufferedTransport(
146 TTransport.TMemoryBuffer(slow_version_binary)))
147 c = o.__class__()
148 c.read(prot)
149 if c != o:
150 print("copy: ")
151 pprint(eval(repr(c)))
152 print("orig: ")
153 pprint(eval(repr(o)))
154
155
156def do_test():
157 check_write(hm)
158 check_read(HolyMoley())
159 no_set = deepcopy(hm)
160 no_set.contain = set()
161 check_read(no_set)
162 check_write(rs)
163 check_read(rs)
164 check_write(rshuge)
165 check_read(rshuge)
166 check_write(my_zero)
167 check_read(my_zero)
168 check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2}))
169
170 # One case where the serialized form changes, but only superficially.
171 o = Backwards(**{"first_tag2": 4, "second_tag1": 2})
172 trans_fast = TTransport.TMemoryBuffer()
173 trans_slow = TTransport.TMemoryBuffer()
174 prot_fast = TBinaryProtocol.TBinaryProtocolAccelerated(trans_fast)
175 prot_slow = TBinaryProtocol.TBinaryProtocol(trans_slow)
176
177 o.write(prot_fast)
178 o.write(prot_slow)
179 ORIG = trans_slow.getvalue()
180 MINE = trans_fast.getvalue()
181 assert id(ORIG) != id(MINE)
182
183 prot = TBinaryProtocol.TBinaryProtocolAccelerated(TTransport.TMemoryBuffer())
184 o.write(prot)
185 prot = TBinaryProtocol.TBinaryProtocol(
186 TTransport.TMemoryBuffer(prot.trans.getvalue()))
187 c = o.__class__()
188 c.read(prot)
189 if c != o:
190 print("copy: ")
191 pprint(eval(repr(c)))
192 print("orig: ")
193 pprint(eval(repr(o)))
194
195
196def do_benchmark(iters=5000):
197 setup = """
198from __main__ import hm, rs, TDevNullTransport
199from thrift.protocol import TBinaryProtocol
200trans = TDevNullTransport()
201prot = TBinaryProtocol.TBinaryProtocol%s(trans)
202"""
203
204 setup_fast = setup % "Accelerated"
205 setup_slow = setup % ""
206
207 print("Starting Benchmarks")
208
209 print("HolyMoley Standard = %f" %
210 timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters))
211 print("HolyMoley Acceler. = %f" %
212 timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters))
213
214 print("FastStruct Standard = %f" %
215 timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters))
216 print("FastStruct Acceler. = %f" %
217 timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters))
218
219if __name__ == '__main__':
220 do_test()
221 do_benchmark()