blob: a8718dce19d73f72f6818ff8aa13d472a3a2bc91 [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):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090044 def __init__(self):
45 pass
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090046
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090047 def isOpen(self):
48 return True
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090049
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'):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090074 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"] = [
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090089 Bonk(**{"type": 1, "message": "Wait."}),
90 Bonk(**{"type": 2, "message": "What?"}),
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090091]
92hm.bonks["poe"] = [
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +090093 Bonk(**{"type": 3, "message": "quoth"}),
94 Bonk(**{"type": 4, "message": "the raven"}),
95 Bonk(**{"type": 5, "message": "nevermore"}),
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +090096]
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):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900115 trans_fast = TTransport.TMemoryBuffer()
116 trans_slow = TTransport.TMemoryBuffer()
117 prot_fast = TBinaryProtocol.TBinaryProtocolAccelerated(trans_fast)
118 prot_slow = TBinaryProtocol.TBinaryProtocol(trans_slow)
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900119
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900120 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)))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900126
127
128def check_read(o):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900129 prot = TBinaryProtocol.TBinaryProtocol(TTransport.TMemoryBuffer())
130 o.write(prot)
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900131
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900132 slow_version_binary = prot.trans.getvalue()
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900133
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900134 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)))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900143
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900144 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)))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900154
155
156def do_test():
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900157 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}))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900169
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900170 # 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)
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900176
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900177 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)
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900182
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900183 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)))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900194
195
196def do_benchmark(iters=5000):
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900197 setup = """
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900198from __main__ import hm, rs, TDevNullTransport
199from thrift.protocol import TBinaryProtocol
200trans = TDevNullTransport()
201prot = TBinaryProtocol.TBinaryProtocol%s(trans)
202"""
203
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900204 setup_fast = setup % "Accelerated"
205 setup_slow = setup % ""
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900206
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900207 print("Starting Benchmarks")
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900208
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900209 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))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900213
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900214 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))
Nobuaki Sukegawa7b894692015-12-23 21:45:06 +0900218
219if __name__ == '__main__':
Nobuaki Sukegawa10308cb2016-02-03 01:57:03 +0900220 do_test()
221 do_benchmark()