8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 22:03:03 +01:00

optimize string performance with the price of 4 additional bytes per string

This commit is contained in:
alexpeshkoff 2004-05-26 16:10:56 +00:00
parent f630228599
commit 99dd6b8a03
2 changed files with 66 additions and 60 deletions

View File

@ -118,8 +118,8 @@ namespace Firebird {
, __FILE__, __LINE__
#endif
);
x.newStorage[n] = 0;
return x.newStorage;
bigStorage[n] = 0;
return bigStorage;
}
AbstractString::pointer AbstractString::baseAppend(size_type n) {
@ -130,10 +130,10 @@ namespace Firebird {
#endif
);
if (x.oldStorage) {
memcpy(x.newStorage, x.oldStorage, x.oldSize);
memcpy(bigStorage, x.oldStorage, x.oldSize);
}
x.newStorage[length()] = 0;
return &x.newStorage[x.oldSize];
bigStorage[length()] = 0;
return &bigStorage[x.oldSize];
}
AbstractString::pointer AbstractString::baseInsert(size_type p0, size_type n) {
@ -147,16 +147,16 @@ namespace Firebird {
#endif
);
if (x.oldStorage) {
memcpy(x.newStorage, x.oldStorage, p0);
memcpy(&x.newStorage[p0 + n],
memcpy(bigStorage, x.oldStorage, p0);
memcpy(&bigStorage[p0 + n],
&x.oldStorage[p0], x.oldSize - p0);
}
else {
memmove(&x.newStorage[p0 + n], &x.newStorage[p0],
memmove(&bigStorage[p0 + n], &bigStorage[p0],
x.oldSize - p0);
}
x.newStorage[length()] = 0;
return &x.newStorage[p0];
bigStorage[length()] = 0;
return &bigStorage[p0];
}
void AbstractString::baseErase(size_type p0, size_type n) {
@ -168,18 +168,23 @@ namespace Firebird {
#endif
);
if (x.oldStorage) {
memcpy(x.newStorage, x.oldStorage, p0);
memcpy(&x.newStorage[p0], &x.oldStorage[p0 + n],
memcpy(bigStorage, x.oldStorage, p0);
memcpy(&bigStorage[p0], &x.oldStorage[p0 + n],
x.oldSize - (p0 + n));
}
else {
memmove(&x.newStorage[p0],
&x.newStorage[p0 + n], x.oldSize - (p0 + n));
memmove(&bigStorage[p0],
&bigStorage[p0 + n], x.oldSize - (p0 + n));
}
x.newStorage[length()] = 0;
bigStorage[length()] = 0;
}
/* void AbstractString::reserve(size_type n) {
/*
*** Firebird::string uses algorithm of freeing memory used by
*** very long strings, when length of string becomes MUCH smaller.
*** Obviously, it conflicts with reserve() STL-like method.
*** Therefore - no implementation for a while.
void AbstractString::reserve(size_type n) {
if (n <= actualSize) {
return;
}
@ -195,9 +200,9 @@ namespace Firebird {
forced = n;
}
if (x.oldStorage) {
memcpy(x.newStorage, x.oldStorage, l);
memcpy(bigStorage, x.oldStorage, l);
}
x.newStorage[l] = 0;
bigStorage[l] = 0;
}*/
void AbstractString::resize(size_type n, char_type c) {
@ -211,12 +216,12 @@ namespace Firebird {
#endif
);
if (x.oldStorage) {
memcpy(x.newStorage, x.oldStorage, n < x.oldSize ? n : x.oldSize);
memcpy(bigStorage, x.oldStorage, n < x.oldSize ? n : x.oldSize);
}
if (n > x.oldSize) {
memset(&x.newStorage[x.oldSize], c, n - x.oldSize);
memset(&bigStorage[x.oldSize], c, n - x.oldSize);
}
x.newStorage[n] = 0;
bigStorage[n] = 0;
}
AbstractString::size_type AbstractString::rfind(const_pointer s, size_type pos) const {
@ -373,12 +378,12 @@ namespace Firebird {
#endif
);
if (x.oldStorage) {
memcpy(x.newStorage, b, NewLength);
memcpy(bigStorage, b, NewLength);
}
else if (b != x.newStorage) {
memmove(x.newStorage, b, NewLength);
else if (b != bigStorage) {
memmove(bigStorage, b, NewLength);
}
x.newStorage[NewLength] = 0;
bigStorage[NewLength] = 0;
}
void AbstractString::printf(const char* format,...) {

View File

@ -54,13 +54,8 @@ namespace Firebird
static const size_type npos;
enum {smallStorageSize = 32, reserveSize = 16, keepSize = 512};
protected:
union {
char_type smallStorage[smallStorageSize];
// BRS 14/05/04: ISO C++ doesn't allow anonymous struct inside anonymous union
// struct {
char_type* bigStorage;
// };
};
char_type smallStorage[smallStorageSize];
char_type* bigStorage;
unsigned short userSize, actualSize;
private:
inline void checkPos(size_type pos) const {
@ -96,33 +91,37 @@ namespace Firebird
inline pointer createStorage(size_type uSize) {
checkSize(uSize);
userSize = uSize;
if (uSize < smallStorageSize) {
if (uSize < smallStorageSize)
{
actualSize = smallStorageSize;
smallStorage[uSize] = 0;
return smallStorage;
bigStorage = smallStorage;
}
allocateStorage(uSize
else
{
allocateStorage(uSize
#ifdef DEV_BUILD
, __FILE__, __LINE__
, __FILE__, __LINE__
#endif
);
);
}
bigStorage[uSize] = 0;
return bigStorage;
}
// Returns (possibly reallocated) newStorage for current string,
// setting values for oldStorage (if string is not
// updated inplace) and oldSize. oldStorage
// should be released after use if oldSize >= smallStorageSize
// Temporary structure returned by openStorage()
struct StoragePair {
pointer newStorage, oldStorage;
pointer oldStorage;
size_type oldSize;
char_type oldSmallStorage[smallStorageSize];
~StoragePair() {
if (oldSize >= AbstractString::smallStorageSize)
delete[] oldStorage;
}
};
friend struct StoragePair;
// Creates (possibly reallocated) bigStorage for new string.
// Sets values for oldStorage
// (if string is not updated inplace) and oldSize.
// oldStorage will be released in StoragePair's destructor.
inline void openStorage(StoragePair& rc, size_type newSize
#ifdef DEV_BUILD
, const char *file, int line
@ -132,36 +131,37 @@ namespace Firebird
rc.oldStorage = 0;
rc.oldSize = userSize;
userSize = newSize;
if (newSize < smallStorageSize) {
if (actualSize > smallStorageSize) {
// new string fits into smallStorage
if (newSize < smallStorageSize)
{
// old bigStorage should be deallocated
if (actualSize > smallStorageSize)
{
rc.oldStorage = bigStorage;
}
rc.newStorage = smallStorage;
bigStorage = smallStorage;
actualSize = smallStorageSize;
return;
}
// size change was small enough not to reallocate memory
if (newSize < actualSize && newSize + keepSize > actualSize) {
rc.newStorage = bigStorage;
return;
}
if (actualSize <= smallStorageSize) {
memcpy(rc.oldSmallStorage, smallStorage, rc.oldSize);
rc.oldStorage = rc.oldSmallStorage;
}
else {
rc.oldStorage = bigStorage;
}
// do memory reallocation
rc.oldStorage = bigStorage;
allocateStorage(newSize
#ifdef DEV_BUILD
, file, line
#endif
);
rc.newStorage = bigStorage;
}
// Returns pointer to current storage.
inline pointer getStorage() {
return actualSize <= smallStorageSize ?
smallStorage : bigStorage;
return bigStorage;
}
protected:
AbstractString(size_type sizeL, const_pointer datap);
@ -169,12 +169,14 @@ namespace Firebird
const_pointer p2, size_type n2);
AbstractString(const AbstractString& v);
inline AbstractString() {
bigStorage = smallStorage;
actualSize = smallStorageSize;
userSize = 0;
smallStorage[0] = 0;
}
AbstractString(size_type sizeL, char_type c);
inline explicit AbstractString(MemoryPool& p) : AutoStorage(p) {
bigStorage = smallStorage;
actualSize = smallStorageSize;
userSize = 0;
smallStorage[0] = 0;
@ -202,8 +204,7 @@ namespace Firebird
void baseTrim(TrimType WhereTrim, const_pointer ToTrim);
public:
inline const_pointer c_str() const {
return actualSize <= smallStorageSize ?
smallStorage : bigStorage;
return bigStorage;
}
inline size_type length() const {
return userSize;