Skip to content

Instantly share code, notes, and snippets.

@PM2Ring
Last active October 8, 2017 18:11
Show Gist options
  • Save PM2Ring/1d500e9518146c3391161159686014e5 to your computer and use it in GitHub Desktop.
Save PM2Ring/1d500e9518146c3391161159686014e5 to your computer and use it in GitHub Desktop.
Test speeds of performing XOR on two bytes strings of equal length
#! /usr/bin/env python3
''' Test speeds of performing XOR on two bytes strings of equal length
Typical results on a 32bit 2GHz machine running Python 3.6.0 on Linux
Size: 2 Loops: 65536
Verify True
xor_bytes_I : [0.36799076000170317, 0.3949565820003045, 0.40133740400051465]
xor_bytes_BLC : [0.41839819899905706, 0.4583157610031776, 0.4664555540002766]
xor_bytes_BGE : [0.5030300959988381, 0.5058843359947787, 0.5087879880011315]
xor_bytes_np : [1.470509658996889, 1.47526081000251, 1.4791794430057053]
Size: 4 Loops: 32768
Verify True
xor_bytes_I : [0.18256082600419177, 0.18330108100053621, 0.1974477189942263]
xor_bytes_BLC : [0.24958959400100866, 0.24997311100014485, 0.25036751500010723]
xor_bytes_BGE : [0.30370191400288604, 0.3089544240065152, 0.3098974550011917]
xor_bytes_np : [0.7608524470051634, 0.7629943619976984, 0.800917237997055]
Size: 8 Loops: 16384
Verify True
xor_bytes_I : [0.09439384900178993, 0.09529653799836524, 0.10371874699922046]
xor_bytes_BLC : [0.16968677599652437, 0.16982837799878325, 0.17017306399793597]
xor_bytes_BGE : [0.2039188320050016, 0.2058013099958771, 0.20817617000284372]
xor_bytes_np : [0.3748543999972753, 0.37950370500038844, 0.4009694380001747]
Size: 16 Loops: 8192
Verify True
xor_bytes_I : [0.04769808200217085, 0.04869775400584331, 0.056493796000722796]
xor_bytes_BLC : [0.1279585299998871, 0.12869811699783895, 0.13057770000159508]
xor_bytes_BGE : [0.1536894230011967, 0.15522670499922242, 0.15877328100032173]
xor_bytes_np : [0.17991206800070358, 0.18021535899606533, 0.1826240640002652]
Size: 32 Loops: 4096
Verify True
xor_bytes_I : [0.025491733002127148, 0.025824666998232715, 0.033266462000028696]
xor_bytes_np : [0.0911671150024631, 0.09279038700333331, 0.0947080170008121]
xor_bytes_BLC : [0.10758084500412224, 0.10769654699834064, 0.10833411999919917]
xor_bytes_BGE : [0.12492722799652256, 0.1251947150012711, 0.12572688299405854]
Size: 64 Loops: 2048
Verify True
xor_bytes_I : [0.014080011002079118, 0.01757618299598107, 0.0183639039969421]
xor_bytes_np : [0.045353582994721364, 0.045746611001959536, 0.04580846300086705]
xor_bytes_BLC : [0.09621700100251473, 0.09909401399636408, 0.10263394999492448]
xor_bytes_BGE : [0.1129366300010588, 0.11295083499862812, 0.11344825999549357]
Size: 128 Loops: 1024
Verify True
xor_bytes_I : [0.007812693998857867, 0.008573753002565354, 0.015126005004276522]
xor_bytes_np : [0.02274296600080561, 0.022968992998357862, 0.02359117900050478]
xor_bytes_BLC : [0.08923896099440753, 0.0892793309976696, 0.08934248700097669]
xor_bytes_BGE : [0.10668773300130852, 0.10722463700221851, 0.1091907519949018]
Size: 256 Loops: 512
Verify True
xor_bytes_I : [0.006113153001933824, 0.006236145993170794, 0.011532172000443097]
xor_bytes_np : [0.011736529995687306, 0.011879313999088481, 0.012003206997178495]
xor_bytes_BLC : [0.08419692099414533, 0.08457828099926701, 0.08504373799951281]
xor_bytes_BGE : [0.10667827900033444, 0.10779845900106011, 0.1092514729971299]
Size: 512 Loops: 256
Verify True
xor_bytes_I : [0.00401436699758051, 0.00472224700206425, 0.012311526996199973]
xor_bytes_np : [0.006273667000641581, 0.006494750996353105, 0.006957768004212994]
xor_bytes_BLC : [0.08186923400353407, 0.0834047950047534, 0.0883721459977096]
xor_bytes_BGE : [0.10127449599531246, 0.10222290999809047, 0.10234129700256744]
Size: 1024 Loops: 128
Verify True
xor_bytes_I : [0.0030069040003581904, 0.0030316939955810085, 0.003352226995048113]
xor_bytes_np : [0.003309405001346022, 0.0034119560004910454, 0.003667826000310015]
xor_bytes_BLC : [0.08179298200411722, 0.09707587899902137, 0.09994569000264164]
xor_bytes_BGE : [0.10219201799918665, 0.10487588799878722, 0.12904461099969922]
Size: 2048 Loops: 64
Verify True
xor_bytes_np : [0.0016799910008558072, 0.0017491820035502315, 0.0023421079968102276]
xor_bytes_I : [0.0025409930021851324, 0.002865677000954747, 0.0029066460047033615]
xor_bytes_BLC : [0.08154783299687551, 0.08216975400137017, 0.08881795300112572]
xor_bytes_BGE : [0.10065978900092887, 0.10133726200001547, 0.10557382299884921]
Size: 4096 Loops: 32
Verify True
xor_bytes_np : [0.0009038830030476674, 0.0009098800001083873, 0.0009814310033107176]
xor_bytes_I : [0.0023531379993073642, 0.0026210259966319427, 0.002630349998071324]
xor_bytes_BLC : [0.08148786899982952, 0.08734032800566638, 0.12421483200159855]
xor_bytes_BGE : [0.10023190500214696, 0.10078571500343969, 0.10700276200077496]
Size: 8192 Loops: 16
Verify True
xor_bytes_np : [0.000497059001645539, 0.0005071399937151, 0.0006143589998828247]
xor_bytes_I : [0.002125589999195654, 0.002488359001290519, 0.0033838050003396347]
xor_bytes_BLC : [0.07940631700330414, 0.07973214800585993, 0.08431133900012355]
xor_bytes_BGE : [0.10001250600180356, 0.10005164799804334, 0.10020199900463922]
https://gist.github.com/PM2Ring/1d500e9518146c3391161159686014e5
Written by PM 2Ring 2017.10.09
'''
from timeit import Timer
from random import seed, choice, shuffle, getrandbits
import numpy as np
def randbytes(size):
n = getrandbits(8 * size)
return n.to_bytes(size, 'big')
def xor_bytes_I(a, b):
''' Convert to integer, XOR, and convert back '''
size = len(a)
#if len(b) != size:
#raise ValueError('Args must have same length')
a = int.from_bytes(a, 'big')
b = int.from_bytes(b, 'big')
return (a ^ b).to_bytes(size, 'big')
def xor_bytes_BLC(a, b):
''' loop over the individual bytes using a list comprehension '''
return bytes([u ^ v for u, v in zip(a, b)])
def xor_bytes_BGE(a, b):
''' loop over the individual bytes using a generator expression '''
return bytes(u ^ v for u, v in zip(a, b))
def xor_bytes_np(a, b):
''' Numpy version by Andras Deak '''
arr1 = np.frombuffer(a, dtype=np.uint8)
arr2 = np.frombuffer(b, dtype=np.uint8)
return (arr1 ^ arr2).tobytes()
funcs = (
xor_bytes_I,
xor_bytes_BLC,
xor_bytes_BGE,
xor_bytes_np,
)
def verify(a, b):
head, *tail = (f(a, b) for f in funcs)
return all(head == u for u in tail)
def time_test(d1, d2, loops):
timings = []
for func in funcs:
t = Timer(lambda: func(d1, d2))
result = sorted(t.repeat(3, loops))
timings.append((result, func.__name__))
timings.sort()
for result, name in timings:
print('{:14} : {}'.format(name, result))
print()
size, loops = 2, 1 << 16
for _ in range(13):
print('Size:', size, 'Loops:', loops)
d1, d2 = randbytes(size), randbytes(size)
print('Verify', verify(d1, d2))
time_test(d1, d2, loops)
loops >>= 1
size <<= 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment