diff -r a359256acfc6 -r c8a366e56285 webengine/osswebengine/cache/src/HttpCachePostponeWriteUtilities.cpp --- a/webengine/osswebengine/cache/src/HttpCachePostponeWriteUtilities.cpp Thu Aug 27 07:44:59 2009 +0300 +++ b/webengine/osswebengine/cache/src/HttpCachePostponeWriteUtilities.cpp Thu Sep 24 12:53:48 2009 +0300 @@ -194,16 +194,17 @@ void CSegmentedHeapBuffer::AppendL(TInt& aRemainder, const TDesC8& aDes) { aRemainder = aDes.Length(); // consumed nothing yet. - TInt workingLen; - TInt workingOffset=0; // read position in source descriptor HBufC8* currentBuffer; + // 90% of cached objects are less than 4KB. + // Lots of them also come in two parts from the http stack. +#define HTTPSEGMENTEDBUFFER_OPTION_INCREMENT_GRADUALLY +#ifndef HTTPSEGMENTEDBUFFER_OPTION_INCREMENT_GRADUALLY TInt lastBuffer = iBufferList.Count()-1; if ( lastBuffer < 0 ) { // TODO: Make the first block only equal to the size of data we need? // Take some traces to see what happens. - // no blocks allocated. May leave here if we can't get space. currentBuffer = HBufC8::NewLC(iBufferSize); iBufferList.AppendL(currentBuffer); @@ -215,6 +216,8 @@ currentBuffer = iBufferList[lastBuffer]; } + TInt workingLen; + TInt workingOffset=0; // read position in source descriptor // here, currentBuffer always points to a buffer we can use. while ( aRemainder ) { @@ -236,6 +239,123 @@ CleanupStack::Pop(currentBuffer); } } +#else +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L("CHttpCacheSegmentedBuffer::AppendL %08x adding %d bytes to %d"), this, aRemainder, this->Length()); +#endif + // because most items are small, increment buffers up to the configured segment size as data is added... + TInt workingOffset = 0; + TInt lastBuffer = iBufferList.Count()-1; + if ( lastBuffer < 0 ) + { + // special case for first allocation. + // no blocks allocated. May leave here if we can't get space. + if( aRemainder <= iBufferSize) // we can fit the first block into a single segment + { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" First alloc %d into buffer fits inside %d"), aRemainder, iBufferSize ); +#endif + // fast path optimisation for first alloc into an empty segmented buffer. + currentBuffer = aDes.AllocLC(); + iBufferList.AppendL( currentBuffer ); + CleanupStack::Pop( currentBuffer ); + aRemainder = 0; + } + else + { + // the segmented buffer is empty and the first block to add is bigger than the configured block size + // fill the first segment and leave the rest for the loop +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" First alloc %d is bigger than %d"), aRemainder, iBufferSize ); +#endif + currentBuffer = HBufC8::NewLC( iBufferSize ); + iBufferList.AppendL( currentBuffer ); + CleanupStack::Pop( currentBuffer ); + currentBuffer->Des().Copy( aDes.Ptr(), iBufferSize ); + workingOffset = iBufferSize; // when we add the remaining data, we start from here. + aRemainder -= iBufferSize; + } + } + else + { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" Buffer already contains data")); +#endif + currentBuffer = iBufferList[lastBuffer]; + } + + // When we get to here the following state applies. + // currentBuffer points to an allocated and filled HBufC8 + // workingOffset tells us how far into the supplied descriptor the data we want is + // aRemainder tells us how much data is left to copy. + while( aRemainder ) + { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" %d bytes left to add to buffer"), aRemainder); +#endif + TInt possibleConsumptionInThisBlock = iBufferSize - currentBuffer->Length(); + if( possibleConsumptionInThisBlock == 0 ) + { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" Buffer cannot be extended.")); +#endif + // block cannot extend, alloc a new one + // the new one is either the correct length, or iBufferSize if aRemainder is too big. + TInt spaceToAlloc = aRemainder < iBufferSize ? aRemainder : iBufferSize; + currentBuffer = HBufC8::NewLC( spaceToAlloc ); + iBufferList.AppendL( currentBuffer ); + CleanupStack::Pop( currentBuffer ); + possibleConsumptionInThisBlock = spaceToAlloc; +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" New buffer of %d bytes allocated"), spaceToAlloc); +#endif + // fill the block as far as possible + currentBuffer->Des().Append( aDes.Mid( workingOffset, possibleConsumptionInThisBlock )); + workingOffset += possibleConsumptionInThisBlock; + aRemainder -= possibleConsumptionInThisBlock; + } + else + { + // block can extend + if( possibleConsumptionInThisBlock >= aRemainder ) + { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" Current buffer can be extended to hold all data.")); +#endif + // we can realloc this buffer big enough to hold all the remaining data. + currentBuffer = currentBuffer->ReAllocL( currentBuffer->Length() + aRemainder ); + CleanupStack::PushL( currentBuffer ); + iBufferList.Remove(iBufferList.Count()-1); + iBufferList.AppendL( currentBuffer ); + CleanupStack::Pop( currentBuffer ); + // copy the data + currentBuffer->Des().Append( aDes.Mid( workingOffset, aRemainder )); + aRemainder = 0; + } + else + { +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" Buffer cannot be extended to hold all data, consuming %d bytes."), possibleConsumptionInThisBlock); +#endif + // this buffer cannot extend to hold all the data. + // take as much as we can - we will allocate a new buffer next time around. + currentBuffer = currentBuffer->ReAllocL( currentBuffer->Length() + possibleConsumptionInThisBlock ); + CleanupStack::PushL( currentBuffer ); + iBufferList.Remove(iBufferList.Count()-1); + iBufferList.AppendL( currentBuffer ); + CleanupStack::Pop( currentBuffer ); + // copy the data + currentBuffer->Des().Append( aDes.Mid( workingOffset, possibleConsumptionInThisBlock )); + // set up variables for next time around + workingOffset += possibleConsumptionInThisBlock; + aRemainder -= possibleConsumptionInThisBlock; + } + } + } +#endif +#ifdef __CACHELOG__ + HttpCacheUtil::WriteFormatLog(0, _L(" exiting AppendL. Segmented buffer now contains %d bytes"), this->Length()); +#endif // will only exit here if we consumed all data } @@ -350,7 +470,7 @@ // ----------------------------------------------------------------------------- // CHttpCacheWriteTimeout::CHttpCacheWriteTimeout( const TInt aTimeout ) - : CActive(EPriorityStandard), + : CActive(EPriorityIdle), iTimeout(aTimeout) // Standard priority { }