Skip to content

Commit a4453c6

Browse files
committed
Adds speed tests for int2bytes and old_int2bytes.
* In the following tests, the first speed test for each version of Python checked is the new implementation and the second is the old implementation. $ ./speed.sh int2bytes speed test python2.5 1000 loops, best of 3: 315 usec per loop 100 loops, best of 3: 4.87 msec per loop python2.6 10000 loops, best of 3: 170 usec per loop 100 loops, best of 3: 3.34 msec per loop python2.7 10000 loops, best of 3: 169 usec per loop 100 loops, best of 3: 2.8 msec per loop python3.2 10000 loops, best of 3: 169 usec per loop 100 loops, best of 3: 3.16 msec per loop
1 parent c19a21b commit a4453c6

3 files changed

Lines changed: 89 additions & 7 deletions

File tree

rsa/transform.py

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121

2222
from __future__ import absolute_import
2323

24+
import types
2425
import binascii
2526
from struct import pack
26-
from rsa._compat import is_integer, b
27+
from rsa import common
28+
from rsa._compat import is_integer, b, byte
2729

2830
ZERO_BYTE = b('\x00')
2931

@@ -43,7 +45,7 @@ def bytes2int(raw_bytes):
4345
return int(binascii.hexlify(raw_bytes), 16)
4446

4547

46-
def int2bytes(number, block_size=None):
48+
def old_int2bytes(number, block_size=0):
4749
r'''Converts a number to a string of bytes.
4850
4951
@param number: the number to convert
@@ -55,6 +57,65 @@ def int2bytes(number, block_size=None):
5557
bytes than fit into the block.
5658
5759
60+
>>> old_int2bytes(123456789)
61+
b'\x07[\xcd\x15'
62+
>>> bytes2int(int2bytes(123456789))
63+
123456789
64+
65+
>>> old_int2bytes(123456789, 6)
66+
b'\x00\x00\x07[\xcd\x15'
67+
>>> bytes2int(int2bytes(123456789, 128))
68+
123456789
69+
70+
>>> old_int2bytes(123456789, 3)
71+
Traceback (most recent call last):
72+
...
73+
OverflowError: Needed 4 bytes for number, but block size is 3
74+
75+
'''
76+
77+
# Type checking
78+
if not is_integer(number):
79+
raise TypeError("You must pass an integer for 'number', not %s" %
80+
number.__class__)
81+
82+
if number < 0:
83+
raise ValueError('Negative numbers cannot be used: %i' % number)
84+
85+
# Do some bounds checking
86+
needed_bytes = common.byte_size(number)
87+
if block_size > 0:
88+
if needed_bytes > block_size:
89+
raise OverflowError('Needed %i bytes for number, but block size '
90+
'is %i' % (needed_bytes, block_size))
91+
92+
# Convert the number to bytes.
93+
raw_bytes = []
94+
while number > 0:
95+
raw_bytes.insert(0, byte(number & 0xFF))
96+
number >>= 8
97+
98+
# Pad with zeroes to fill the block
99+
if block_size > 0:
100+
padding = (block_size - needed_bytes) * ZERO_BYTE
101+
else:
102+
padding = b('')
103+
104+
return padding + b('').join(raw_bytes)
105+
106+
107+
def int2bytes(number, block_size=None):
108+
"""Converts a number to a string of bytes.
109+
110+
@param number: the number to convert
111+
@param block_size: the number of bytes to output. If the number encoded to
112+
bytes is less than this, the block will be zero-padded. When not given,
113+
the returned block is not padded.
114+
115+
@throws OverflowError when block_size is given and the number takes up more
116+
bytes than fit into the block.
117+
118+
58119
>>> int2bytes(123456789)
59120
'\x07[\xcd\x15'
60121
>>> bytes2int(int2bytes(123456789))
@@ -69,9 +130,7 @@ def int2bytes(number, block_size=None):
69130
Traceback (most recent call last):
70131
...
71132
OverflowError: Need 4 bytes for number, but block size is 3
72-
73-
'''
74-
133+
"""
75134
# Type checking
76135
if not is_integer(number):
77136
raise TypeError("You must pass an integer for 'number', not %s" %
@@ -95,7 +154,7 @@ def int2bytes(number, block_size=None):
95154
if x != ZERO_BYTE[0]:
96155
break
97156

98-
if block_size > 0:
157+
if block_size is not None and block_size > 0:
99158
# Bounds checking. We're not doing this up-front because the
100159
# most common use case is not specifying a chunk size. In the worst
101160
# case, the number will already have been converted to bytes above.

speed.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/sh
2+
3+
echo "int2bytes speed test"
4+
echo "python2.5"
5+
python2.5 -mtimeit -s'from rsa.transform import int2bytes; n = 1<<4096' 'int2bytes(n)'
6+
python2.5 -mtimeit -s'from rsa.transform import old_int2bytes; n = 1<<4096' 'old_int2bytes(n)'
7+
echo "python2.6"
8+
python2.6 -mtimeit -s'from rsa.transform import int2bytes; n = 1<<4096' 'int2bytes(n)'
9+
python2.6 -mtimeit -s'from rsa.transform import old_int2bytes; n = 1<<4096' 'old_int2bytes(n)'
10+
echo "python2.7"
11+
python2.7 -mtimeit -s'from rsa.transform import int2bytes; n = 1<<4096' 'int2bytes(n)'
12+
python2.7 -mtimeit -s'from rsa.transform import old_int2bytes; n = 1<<4096' 'old_int2bytes(n)'
13+
echo "python3.2"
14+
python3 -mtimeit -s'from rsa.transform import int2bytes; n = 1<<4096' 'int2bytes(n)'
15+
python3 -mtimeit -s'from rsa.transform import old_int2bytes; n = 1<<4096' 'old_int2bytes(n)'

tests/test_transform.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import unittest2
55
from rsa._compat import b
6-
from rsa.transform import int2bytes
6+
from rsa.transform import int2bytes, old_int2bytes
77

88

99
class Test_integer_to_bytes(unittest2.TestCase):
@@ -12,13 +12,21 @@ def test_chunk_size(self):
1212
b('\x00\x00\x07[\xcd\x15'))
1313
self.assertEqual(int2bytes(123456789, 7),
1414
b('\x00\x00\x00\x07[\xcd\x15'))
15+
self.assertEqual(old_int2bytes(123456789, 6),
16+
b('\x00\x00\x07[\xcd\x15'))
17+
self.assertEqual(old_int2bytes(123456789, 7),
18+
b('\x00\x00\x00\x07[\xcd\x15'))
1519

1620
def test_raises_OverflowError_when_chunk_size_is_insufficient(self):
1721
self.assertRaises(OverflowError, int2bytes, 123456789, 3)
1822
self.assertRaises(OverflowError, int2bytes, 299999999999, 4)
23+
self.assertRaises(OverflowError, old_int2bytes, 123456789, 3)
24+
self.assertRaises(OverflowError, old_int2bytes, 299999999999, 4)
1925

2026
def test_raises_ValueError_when_negative_integer(self):
2127
self.assertRaises(ValueError, int2bytes, -1)
28+
self.assertRaises(ValueError, old_int2bytes, -1)
2229

2330
def test_raises_TypeError_when_not_integer(self):
2431
self.assertRaises(TypeError, int2bytes, None)
32+
self.assertRaises(TypeError, old_int2bytes, None)

0 commit comments

Comments
 (0)