On Thu, Aug 11, 2016 at 09:18:34PM +0900, Oleg Endo wrote: > On Wed, 2016-08-10 at 21:31 -0400, Trevor Saunders wrote: > > > > > Well, I'd say the compromises made in std::string make it pretty > > terrible for general purpose use accept where perf and memory doesn't > > matter at all. > > > > std::vector isn't very great size wise either, imho the size / > > capacity fields would be much better put in the buffer than in the > > struct itself, to save 2 * sizeof (void *) in sizeof std::vector. > > There's nothing in the standard that says those fields have to go into > the vector struct/class itself and not into the data buffer. It just > happens to be the way it's implemented in libstdc++. E.g. libc++ > implements some things in different ways to save a few bytes here and > there. > > It looks more practical to put those fields into the container itself, > otherwise you'd have to do a nullptr check every time you access the > size field etc. Although newer compilers optimize away the redundant > nullptr checks, older compilers (which GCC wants to be good with) might > not do it. In any case, it seems to generate slightly bigger code, at > least in one instance (see attachment).
if you are clever you can have a empty global vector that you point all the empty vectors at and so eliminate the null check. Well, I guess that doesn't work quite as well if the global needs to be accessed through a plt sigh, but at least you only need to check against it for reallocation which is rather heavy weight anyway. > Anyway, normally there is more data in the vectors than there are > vectors around, so whether sizeof (vector) is 8 or 24 bytes doesn't > matter. It matters if you have any empty vectors around. The only numbers I can find are https://bugzilla.mozilla.org/show_bug.cgi?id=1007846 but I seem to remember seeing that for Firefox at least most vectors contained 0 elements. > > > > or just having your stack_string type convert to the normal string > > type so that you can pass mutable references. > > But that would imply copying, wouldn't it? Not if you are clever, you can use the same trick gcc uses in vec / auto_vec with strings. Trev > > Cheers, > Oleg > > #if 0 > template <typename T> > class vector > { > public: > unsigned int size (void) const { return m_buffer != nullptr ? > m_buffer->size : 0; } > bool empty (void) const { return size () == 0; } > > unsigned int capacity (void) const { return m_buffer != nullptr ? > m_buffer->capacity : 0; } > > T* data (void) { return (T*)(m_buffer + 1); } > const T* data (void) const { return (const T*)(m_buffer + 1); } > > T& operator [] (unsigned int i) { return data ()[i]; } > const T& operator [] (unsigned int i) const { return data ()[i]; } > > private: > struct buffer_header > { > unsigned int size; > unsigned int capacity; > }; > > buffer_header* m_buffer; > }; > > > int foo (const vector<int>& x) > { > if (x.empty ()) > return 0; > > int r = 0; > for (unsigned int i = 0; i < x.size (); ++i) > r += x[i]; > > return r; > } > > /* > -O2 -m2a > mov.l @r4,r2 > tst r2,r2 > bt .L5 > mov.l @r2,r1 > tst r1,r1 > bt.s .L5 > shll2 r1 > add #-4,r1 > shlr2 r1 > add #8,r2 > mov #0,r0 > add #1,r1 > .align 2 > .L3: > mov.l @r2+,r3 > dt r1 > bf.s .L3 > add r3,r0 > rts/n > .align 1 > .L5: > rts > mov #0,r0 > */ > #endif > > > #if 1 > > template <typename T> > class vector > { > public: > unsigned int size (void) const { return m_size; } > bool empty (void) const { return size () == 0; } > > unsigned int capacity (void) const { return m_capacity; } > > T* data (void) { return (T*)(m_buffer); } > const T* data (void) const { return (const T*)(m_buffer); } > > T& operator [] (unsigned int i) { return data ()[i]; } > const T& operator [] (unsigned int i) const { return data ()[i]; } > > private: > unsigned int m_size; > unsigned int m_capacity; > T* m_buffer; > }; > > > int foo (const vector<int>& x) > { > if (x.empty ()) > return 0; > > int r = 0; > for (unsigned int i = 0; i < x.size (); ++i) > r += x[i]; > > return r; > } > > /* > -O2 -m2a > mov.l @r4,r1 > tst r1,r1 > bt.s .L7 > mov #0,r0 > shll2 r1 > mov.l @(8,r4),r2 > add #-4,r1 > shlr2 r1 > add #1,r1 > .align 2 > .L3: > mov.l @r2+,r3 > dt r1 > bf.s .L3 > add r3,r0 > .L7: > rts/n > */ > > #endif >