ZeroNet/plugins/Bigfile/BigfilePiecefield.py

171 lines
4.6 KiB
Python
Raw Normal View History

2017-10-04 13:28:59 +02:00
import array
def packPiecefield(data):
if not isinstance(data, bytes) and not isinstance(data, bytearray):
raise Exception("Invalid data type: %s" % type(data))
2017-10-04 13:28:59 +02:00
res = []
if not data:
2019-03-15 21:06:59 +01:00
return array.array("H", b"")
2017-10-04 13:28:59 +02:00
if data[0] == b"\x00":
2017-10-04 13:28:59 +02:00
res.append(0)
find = b"\x01"
2017-10-04 13:28:59 +02:00
else:
find = b"\x00"
2017-10-04 13:28:59 +02:00
last_pos = 0
pos = 0
while 1:
pos = data.find(find, pos)
if find == b"\x00":
find = b"\x01"
2017-10-04 13:28:59 +02:00
else:
find = b"\x00"
2017-10-04 13:28:59 +02:00
if pos == -1:
res.append(len(data) - last_pos)
break
res.append(pos - last_pos)
last_pos = pos
return array.array("H", res)
def unpackPiecefield(data):
if not data:
return b""
2017-10-04 13:28:59 +02:00
res = []
char = b"\x01"
2017-10-04 13:28:59 +02:00
for times in data:
if times > 10000:
return b""
2017-10-04 13:28:59 +02:00
res.append(char * times)
if char == b"\x01":
char = b"\x00"
2017-10-04 13:28:59 +02:00
else:
char = b"\x01"
return b"".join(res)
2017-10-04 13:28:59 +02:00
def spliceBit(data, idx, bit):
if bit != b"\x00" and bit != b"\x01":
raise Exception("Invalid bit: %s" % bit)
if len(data) < idx:
data = data.ljust(idx + 1, b"\x00")
return data[:idx] + bit + data[idx+ 1:]
class Piecefield(object):
def tostring(self):
return "".join(["1" if b else "0" for b in self.tobytes()])
class BigfilePiecefield(Piecefield):
2017-10-04 13:28:59 +02:00
__slots__ = ["data"]
def __init__(self):
2019-03-15 21:06:59 +01:00
self.data = b""
2017-10-04 13:28:59 +02:00
def frombytes(self, s):
if not isinstance(s, bytes) and not isinstance(s, bytearray):
raise Exception("Invalid type: %s" % type(s))
2017-10-04 13:28:59 +02:00
self.data = s
def tobytes(self):
2017-10-04 13:28:59 +02:00
return self.data
def pack(self):
return packPiecefield(self.data).tobytes()
2017-10-04 13:28:59 +02:00
def unpack(self, s):
self.data = unpackPiecefield(array.array("H", s))
def __getitem__(self, key):
try:
return self.data[key]
2017-10-04 13:28:59 +02:00
except IndexError:
return False
def __setitem__(self, key, value):
self.data = spliceBit(self.data, key, value)
2017-10-04 13:28:59 +02:00
class BigfilePiecefieldPacked(Piecefield):
2017-10-04 13:28:59 +02:00
__slots__ = ["data"]
def __init__(self):
2019-03-15 21:06:59 +01:00
self.data = b""
2017-10-04 13:28:59 +02:00
def frombytes(self, data):
if not isinstance(data, bytes) and not isinstance(data, bytearray):
raise Exception("Invalid type: %s" % type(data))
self.data = packPiecefield(data).tobytes()
2017-10-04 13:28:59 +02:00
def tobytes(self):
2017-10-04 13:28:59 +02:00
return unpackPiecefield(array.array("H", self.data))
def pack(self):
return array.array("H", self.data).tobytes()
2017-10-04 13:28:59 +02:00
def unpack(self, data):
self.data = data
def __getitem__(self, key):
try:
return self.tobytes()[key]
2017-10-04 13:28:59 +02:00
except IndexError:
return False
def __setitem__(self, key, value):
data = spliceBit(self.tobytes(), key, value)
self.frombytes(data)
2017-10-04 13:28:59 +02:00
if __name__ == "__main__":
import os
import psutil
import time
testdata = b"\x01" * 100 + b"\x00" * 900 + b"\x01" * 4000 + b"\x00" * 4999 + b"\x01"
2017-10-04 13:28:59 +02:00
meminfo = psutil.Process(os.getpid()).memory_info
for storage in [BigfilePiecefieldPacked, BigfilePiecefield]:
2019-03-16 03:44:13 +01:00
print("-- Testing storage: %s --" % storage)
2017-10-04 13:28:59 +02:00
m = meminfo()[0]
s = time.time()
piecefields = {}
for i in range(10000):
piecefield = storage()
piecefield.frombytes(testdata[:i] + b"\x00" + testdata[i + 1:])
2017-10-04 13:28:59 +02:00
piecefields[i] = piecefield
2019-03-15 21:06:59 +01:00
print("Create x10000: +%sKB in %.3fs (len: %s)" % ((meminfo()[0] - m) / 1024, time.time() - s, len(piecefields[0].data)))
2017-10-04 13:28:59 +02:00
m = meminfo()[0]
s = time.time()
2019-03-15 21:06:59 +01:00
for piecefield in list(piecefields.values()):
2017-10-04 13:28:59 +02:00
val = piecefield[1000]
2019-03-15 21:06:59 +01:00
print("Query one x10000: +%sKB in %.3fs" % ((meminfo()[0] - m) / 1024, time.time() - s))
2017-10-04 13:28:59 +02:00
m = meminfo()[0]
s = time.time()
2019-03-15 21:06:59 +01:00
for piecefield in list(piecefields.values()):
piecefield[1000] = b"\x01"
2017-10-04 13:28:59 +02:00
2019-03-15 21:06:59 +01:00
print("Change one x10000: +%sKB in %.3fs" % ((meminfo()[0] - m) / 1024, time.time() - s))
2017-10-04 13:28:59 +02:00
m = meminfo()[0]
s = time.time()
2019-03-15 21:06:59 +01:00
for piecefield in list(piecefields.values()):
2017-10-04 13:28:59 +02:00
packed = piecefield.pack()
2019-03-15 21:06:59 +01:00
print("Pack x10000: +%sKB in %.3fs (len: %s)" % ((meminfo()[0] - m) / 1024, time.time() - s, len(packed)))
2017-10-04 13:28:59 +02:00
m = meminfo()[0]
s = time.time()
2019-03-15 21:06:59 +01:00
for piecefield in list(piecefields.values()):
2017-10-04 13:28:59 +02:00
piecefield.unpack(packed)
2019-03-15 21:06:59 +01:00
print("Unpack x10000: +%sKB in %.3fs (len: %s)" % ((meminfo()[0] - m) / 1024, time.time() - s, len(piecefields[0].data)))
2017-10-04 13:28:59 +02:00
piecefields = {}