Last active
October 8, 2017 18:11
-
-
Save PM2Ring/1d500e9518146c3391161159686014e5 to your computer and use it in GitHub Desktop.
Test speeds of performing XOR on two bytes strings of equal length
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
#! /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