From c62a807eb3781d4bce358edb7e6bb99f1e6e540e Mon Sep 17 00:00:00 2001
From: Philippe Canal <pcanal@fnal.gov>
Date: Thu, 2 Jun 2011 21:16:27 +0000
Subject: [PATCH] Add the function TBuffer::AutoExpand to centralize the
 automatic buffer extension policy.  This enable the ability to tweak it later
 (for example instead of always doubling the size, increasing by only at most
 2Mb or take hints from the number of entries already in a TBasket).

git-svn-id: http://root.cern.ch/svn/root/trunk@39548 27541ba8-7e3a-0410-8455-c3a389f83636
---
 core/base/inc/TBuffer.h   |  1 +
 core/base/src/TBuffer.cxx | 21 ++++++++++++++++-
 io/io/inc/TBufferFile.h   | 26 ++++++++++-----------
 io/io/src/TBufferFile.cxx | 48 +++++++++++++++++++--------------------
 4 files changed, 58 insertions(+), 38 deletions(-)

diff --git a/core/base/inc/TBuffer.h b/core/base/inc/TBuffer.h
index c1f21fbc5ce..b1f78339a93 100644
--- a/core/base/inc/TBuffer.h
+++ b/core/base/inc/TBuffer.h
@@ -93,6 +93,7 @@ public:
    void     DetachBuffer() { fBuffer = 0; }
    Int_t    Length()     const { return (Int_t)(fBufCur - fBuffer); }
    void     Expand(Int_t newsize);  // expand buffer to newsize
+   void     AutoExpand(Int_t size_needed);  // expand buffer to newsize
 
    virtual Bool_t     CheckObject(const TObject *obj) = 0;
    virtual Bool_t     CheckObject(const void *obj, const TClass *ptrClass) = 0;
diff --git a/core/base/src/TBuffer.cxx b/core/base/src/TBuffer.cxx
index 6b12b2428f4..d562e8a2135 100644
--- a/core/base/src/TBuffer.cxx
+++ b/core/base/src/TBuffer.cxx
@@ -140,6 +140,25 @@ TBuffer::~TBuffer()
    fParent = 0;
 }
 
