123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- import array
- def packPiecefield(data):
- if not isinstance(data, bytes) and not isinstance(data, bytearray):
- raise Exception("Invalid data type: %s" % type(data))
- res = []
- if not data:
- return array.array("H", b"")
- if data[0] == b"\x00":
- res.append(0)
- find = b"\x01"
- else:
- find = b"\x00"
- last_pos = 0
- pos = 0
- while 1:
- pos = data.find(find, pos)
- if find == b"\x00":
- find = b"\x01"
- else:
- find = b"\x00"
- 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""
- res = []
- char = b"\x01"
- for times in data:
- if times > 10000:
- return b""
- res.append(char * times)
- if char == b"\x01":
- char = b"\x00"
- else:
- char = b"\x01"
- return b"".join(res)
- 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):
- __slots__ = ["data"]
- def __init__(self):
- self.data = b""
- def frombytes(self, s):
- if not isinstance(s, bytes) and not isinstance(s, bytearray):
- raise Exception("Invalid type: %s" % type(s))
- self.data = s
- def tobytes(self):
- return self.data
- def pack(self):
- return packPiecefield(self.data).tobytes()
- def unpack(self, s):
- self.data = unpackPiecefield(array.array("H", s))
- def __getitem__(self, key):
- try:
- return self.data[key]
- except IndexError:
- return False
- def __setitem__(self, key, value):
- self.data = spliceBit(self.data, key, value)
- class BigfilePiecefieldPacked(Piecefield):
- __slots__ = ["data"]
- def __init__(self):
- self.data = b""
- 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()
- def tobytes(self):
- return unpackPiecefield(array.array("H", self.data))
- def pack(self):
- return array.array("H", self.data).tobytes()
- def unpack(self, data):
- self.data = data
- def __getitem__(self, key):
- try:
- return self.tobytes()[key]
- except IndexError:
- return False
- def __setitem__(self, key, value):
- data = spliceBit(self.tobytes(), key, value)
- self.frombytes(data)
- if __name__ == "__main__":
- import os
- import psutil
- import time
- testdata = b"\x01" * 100 + b"\x00" * 900 + b"\x01" * 4000 + b"\x00" * 4999 + b"\x01"
- meminfo = psutil.Process(os.getpid()).memory_info
- for storage in [BigfilePiecefieldPacked, BigfilePiecefield]:
- print("-- Testing storage: %s --" % storage)
- m = meminfo()[0]
- s = time.time()
- piecefields = {}
- for i in range(10000):
- piecefield = storage()
- piecefield.frombytes(testdata[:i] + b"\x00" + testdata[i + 1:])
- piecefields[i] = piecefield
- print("Create x10000: +%sKB in %.3fs (len: %s)" % ((meminfo()[0] - m) / 1024, time.time() - s, len(piecefields[0].data)))
- m = meminfo()[0]
- s = time.time()
- for piecefield in list(piecefields.values()):
- val = piecefield[1000]
- print("Query one x10000: +%sKB in %.3fs" % ((meminfo()[0] - m) / 1024, time.time() - s))
- m = meminfo()[0]
- s = time.time()
- for piecefield in list(piecefields.values()):
- piecefield[1000] = b"\x01"
- print("Change one x10000: +%sKB in %.3fs" % ((meminfo()[0] - m) / 1024, time.time() - s))
- m = meminfo()[0]
- s = time.time()
- for piecefield in list(piecefields.values()):
- packed = piecefield.pack()
- print("Pack x10000: +%sKB in %.3fs (len: %s)" % ((meminfo()[0] - m) / 1024, time.time() - s, len(packed)))
- m = meminfo()[0]
- s = time.time()
- for piecefield in list(piecefields.values()):
- piecefield.unpack(packed)
- print("Unpack x10000: +%sKB in %.3fs (len: %s)" % ((meminfo()[0] - m) / 1024, time.time() - s, len(piecefields[0].data)))
- piecefields = {}
|