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
@@ -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);
});
}
@@ -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;
};
@@ -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">
@@ -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.