[Python] xor: cosi' lento?

michele a nectarine.it michele a nectarine.it
Mer 15 Ott 2008 13:15:38 CEST


Ciao,
ho scritto un semplice encoder in Python che deve effettuare dei  
semplici xor tra blocchi di dati (non mi soffermo sul procedimento, la  
questione è un'altra).
Il problema è che lo xor deve essere fatto su byte di dati, e quindi  
del tipo str; xor non è supportato per str, quindi devo scorrere la  
stringa tramite un ciclo, leggere il carattere corrispondente,  
trasformarlo in intero con ord(), fare lo xor, ritrasformare l'intero  
in carattere e poi metterlo nella stringa.
Suppongo che le operazioni che ho descritto nell'ultimo paragrafo  
siano quelle per cui impiego più tempo: infatti, su una macchina  
abbastanza recente (dual core 3.0Ghz), l'esecuzione del metodo  
create_random_block impiega ben 0.5s:

took 48.9989998341s, avg: 0.489989998341s

Ovviamente non sono a conoscenza di un altro modo per effettuare lo  
xor tra byte di dati, ma mi sembra che il tempo richiesto per le  
operazioni sia effettivamente troppo alto (perfino java è più veloce).

Secondo voi come potrei risolvere?
In coda trovate il mio codice completo.

Grazie


from __future__ import division
import random
import time
import sha
import os

class Encoder(object):
	def create_random_block(self, data, seed, blocksize):
		number_of_blocks = int(len(data)/blocksize)
		random.seed(seed)
		random_block = ['0'] * blocksize
		for index in range(number_of_blocks):
			if int(random.getrandbits(1)) == 1:
				block = data[blocksize*index:blocksize*index+blocksize]
				for bit in range(len(block)):
					random_block[bit] = chr(ord(random_block[bit])^ord(block[bit])) #  
workaround per fare xor bit a bit di str; xor e' solo supportato per  
int -> ord
		return ''.join(random_block)


x = Encoder()
piece = os.urandom(1024*1024)
blocksize = 16384
t1 = time.time()
for l in range(100):
	seed = random.getrandbits(32)
	block = x.create_random_block(piece, seed, blocksize)
t2 = time.time()
print 'took ' + str(t2-t1) + 's, avg: ' + str((t2-t1)/100.0) + 's'




Maggiori informazioni sulla lista Python