+
+//______________________________________________________________________________
+void TBuffer::AutoExpand(Int_t size_needed)
+{
+   // Automatically calculate a new size and expand the buffer to fit at least size_needed.
+   // The goals is to minimize the number of memory allocation and the memory allocation
+   // which avoiding too much memory wastage.
+   // If the size_needed is larger than the current size, the policy
+   // is to expand to double the current size or the size_needed which ever is largest.
+   
+   if (size_needed > fBufSize) {
+      if (size_needed > 2*fBufSize) {
+         Expand(size_needed);
+      } else {
+         Expand(2*fBufSize);
+      }
+   }
+}
+
 //______________________________________________________________________________
 void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
 {
@@ -182,7 +201,7 @@ void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t
 //______________________________________________________________________________
 void TBuffer::Expand(Int_t newsize)
 {
-   // Expand the I/O buffer to newsize bytes.
+   // Expand (or shrink) the I/O buffer to newsize bytes.
 
    Int_t l  = Length();
    if ( (fMode&kWrite)!=0 ) {
diff --git a/io/io/inc/TBufferFile.h b/io/io/inc/TBufferFile.h
index 251b11b8954..4fdb59699ee 100644
--- a/io/io/inc/TBufferFile.h
+++ b/io/io/inc/TBufferFile.h
@@ -321,91 +321,91 @@ public:
 //______________________________________________________________________________
 inline void TBufferFile::WriteBool(Bool_t b)
 {
-   if (fBufCur + sizeof(UChar_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(UChar_t) > fBufMax) AutoExpand(fBufSize+sizeof(UChar_t));
    tobuf(fBufCur, b);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteChar(Char_t c)
 {
-   if (fBufCur + sizeof(Char_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(Char_t) > fBufMax) AutoExpand(fBufSize+sizeof(Char_t));
    tobuf(fBufCur, c);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteUChar(UChar_t c)
 {
-   if (fBufCur + sizeof(UChar_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(UChar_t) > fBufMax) AutoExpand(fBufSize+sizeof(UChar_t));
    tobuf(fBufCur, (Char_t)c);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteShort(Short_t h)
 {
-   if (fBufCur + sizeof(Short_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(Short_t) > fBufMax) AutoExpand(fBufSize+sizeof(Short_t));
    tobuf(fBufCur, h);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteUShort(UShort_t h)
 {
-   if (fBufCur + sizeof(UShort_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(UShort_t) > fBufMax) AutoExpand(fBufSize+sizeof(UShort_t));
    tobuf(fBufCur, (Short_t)h);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteInt(Int_t i)
 {
-   if (fBufCur + sizeof(Int_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(Int_t) > fBufMax) AutoExpand(fBufSize+sizeof(Int_t));
    tobuf(fBufCur, i);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteUInt(UInt_t i)
 {
-   if (fBufCur + sizeof(UInt_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(UInt_t) > fBufMax) AutoExpand(fBufSize+sizeof(UInt_t));
    tobuf(fBufCur, (Int_t)i);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteLong(Long_t l)
 {
-   if (fBufCur + sizeof(Long_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(Long_t) > fBufMax) AutoExpand(fBufSize+sizeof(Long_t));
    tobuf(fBufCur, l);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteULong(ULong_t l)
 {
-   if (fBufCur + sizeof(ULong_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(ULong_t) > fBufMax) AutoExpand(fBufSize+sizeof(ULong_t));
    tobuf(fBufCur, (Long_t)l);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteLong64(Long64_t ll)
 {
-   if (fBufCur + sizeof(Long64_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(Long64_t) > fBufMax) AutoExpand(fBufSize+sizeof(Long64_t));
    tobuf(fBufCur, ll);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteULong64(ULong64_t ll)
 {
-   if (fBufCur + sizeof(ULong64_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(ULong64_t) > fBufMax) AutoExpand(fBufSize+sizeof(ULong64_t));
    tobuf(fBufCur, (Long64_t)ll);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteFloat(Float_t f)
 {
-   if (fBufCur + sizeof(Float_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(Float_t) > fBufMax) AutoExpand(fBufSize+sizeof(Float_t));
    tobuf(fBufCur, f);
 }
 
 //______________________________________________________________________________
 inline void TBufferFile::WriteDouble(Double_t d)
 {
-   if (fBufCur + sizeof(Double_t) > fBufMax) Expand(2*fBufSize);
+   if (fBufCur + sizeof(Double_t) > fBufMax) AutoExpand(fBufSize+sizeof(Double_t));
    tobuf(fBufCur, d);
 }
 
diff --git a/io/io/src/TBufferFile.cxx b/io/io/src/TBufferFile.cxx
index 4bc4f61db93..12eceed5531 100644
--- a/io/io/src/TBufferFile.cxx
+++ b/io/io/src/TBufferFile.cxx
@@ -1558,7 +1558,7 @@ void TBufferFile::WriteArray(const Bool_t *b, Int_t n)
    R__ASSERT(b);
 
    Int_t l = sizeof(UChar_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    if (sizeof(Bool_t) > 1) {
       for (int i = 0; i < n; i++)
@@ -1583,7 +1583,7 @@ void TBufferFile::WriteArray(const Char_t *c, Int_t n)
    R__ASSERT(c);
 
    Int_t l = sizeof(Char_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    memcpy(fBufCur, c, l);
    fBufCur += l;
@@ -1603,7 +1603,7 @@ void TBufferFile::WriteArray(const Short_t *h, Int_t n)
    R__ASSERT(h);
 
    Int_t l = sizeof(Short_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
 # ifdef USE_BSWAPCPY
@@ -1633,7 +1633,7 @@ void TBufferFile::WriteArray(const Int_t *ii, Int_t n)
    R__ASSERT(ii);
 
    Int_t l = sizeof(Int_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
 # ifdef USE_BSWAPCPY
@@ -1663,7 +1663,7 @@ void TBufferFile::WriteArray(const Long_t *ll, Int_t n)
    R__ASSERT(ll);
 
    Int_t l = 8*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
    for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
 }
 
@@ -1683,7 +1683,7 @@ void TBufferFile::WriteArray(const ULong_t *ll, Int_t n)
    R__ASSERT(ll);
 
    Int_t l = 8*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
    for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
 }
 
@@ -1701,7 +1701,7 @@ void TBufferFile::WriteArray(const Long64_t *ll, Int_t n)
    R__ASSERT(ll);
 
    Int_t l = sizeof(Long64_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
    for (int i = 0; i < n; i++)
@@ -1726,7 +1726,7 @@ void TBufferFile::WriteArray(const Float_t *f, Int_t n)
    R__ASSERT(f);
 
    Int_t l = sizeof(Float_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
 # ifdef USE_BSWAPCPY
@@ -1756,7 +1756,7 @@ void TBufferFile::WriteArray(const Double_t *d, Int_t n)
    R__ASSERT(d);
 
    Int_t l = sizeof(Double_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
    for (int i = 0; i < n; i++)
@@ -1782,7 +1782,7 @@ void TBufferFile::WriteArrayFloat16(const Float_t *f, Int_t n, TStreamerElement
    R__ASSERT(f);
 
    Int_t l = sizeof(Float_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    WriteFastArrayFloat16(f,n,ele);
 }
@@ -1802,7 +1802,7 @@ void TBufferFile::WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElemen
    R__ASSERT(d);
 
    Int_t l = sizeof(Float_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    WriteFastArrayDouble32(d,n,ele);
 }
@@ -1815,7 +1815,7 @@ void TBufferFile::WriteFastArray(const Bool_t *b, Int_t n)
    if (n <= 0) return;
 
    Int_t l = sizeof(UChar_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    if (sizeof(Bool_t) > 1) {
       for (int i = 0; i < n; i++)
@@ -1834,7 +1834,7 @@ void TBufferFile::WriteFastArray(const Char_t *c, Int_t n)
    if (n <= 0) return;
 
    Int_t l = sizeof(Char_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    memcpy(fBufCur, c, l);
    fBufCur += l;
@@ -1855,7 +1855,7 @@ void TBufferFile::WriteFastArrayString(const Char_t *c, Int_t n)
    if (n <= 0) return;
 
    Int_t l = sizeof(Char_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    memcpy(fBufCur, c, l);
    fBufCur += l;
@@ -1869,7 +1869,7 @@ void TBufferFile::WriteFastArray(const Short_t *h, Int_t n)
    if (n <= 0) return;
 
    Int_t l = sizeof(Short_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
 # ifdef USE_BSWAPCPY
@@ -1893,7 +1893,7 @@ void TBufferFile::WriteFastArray(const Int_t *ii, Int_t n)
    if (n <= 0) return;
 
    Int_t l = sizeof(Int_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
 # ifdef USE_BSWAPCPY
@@ -1917,7 +1917,7 @@ void TBufferFile::WriteFastArray(const Long_t *ll, Int_t n)
    if (n <= 0) return;
 
    Int_t l = 8*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
 }
@@ -1932,7 +1932,7 @@ void TBufferFile::WriteFastArray(const ULong_t *ll, Int_t n)
    if (n <= 0) return;
 
    Int_t l = 8*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
 }
@@ -1945,7 +1945,7 @@ void TBufferFile::WriteFastArray(const Long64_t *ll, Int_t n)
    if (n <= 0) return;
 
    Int_t l = sizeof(Long64_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
    for (int i = 0; i < n; i++)
@@ -1964,7 +1964,7 @@ void TBufferFile::WriteFastArray(const Float_t *f, Int_t n)
    if (n <= 0) return;
 
    Int_t l = sizeof(Float_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
 # ifdef USE_BSWAPCPY
@@ -1988,7 +1988,7 @@ void TBufferFile::WriteFastArray(const Double_t *d, Int_t n)
    if (n <= 0) return;
 
    Int_t l = sizeof(Double_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
 #ifdef R__BYTESWAP
    for (int i = 0; i < n; i++)
@@ -2008,7 +2008,7 @@ void TBufferFile::WriteFastArrayFloat16(const Float_t *f, Int_t n, TStreamerElem
    if (n <= 0) return;
 
    Int_t l = sizeof(Float_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    if (ele && ele->GetFactor()) {
       //A range is specified. We normalize the float to the range and
@@ -2059,7 +2059,7 @@ void TBufferFile::WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerEl
    if (n <= 0) return;
 
    Int_t l = sizeof(Float_t)*n;
-   if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
+   if (fBufCur + l > fBufMax) AutoExpand(fBufSize+l);
 
    if (ele && ele->GetFactor()) {
       //A range is specified. We normalize the double to the range and
@@ -3273,7 +3273,7 @@ void TBufferFile::WriteBuf(const void *buf, Int_t max)
 
    if (max == 0) return;
 
-   if (fBufCur + max > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+max));
+   if (fBufCur + max > fBufMax) AutoExpand(fBufSize+max); // a more precise request would be: fBufSize + max - (fBufMax - fBufCur)
 
    memcpy(fBufCur, buf, max);
    fBufCur += max;
-- 
GitLab