improved performance of ByteCountCoding<> decode

This commit is contained in:
ZappoMan 2015-07-08 17:32:51 -07:00
parent 6a9344a3f6
commit e885ac1821
4 changed files with 123 additions and 39 deletions

View file

@ -1014,6 +1014,7 @@ void Application::paintGL() {
void Application::runTests() {
runTimingTests();
//runUnitTests();
}
void Application::audioMuteToggled() {

View file

@ -21,6 +21,7 @@
#include <QThread>
#include <ByteCountCoding.h>
#include <SharedUtil.h>
#include <TextRenderer.h>
@ -229,6 +230,43 @@ void runTimingTests() {
elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC;
qCDebug(interfaceapp, "vec3 assign and dot() usecs: %f, last result:%f",
(double)(elapsedUsecs / numTests), (double)result);
quint64 BYTE_CODE_MAX_VALUE = 99999999;
quint64 BYTE_CODE_TESTS_SKIP = 999;
QByteArray extraJunk;
const int EXTRA_JUNK_SIZE = 200;
extraJunk.append((unsigned char)255);
for (int i = 0; i < EXTRA_JUNK_SIZE; i++) {
extraJunk.append(QString("junk"));
}
{
startTime.start();
quint64 tests = 0;
quint64 failed = 0;
for (quint64 value = 0; value < BYTE_CODE_MAX_VALUE; value += BYTE_CODE_TESTS_SKIP) {
quint64 valueA = value; // usecTimestampNow();
ByteCountCoded<quint64> codedValueA = valueA;
QByteArray codedValueABuffer = codedValueA;
codedValueABuffer.append(extraJunk);
ByteCountCoded<quint64> decodedValueA;
decodedValueA.decode(codedValueABuffer);
quint64 valueADecoded = decodedValueA;
tests++;
if (valueA != valueADecoded) {
qDebug() << "FAILED! value:" << valueA << "decoded:" << valueADecoded;
failed++;
}
}
elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC;
qCDebug(interfaceapp) << "ByteCountCoded<quint64> usecs: " << elapsedUsecs
<< "per test:" << (double) (elapsedUsecs / tests)
<< "tests:" << tests
<< "failed:" << failed;
}
}
bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNormalizedDirection,
@ -271,3 +309,37 @@ bool pointInSphere(glm::vec3& point, glm::vec3& sphereCenter, double sphereRadiu
}
return false;
}
void runUnitTests() {
quint64 LAST_TEST = 10;
quint64 SKIP_BY = 1;
for (quint64 value = 0; value <= LAST_TEST; value += SKIP_BY) {
qDebug() << "value:" << value;
ByteCountCoded<quint64> codedValue = value;
QByteArray codedValueBuffer = codedValue;
codedValueBuffer.append((unsigned char)255);
codedValueBuffer.append(QString("junk"));
qDebug() << "codedValueBuffer:";
outputBufferBits((const unsigned char*)codedValueBuffer.constData(), codedValueBuffer.size());
ByteCountCoded<quint64> valueDecoder = codedValueBuffer;
quint64 valueDecoded = valueDecoder;
qDebug() << "valueDecoded:" << valueDecoded;
if (value == valueDecoded) {
qDebug() << "SUCCESS!";
} else {
qDebug() << "FAILED!";
}
}
}

View file

@ -30,6 +30,7 @@ void drawText(int x, int y, float scale, float radians, int mono,
void renderCollisionOverlay(int width, int height, float magnitude, float red = 0, float blue = 0, float green = 0);
void runTimingTests();
void runUnitTests();
bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNormalizedDirection,
const glm::vec3& sphereCenter, float sphereRadius, float& distance);

View file

@ -26,6 +26,8 @@
#include <QBitArray>
#include <QByteArray>
#include "SharedUtil.h"
#include "NumericalConstants.h"
template<typename T> class ByteCountCoded {
@ -40,6 +42,7 @@ public:
QByteArray encode() const;
void decode(const QByteArray& fromEncoded);
void decode(const char* encodedBuffer, int encodedSize);
bool operator==(const ByteCountCoded& other) const { return data == other.data; }
bool operator!=(const ByteCountCoded& other) const { return data != other.data; }
@ -113,50 +116,57 @@ template<typename T> inline QByteArray ByteCountCoded<T>::encode() const {
}
template<typename T> inline void ByteCountCoded<T>::decode(const QByteArray& fromEncodedBytes) {
// first convert the ByteArray into a BitArray...
QBitArray encodedBits;
int bitCount = BITS_IN_BYTE * fromEncodedBytes.count();
encodedBits.resize(bitCount);
// copies the QByteArray into a QBitArray
for(int byte = 0; byte < fromEncodedBytes.count(); byte++) {
char originalByte = fromEncodedBytes.at(byte);
for(int bit = 0; bit < BITS_IN_BYTE; bit++) {
int shiftBy = BITS_IN_BYTE - (bit + 1);
char maskBit = ( 1 << shiftBy);
bool bitValue = originalByte & maskBit;
encodedBits.setBit(byte * BITS_IN_BYTE + bit, bitValue);
}
}
// next, read the leading bits to determine the correct number of bytes to decode (may not match the QByteArray)
decode(fromEncodedBytes.constData(), fromEncodedBytes.size());
}
template<typename T> inline void ByteCountCoded<T>::decode(const char* encodedBuffer, int encodedSize) {
data = 0; // reset data
int bitCount = BITS_IN_BYTE * encodedSize;
int encodedByteCount = 1; // there is at least 1 byte (after the leadBits)
int leadBits = 1; // there is always at least 1 lead bit
int bitAt;
for (bitAt = 0; bitAt < bitCount; bitAt++) {
if (encodedBits.at(bitAt)) {
encodedByteCount++;
leadBits++;
} else {
break;
}
}
int expectedBitCount = (encodedByteCount * BITS_IN_BYTE) - leadBits;
T value = 0;
if (expectedBitCount <= (encodedBits.size() - leadBits)) {
// Now, keep reading...
int valueStartsAt = bitAt + 1;
T bitValue = 1;
for (bitAt = valueStartsAt; bitAt < (expectedBitCount + leadBits); bitAt++) {
if(encodedBits.at(bitAt)) {
value += bitValue;
bool inLeadBits = true;
int bitAt = 0;
int expectedBitCount; // unknown at this point
int lastValueBit;
T bitValue = 1;
for(int byte = 0; byte < encodedSize; byte++) {
char originalByte = encodedBuffer[byte];
unsigned char maskBit = 128;
for(int bit = 0; bit < BITS_IN_BYTE; bit++) {
//int shiftBy = BITS_IN_BYTE - (bit + 1);
//char maskBit = (1 << shiftBy);
bool bitIsSet = originalByte & maskBit;
// Processing of the lead bits
if (inLeadBits) {
if (bitIsSet) {
encodedByteCount++;
leadBits++;
} else {
inLeadBits = false; // once we hit our first 0, we know we're out of the lead bits
expectedBitCount = (encodedByteCount * BITS_IN_BYTE) - leadBits;
lastValueBit = expectedBitCount + bitAt;
// check to see if the remainder of our buffer is sufficient
if (expectedBitCount > (bitCount - leadBits)) {
break;
}
}
} else {
if (bitAt > lastValueBit) {
break;
}
if(bitIsSet) {
data += bitValue;
}
bitValue *= 2;
}
bitValue *= 2;
bitAt++;
maskBit = maskBit >> 1;
}
}
data = value;
}
#endif // hifi_ByteCountCoding_h