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