comparison OrthancFramework/Sources/ChunkedBuffer.cpp @ 4150:b56f3a37a4a1

optimization of ChunkedBuffer if many small chunks are added
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 19 Aug 2020 11:18:55 +0200
parents 732ad6c618ba
children 8c559dd5034b
comparison
equal deleted inserted replaced
4149:72047b61570f 4150:b56f3a37a4a1
30 namespace Orthanc 30 namespace Orthanc
31 { 31 {
32 void ChunkedBuffer::Clear() 32 void ChunkedBuffer::Clear()
33 { 33 {
34 numBytes_ = 0; 34 numBytes_ = 0;
35 pendingPos_ = 0;
35 36
36 for (Chunks::iterator it = chunks_.begin(); 37 for (Chunks::iterator it = chunks_.begin();
37 it != chunks_.end(); ++it) 38 it != chunks_.end(); ++it)
38 { 39 {
39 delete *it; 40 delete *it;
40 } 41 }
41 } 42 }
42 43
43 44
44 void ChunkedBuffer::AddChunk(const void* chunkData, 45 void ChunkedBuffer::AddChunkInternal(const void* chunkData,
45 size_t chunkSize) 46 size_t chunkSize)
46 { 47 {
47 if (chunkSize == 0) 48 if (chunkSize == 0)
48 { 49 {
49 return; 50 return;
50 } 51 }
51 else 52 else
52 { 53 {
53 assert(chunkData != NULL); 54 assert(chunkData != NULL);
54 chunks_.push_back(new std::string(reinterpret_cast<const char*>(chunkData), chunkSize)); 55 chunks_.push_back(new std::string(reinterpret_cast<const char*>(chunkData), chunkSize));
55 numBytes_ += chunkSize; 56 numBytes_ += chunkSize;
57 }
58 }
59
60
61 void ChunkedBuffer::FlushPendingBuffer()
62 {
63 assert(pendingPos_ <= pendingBuffer_.size());
64
65 if (!pendingBuffer_.empty())
66 {
67 AddChunkInternal(pendingBuffer_.c_str(), pendingPos_);
68 }
69 else
70 {
71 assert(pendingPos_ == 0);
72 }
73
74 pendingPos_ = 0;
75 }
76
77
78 ChunkedBuffer::ChunkedBuffer() :
79 numBytes_(0),
80 pendingPos_(0)
81 {
82 pendingBuffer_.resize(16 * 1024); // Default size of the pending buffer: 16KB
83 }
84
85
86 void ChunkedBuffer::SetPendingBufferSize(size_t size)
87 {
88 FlushPendingBuffer();
89 pendingBuffer_.resize(size);
90 }
91
92
93 void ChunkedBuffer::AddChunk(const void* chunkData,
94 size_t chunkSize)
95 {
96 if (chunkSize > 0)
97 {
98 #if 1
99 assert(sizeof(char) == 1);
100
101 // Optimization if Orthanc >= 1.7.3, to speed up in the presence of many small chunks
102 if (pendingPos_ + chunkSize <= pendingBuffer_.size())
103 {
104 // There remain enough place in the pending buffer
105 memcpy(&pendingBuffer_[pendingPos_], chunkData, chunkSize);
106 pendingPos_ += chunkSize;
107 }
108 else
109 {
110 FlushPendingBuffer();
111
112 if (!pendingBuffer_.empty() &&
113 chunkSize < pendingBuffer_.size())
114 {
115 memcpy(&pendingBuffer_[0], chunkData, chunkSize);
116 pendingPos_ = chunkSize;
117 }
118 else
119 {
120 AddChunkInternal(chunkData, chunkSize);
121 }
122 }
123 #else
124 // Non-optimized implementation in Orthanc <= 1.7.2
125 AddChunkInternal(chunkData, chunkSize);
126 #endif
56 } 127 }
57 } 128 }
58 129
59 130
60 void ChunkedBuffer::AddChunk(const std::string& chunk) 131 void ChunkedBuffer::AddChunk(const std::string& chunk)
78 } 149 }
79 150
80 151
81 void ChunkedBuffer::Flatten(std::string& result) 152 void ChunkedBuffer::Flatten(std::string& result)
82 { 153 {
154 FlushPendingBuffer();
83 result.resize(numBytes_); 155 result.resize(numBytes_);
84 156
85 size_t pos = 0; 157 size_t pos = 0;
86 for (Chunks::iterator it = chunks_.begin(); 158 for (Chunks::iterator it = chunks_.begin();
87 it != chunks_.end(); ++it) 159 it != chunks_.end(); ++it)