Mercurial > hg > orthanc
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) |