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:
parent
f630228599
commit
99dd6b8a03
@ -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,...) {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user