THRIFT-3612 Add Python C extension for compact protocol
Client: Python
Patch: Nobuaki Sukegawa
This closes #844
diff --git a/test/py/FastbinaryTest.py b/test/py/FastbinaryTest.py
index a8718dc..d688cd5 100755
--- a/test/py/FastbinaryTest.py
+++ b/test/py/FastbinaryTest.py
@@ -25,6 +25,8 @@
# TODO(dreiss): Test error cases. Check for memory leaks.
+from __future__ import print_function
+
import math
import os
import sys
@@ -34,7 +36,8 @@
from pprint import pprint
from thrift.transport import TTransport
-from thrift.protocol import TBinaryProtocol
+from thrift.protocol.TBinaryProtocol import TBinaryProtocol, TBinaryProtocolAccelerated
+from thrift.protocol.TCompactProtocol import TCompactProtocol, TCompactProtocolAccelerated
from DebugProtoTest import Srv
from DebugProtoTest.ttypes import Backwards, Bonk, Empty, HolyMoley, OneOfEach, RandomStuff, Wrapper
@@ -99,123 +102,150 @@
rs.a = 1
rs.b = 2
rs.c = 3
-rs.myintlist = range(20)
+rs.myintlist = list(range(20))
rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})}
rs.bigint = 124523452435
rs.triple = 3.14
# make sure this splits two buffers in a buffered protocol
rshuge = RandomStuff()
-rshuge.myintlist = range(10000)
+rshuge.myintlist = list(range(10000))
my_zero = Srv.Janky_result(**{"success": 5})
-def check_write(o):
- trans_fast = TTransport.TMemoryBuffer()
- trans_slow = TTransport.TMemoryBuffer()
- prot_fast = TBinaryProtocol.TBinaryProtocolAccelerated(trans_fast)
- prot_slow = TBinaryProtocol.TBinaryProtocol(trans_slow)
+class Test(object):
+ def __init__(self, fast, slow):
+ self._fast = fast
+ self._slow = slow
- o.write(prot_fast)
- o.write(prot_slow)
- ORIG = trans_slow.getvalue()
- MINE = trans_fast.getvalue()
- if ORIG != MINE:
- print("mine: %s\norig: %s" % (repr(MINE), repr(ORIG)))
+ def _check_write(self, o):
+ trans_fast = TTransport.TMemoryBuffer()
+ trans_slow = TTransport.TMemoryBuffer()
+ prot_fast = self._fast(trans_fast)
+ prot_slow = self._slow(trans_slow)
+
+ o.write(prot_fast)
+ o.write(prot_slow)
+ ORIG = trans_slow.getvalue()
+ MINE = trans_fast.getvalue()
+ if ORIG != MINE:
+ print("actual : %s\nexpected: %s" % (repr(MINE), repr(ORIG)))
+ raise Exception('write value mismatch')
+
+ def _check_read(self, o):
+ prot = self._slow(TTransport.TMemoryBuffer())
+ o.write(prot)
+
+ slow_version_binary = prot.trans.getvalue()
+
+ prot = self._fast(
+ TTransport.TMemoryBuffer(slow_version_binary))
+ c = o.__class__()
+ c.read(prot)
+ if c != o:
+ print("actual : ")
+ pprint(repr(c))
+ print("expected: ")
+ pprint(repr(o))
+ raise Exception('read value mismatch')
+
+ prot = self._fast(
+ TTransport.TBufferedTransport(
+ TTransport.TMemoryBuffer(slow_version_binary)))
+ c = o.__class__()
+ c.read(prot)
+ if c != o:
+ print("actual : ")
+ pprint(repr(c))
+ print("expected: ")
+ pprint(repr(o))
+ raise Exception('read value mismatch')
+
+ def do_test(self):
+ self._check_write(HolyMoley())
+ self._check_read(HolyMoley())
+
+ self._check_write(hm)
+ no_set = deepcopy(hm)
+ no_set.contain = set()
+ self._check_read(no_set)
+ self._check_read(hm)
+
+ self._check_write(rs)
+ self._check_read(rs)
+
+ self._check_write(rshuge)
+ self._check_read(rshuge)
+
+ self._check_write(my_zero)
+ self._check_read(my_zero)
+
+ self._check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2}))
+
+ # One case where the serialized form changes, but only superficially.
+ o = Backwards(**{"first_tag2": 4, "second_tag1": 2})
+ trans_fast = TTransport.TMemoryBuffer()
+ trans_slow = TTransport.TMemoryBuffer()
+ prot_fast = self._fast(trans_fast)
+ prot_slow = self._slow(trans_slow)
+
+ o.write(prot_fast)
+ o.write(prot_slow)
+ ORIG = trans_slow.getvalue()
+ MINE = trans_fast.getvalue()
+ assert id(ORIG) != id(MINE)
+
+ prot = self._fast(TTransport.TMemoryBuffer())
+ o.write(prot)
+ prot = self._slow(
+ TTransport.TMemoryBuffer(prot.trans.getvalue()))
+ c = o.__class__()
+ c.read(prot)
+ if c != o:
+ print("copy: ")
+ pprint(repr(c))
+ print("orig: ")
+ pprint(repr(o))
-def check_read(o):
- prot = TBinaryProtocol.TBinaryProtocol(TTransport.TMemoryBuffer())
- o.write(prot)
-
- slow_version_binary = prot.trans.getvalue()
-
- prot = TBinaryProtocol.TBinaryProtocolAccelerated(
- TTransport.TMemoryBuffer(slow_version_binary))
- c = o.__class__()
- c.read(prot)
- if c != o:
- print("copy: ")
- pprint(eval(repr(c)))
- print("orig: ")
- pprint(eval(repr(o)))
-
- prot = TBinaryProtocol.TBinaryProtocolAccelerated(
- TTransport.TBufferedTransport(
- TTransport.TMemoryBuffer(slow_version_binary)))
- c = o.__class__()
- c.read(prot)
- if c != o:
- print("copy: ")
- pprint(eval(repr(c)))
- print("orig: ")
- pprint(eval(repr(o)))
+def do_test(fast, slow):
+ Test(fast, slow).do_test()
-def do_test():
- check_write(hm)
- check_read(HolyMoley())
- no_set = deepcopy(hm)
- no_set.contain = set()
- check_read(no_set)
- check_write(rs)
- check_read(rs)
- check_write(rshuge)
- check_read(rshuge)
- check_write(my_zero)
- check_read(my_zero)
- check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2}))
-
- # One case where the serialized form changes, but only superficially.
- o = Backwards(**{"first_tag2": 4, "second_tag1": 2})
- trans_fast = TTransport.TMemoryBuffer()
- trans_slow = TTransport.TMemoryBuffer()
- prot_fast = TBinaryProtocol.TBinaryProtocolAccelerated(trans_fast)
- prot_slow = TBinaryProtocol.TBinaryProtocol(trans_slow)
-
- o.write(prot_fast)
- o.write(prot_slow)
- ORIG = trans_slow.getvalue()
- MINE = trans_fast.getvalue()
- assert id(ORIG) != id(MINE)
-
- prot = TBinaryProtocol.TBinaryProtocolAccelerated(TTransport.TMemoryBuffer())
- o.write(prot)
- prot = TBinaryProtocol.TBinaryProtocol(
- TTransport.TMemoryBuffer(prot.trans.getvalue()))
- c = o.__class__()
- c.read(prot)
- if c != o:
- print("copy: ")
- pprint(eval(repr(c)))
- print("orig: ")
- pprint(eval(repr(o)))
-
-
-def do_benchmark(iters=5000):
+def do_benchmark(protocol, iters=5000, skip_slow=False):
setup = """
from __main__ import hm, rs, TDevNullTransport
-from thrift.protocol import TBinaryProtocol
+from thrift.protocol.{0} import {0}{1}
trans = TDevNullTransport()
-prot = TBinaryProtocol.TBinaryProtocol%s(trans)
+prot = {0}{1}(trans)
"""
- setup_fast = setup % "Accelerated"
- setup_slow = setup % ""
+ setup_fast = setup.format(protocol, 'Accelerated')
+ if not skip_slow:
+ setup_slow = setup.format(protocol, '')
print("Starting Benchmarks")
- print("HolyMoley Standard = %f" %
- timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters))
+ if not skip_slow:
+ print("HolyMoley Standard = %f" %
+ timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters))
+
print("HolyMoley Acceler. = %f" %
timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters))
- print("FastStruct Standard = %f" %
- timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters))
+ if not skip_slow:
+ print("FastStruct Standard = %f" %
+ timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters))
+
print("FastStruct Acceler. = %f" %
timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters))
+
if __name__ == '__main__':
- do_test()
- do_benchmark()
+ print('Testing TBinaryAccelerated')
+ do_test(TBinaryProtocolAccelerated, TBinaryProtocol)
+ do_benchmark('TBinaryProtocol')
+ print('Testing TCompactAccelerated')
+ do_test(TCompactProtocolAccelerated, TCompactProtocol)
+ do_benchmark('TCompactProtocol')