Created
May 15, 2015 20:58
-
-
Save esneider/a89e4d57c7fa1e56b42b to your computer and use it in GitHub Desktop.
Comparison of number_to_bytes strategies (unsigned big integer to zero-padded big endian byte buffer)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import binascii | |
import struct | |
import timeit | |
def number_to_bytes__hex(num, num_bytes): | |
padded_hex = '%0*x' % (2 * num_bytes, num) | |
big_endian = binascii.a2b_hex(padded_hex.encode('ascii')) | |
return big_endian | |
def number_to_bytes__struct(num, num_bytes): | |
little_endian = bytearray() | |
while num != 0: | |
word = struct.pack("<I", num & 0xffffffff) | |
little_endian.extend(word) | |
num >>= 32 | |
little_endian.reverse() | |
return bytes(little_endian.zfill(num_bytes)) | |
def number_to_bytes__twiddling(num, num_bytes): | |
little_endian = bytearray() | |
while num != 0: | |
little_endian.append(num & 0xff) | |
num >>= 8 | |
little_endian.reverse() | |
return bytes(little_endian.zfill(num_bytes)) | |
def number_to_bytes__twiddling_inplace(num, num_bytes): | |
little_endian = bytearray(num_bytes) | |
for digit in xrange(num_bytes): | |
little_endian[digit] = num & 0xff | |
num >>= 8 | |
little_endian.reverse() | |
return bytes(little_endian.zfill(num_bytes)) | |
def number_to_bytes__twiddling_inplace_direct(num, num_bytes): | |
big_endian = bytearray(num_bytes) | |
for digit in xrange(num_bytes - 1, -1, -1): | |
big_endian[digit] = num & 0xff | |
num >>= 8 | |
return bytes(big_endian.zfill(num_bytes)) | |
def number_to_bytes__comprehension(num, num_bytes): | |
big_endian = [(num >> (i << 3)) & 0xff for i in xrange(num_bytes)] | |
return bytes(bytearray(big_endian)) | |
SERIES = 3 | |
TIMES = 100000 | |
NUM = 102225100404872345074909098344783070714972869277281741698390630972627838506489L | |
NUM_BYTES = 32 | |
def sample(func): | |
def callable(): | |
return func(NUM, NUM_BYTES) | |
return callable | |
def eval(func): | |
print func.__name__, | |
print timeit.repeat(sample(func), repeat=SERIES, number=TIMES) | |
eval(number_to_bytes__hex) | |
eval(number_to_bytes__struct) | |
eval(number_to_bytes__twiddling) | |
eval(number_to_bytes__twiddling_inplace) | |
eval(number_to_bytes__twiddling_inplace_direct) | |
eval(number_to_bytes__comprehension) | |
# dario test (master) $ python num2bytes.py | |
# number_to_bytes__hex [0.2139139175415039, 0.2140209674835205, 0.19702410697937012] | |
# number_to_bytes__struct [0.6415131092071533, 0.6454949378967285, 0.6583528518676758] | |
# number_to_bytes__twiddling [1.3148159980773926, 1.299818992614746, 1.309149980545044] | |
# number_to_bytes__twiddling_inplace [0.9573349952697754, 0.95682692527771, 0.921299934387207] | |
# number_to_bytes__twiddling_inplace_direct [0.962622880935669, 0.9370100498199463, 0.9494130611419678] | |
# number_to_bytes__comprehension [1.1176629066467285, 1.1113028526306152, 1.1326720714569092] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment