For any variable you use, (pb)Lua internally needs 64bit (8 full bytes!) to handle it (see
The implementation of Lua 5.0 by
R. Ierusalimschy, L. H. de Figueiredo and W. Celes).
No matter if you only need a byte, a word or even a bit. Eight bytes, no less.
mBits helps saving a huge amount of memory by using an arbitrary bit-width for storage (1..32) in one (pb)Lua storage unit.
- 1/32 of mem needed for bit storage
- 1/16 of mem needed for 2-bit storage
- ...
- 1/2 of mem needed for word storage
Regarding the overhead, caused by the necessary routines, it only makes sense if you have large (n > ~200 = 1.6kB, native)
sums of data to store (a map, measured values, ...).
mBits uses a 2 dimensional table for storage to overcome the 2^n table rise problem:
The size of a table is always 2^n.
If you store the 129th value in a table its size will change from 128 to 256 (1024 to 2048 bytes).
If you store the 513th value, from 4096 bytes to 8192 bytes(!).
So the worst case is having e.g. 513 values in a table, which then occupies the same amount of memory as
1024 values would take (minus 1 ;-)!
To overcome this dramatic memory loss, I decided to use a 2 dimensional table, which will lessen the growth
of memory a little.
As of version 18a, pbLua supports (un)loading modules to save memory. Therefore I redesigned the original mBits version
to a version that does not need "nxt.math"...
Just set your bit width:
mBits.cBitWidth=<1..32>
Note:
Although it is possible, using a 32 bit width does not make sense ;-) Keep this below or equal 16...
Write values with:
mBits:set(<address>, <value>)
And read them back via:
mBits:get(<address>)
In all cases, make sure <value> does not exceed your chosen bit width and keep <address> positive...
-- mBits
-- Multiple bit storage class
--
-- Does not need nxt.math!
--
-- ASkr, 2009
mBits={}
mBits.cTabWidth=128 -- do not change!
mBits.cBitWidth=9 -- bit width to store (1, 2, 3, .. 32)
function mBits:set(address,value)
local row=(address/self.cTabWidth)+1
local col=1+(address%self.cTabWidth)/(32/self.cBitWidth)
local ind=address%(32/self.cBitWidth)
local val
if self[row]==nil then
self[row]={}
end
if self[row][col]==nil then
self[row][col]=0
end
val=self[row][col]*2^(32-mBits.cBitWidth-(ind*mBits.cBitWidth))
if val < 0 then
val=(val-0x80000000)/(2^(32-mBits.cBitWidth))
val=val+(2^(mBits.cBitWidth-1))
else
val=val/(2^(32-mBits.cBitWidth))
end
val=self[row][col]-val*(2^(mBits.cBitWidth*ind))
self[row][col]=val+value*(2^(mBits.cBitWidth*ind))
end
function mBits:get(address,value)
local row=(address/self.cTabWidth)+1
local col=1+(address%self.cTabWidth)/(32/self.cBitWidth)
local ind=address%(32/self.cBitWidth)
local val
val=self[row][col]*2^(32-mBits.cBitWidth-(ind*mBits.cBitWidth))
if val < 0 then
val=(val-0x80000000)/(2^(32-mBits.cBitWidth))
val=val+(2^(mBits.cBitWidth-1))
else
val=val/(2^(32-mBits.cBitWidth))
end
return val
end
|
ASkr 7/2009
Eine klitzekleine deutsche Version kann man hier finden.
|