Skip to content

Instantly share code, notes, and snippets.

@esneider
Created May 15, 2015 20:58
Show Gist options
  • Save esneider/a89e4d57c7fa1e56b42b to your computer and use it in GitHub Desktop.
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)
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