Permalink
Browse files

Implemented block pool for caching chunk allocations (dramatically re…

…duces page

fault count; performance gain ranges from 10% up to 50%...)
  • Loading branch information...
zeux committed Mar 5, 2012
1 parent 3a791e7 commit 4885f8a88dec0d8329b11d12692bd018f7051232
Showing with 84 additions and 12 deletions.
  1. +43 −0 src/blockpool.cpp
  2. +21 −0 src/blockpool.hpp
  3. +2 −0 src/qgrep.vcxproj
  4. +6 −0 src/qgrep.vcxproj.filters
  5. +12 −12 src/search.cpp
View
@@ -0,0 +1,43 @@
+#include "blockpool.hpp"
+
+#include <cassert>
+
+static char* pop(std::vector<char*>& v)
+{
+ char* r = v.back();
+ v.pop_back();
+ return r;
+}
+
+BlockPool::BlockPool(size_t blockSize): blockSize(blockSize), liveBlocks(0)
+{
+}
+
+BlockPool::~BlockPool()
+{
+ assert(liveBlocks == 0);
+
+ for (size_t i = 0; i < blocks.size(); ++i)
+ delete[] blocks[i];
+}
+
+std::shared_ptr<char> BlockPool::allocate(size_t size)
+{
+ if (size > blockSize)
+ return std::shared_ptr<char>(new char[size]);
+
+ std::lock_guard<std::mutex> lock(mutex);
+
+ char* block = blocks.empty() ? new char[blockSize] : pop(blocks);
+
+ liveBlocks++;
+
+ return std::shared_ptr<char>(block, [this](char* block) {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ assert(liveBlocks > 0);
+ liveBlocks--;
+
+ blocks.push_back(block);
+ });
+}
View
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <mutex>
+#include <vector>
+#include <memory>
+
+class BlockPool
+{
+public:
+ BlockPool(size_t blockSize);
+ ~BlockPool();
+
+ std::shared_ptr<char> allocate(size_t size);
+
+private:
+ size_t blockSize;
+
+ std::mutex mutex;
+ std::vector<char*> blocks;
+ size_t liveBlocks;
+};
View
@@ -109,6 +109,7 @@
<ClCompile Include="..\extern\re2\util\stringpiece.cc" />
<ClCompile Include="..\extern\re2\util\stringprintf.cc" />
<ClCompile Include="..\extern\re2\util\strutil.cc" />
+ <ClCompile Include="blockpool.cpp" />
<ClCompile Include="build.cpp" />
<ClCompile Include="fileutil.cpp" />
<ClCompile Include="init.cpp" />
@@ -132,6 +133,7 @@
<ClInclude Include="..\extern\re2\util\sparse_array.h" />
<ClInclude Include="..\extern\re2\util\sparse_set.h" />
<ClInclude Include="blockingqueue.hpp" />
+ <ClInclude Include="blockpool.hpp" />
<ClInclude Include="build.hpp" />
<ClInclude Include="constants.hpp" />
<ClInclude Include="fileutil.hpp" />
@@ -94,6 +94,9 @@
<ClCompile Include="orderedoutput.cpp">
<Filter>src</Filter>
</ClCompile>
+ <ClCompile Include="blockpool.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\extern\lz4\lz4.h">
@@ -165,6 +168,9 @@
<ClInclude Include="search.hpp">
<Filter>src</Filter>
</ClInclude>
+ <ClInclude Include="blockpool.hpp">
+ <Filter>src</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="src">
View
@@ -7,6 +7,7 @@
#include "regex.hpp"
#include "orderedoutput.hpp"
#include "constants.hpp"
+#include "blockpool.hpp"
#include <fstream>
#include <algorithm>
@@ -140,15 +141,15 @@ template <typename T> bool read(std::istream& in, T& value)
return read(in, &value, sizeof(T));
}
-char* safeAlloc(size_t size)
+std::shared_ptr<char> safeAlloc(BlockPool& pool, size_t size)
{
try
{
- return new char[size];
+ return pool.allocate(size);
}
catch (const std::bad_alloc&)
{
- return nullptr;
+ return std::shared_ptr<char>();
}
}
@@ -182,27 +183,26 @@ void searchProject(const char* file, const char* string, unsigned int options)
ChunkHeader chunk;
unsigned int chunkIndex = 0;
+ // Assume 50% compression ratio (it's usually much better)
+ BlockPool chunkPool(kChunkSize * 3 / 2);
WorkQueue queue(WorkQueue::getIdealWorkerCount(), kMaxQueuedChunkData);
while (read(in, chunk))
{
- char* compressed = safeAlloc(chunk.compressedSize);
- char* data = safeAlloc(chunk.uncompressedSize);
+ std::shared_ptr<char> data = safeAlloc(chunkPool, chunk.compressedSize + chunk.uncompressedSize);
- if (!compressed || !data || !read(in, compressed, chunk.compressedSize))
+ if (!data || !read(in, data.get(), chunk.compressedSize))
{
- delete[] compressed;
- delete[] data;
error("Error reading data file %s: malformed chunk\n", dataPath.c_str());
return;
}
queue.push([=, &regex, &output]() {
- LZ4_uncompress(compressed, data, chunk.uncompressedSize);
- delete[] compressed;
+ char* compressed = data.get();
+ char* uncompressed = data.get() + chunk.compressedSize;
- processChunk(regex.get(), &output, chunkIndex, data, chunk.fileCount);
- delete[] data;
+ LZ4_uncompress(compressed, uncompressed, chunk.uncompressedSize);
+ processChunk(regex.get(), &output, chunkIndex, uncompressed, chunk.fileCount);
}, chunk.compressedSize + chunk.uncompressedSize);
chunkIndex++;

0 comments on commit 4885f8a

Please sign in to comment.