I have this very big vector<unsigned char> bitmap
that I use as a bitmap. Most of time it has like millions or billions of entries. So every bit in a unsigned char stands for a free(0) or used(1) block in my program. My function to set those bits looks like this:
int setNextFreeIDX_In(std::vector<unsigned char> & bitmap){
for(int i=0; i<bitmap.size(); i++){
for(int bit=0; bit<8; bit++){
if(!(bitmap[i] & (1 << bit))){ //72.33% <- this is what the Xcode Profile says
turnOn(bit, bitmap[i]);
return (i*8) + bit;
}
}
}
return -1;
}
So after profiling my Code with Xcode instruments, it says that this function takes a lot of time. (about 25 minutes! when working with about 4.5 gb of blocks and every block is 4096 bytes)
do you see anything that could take that much time. Or maybe there is a better way to do this!?
I already tried to do this with the iterator instead of for(int i....
but it still takes a lot of time. Here is my turnOn function:
void turnOn(int bitNumber, unsigned char & byte){ //75.00% <- Profiler says this
byte |= 0x01 << bitNumber; //turn on the N-th bit
}
2
Answers
So i simply solved this by adding a static var
int lastSettedBlockIDX
this helps me to jump right at the last setted bit. Chances are high that the next bit would be 0 so I don't have to loop through all idx´s anymore. Still there could be cases where iterating through the whole list would be necessary. For example after there are unsetted bits in the middle and setted bits in the end of the list. So I will take a closer look @Surt answer later if this Problem appears. Thx a lot.!An O(N) solution is not really good, maybe we can let us inspire by van Emde Boas tree but a bit simpler and reduce that to O(sqrt(N))
if we take the SqrtN = sqrt of N (rounded up) and makes that many indexes of
Warning: totally untested concept code
Further speed improvements should be possible by using 64-bit numbers instead of bytes and using either C++20 bit-header or some buildin bit manipulation, i64 has single instructions to do that in O(1).