summaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2020-01-11 17:47:44 +0100
committerGitHub <noreply@github.com>2020-01-11 17:47:44 +0100
commitb897bac08830142558b104ffcbc104b3ede755cd (patch)
tree10d1a2d725f84803b3f1420dbea60d31b867e558 /searchlib
parent5d77f9fe25dd5f143293d09e9086587d6b6a803e (diff)
parenteb90cf9114c07234eddfa2ae03369860e4e9a1d4 (diff)
Merge pull request #11749 from vespa-engine/balder/compact-buffer-after-compression
Balder/compact buffer after compression
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/tests/docstore/document_store/document_store_test.cpp9
-rw-r--r--searchlib/src/vespa/searchlib/docstore/value.cpp27
-rw-r--r--searchlib/src/vespa/searchlib/docstore/value.h1
3 files changed, 28 insertions, 9 deletions
diff --git a/searchlib/src/tests/docstore/document_store/document_store_test.cpp b/searchlib/src/tests/docstore/document_store/document_store_test.cpp
index f950377be4b..04ec18aacc4 100644
--- a/searchlib/src/tests/docstore/document_store/document_store_test.cpp
+++ b/searchlib/src/tests/docstore/document_store/document_store_test.cpp
@@ -142,6 +142,15 @@ TEST("require that Value can store zstd compressed data") {
verifyValue(S1, v);
}
+TEST("require that Value is shrunk to fit compressed data") {
+ Value v = createValue(S1, CompressionConfig::ZSTD);
+ EXPECT_EQUAL(CompressionConfig::ZSTD, v.getCompression());
+ EXPECT_EQUAL(128u, v.size());
+ EXPECT_EQUAL(128u, v.capacity());
+ EXPECT_EQUAL(297u, v.getUncompressedSize());
+ verifyValue(S1, v);
+}
+
TEST("require that Value can detect if output not equal to input") {
Value v = createValue(S1, CompressionConfig::NONE);
const_cast<uint8_t *>(static_cast<const uint8_t *>(v.get()))[8] ^= 0xff;
diff --git a/searchlib/src/vespa/searchlib/docstore/value.cpp b/searchlib/src/vespa/searchlib/docstore/value.cpp
index ea29c894cba..09725b447cd 100644
--- a/searchlib/src/vespa/searchlib/docstore/value.cpp
+++ b/searchlib/src/vespa/searchlib/docstore/value.cpp
@@ -42,6 +42,19 @@ Value::set(vespalib::DataBuffer &&buf, ssize_t len) {
set(std::move(buf), len, CompressionConfig());
}
+namespace {
+
+vespalib::alloc::Alloc
+compact(size_t sz, vespalib::alloc::Alloc buf) {
+ if (vespalib::roundUp2inN(sz) < vespalib::roundUp2inN(buf.size())) {
+ vespalib::alloc::Alloc shrunk = buf.create(sz);
+ memcpy(shrunk.get(), buf.get(), sz);
+ return shrunk;
+ }
+ return buf;
+}
+
+}
void
Value::set(vespalib::DataBuffer &&buf, ssize_t len, const CompressionConfig &compression) {
assert(len < std::numeric_limits<uint32_t>::max());
@@ -50,20 +63,16 @@ Value::set(vespalib::DataBuffer &&buf, ssize_t len, const CompressionConfig &com
vespalib::ConstBufferRef input(buf.getData(), len);
CompressionConfig::Type type = compress(compression, input, compressed, true);
_compressedSize = compressed.getDataLen();
+ _compression = type;
+ _uncompressedSize = len;
+ _uncompressedCrc = XXH64(input.c_str(), input.size(), 0);
+ _buf = std::make_shared<Alloc>(compact(_compressedSize,
+ (buf.getData() == compressed.getData()) ? buf.stealBuffer() : compressed.stealBuffer()));
- if (buf.getData() == compressed.getData()) {
- // Uncompressed so we can just steal the underlying buffer.
- _buf = std::make_shared<Alloc>(buf.stealBuffer());
- } else {
- _buf = std::make_shared<Alloc>(compressed.stealBuffer());
- }
assert(((type == CompressionConfig::NONE) &&
(len == ssize_t(_compressedSize))) ||
((type != CompressionConfig::NONE) &&
(len > ssize_t(_compressedSize))));
- _compression = type;
- _uncompressedSize = len;
- _uncompressedCrc = XXH64(input.c_str(), input.size(), 0);
}
Value::Result
diff --git a/searchlib/src/vespa/searchlib/docstore/value.h b/searchlib/src/vespa/searchlib/docstore/value.h
index f58d96e3e77..fb377abb2fb 100644
--- a/searchlib/src/vespa/searchlib/docstore/value.h
+++ b/searchlib/src/vespa/searchlib/docstore/value.h
@@ -42,6 +42,7 @@ public:
Result decompressed() const;
size_t size() const { return _compressedSize; }
+ size_t capacity() const { return _buf ? _buf->size() : 0; }
bool empty() const { return size() == 0; }
operator const void *() const { return get(); }
const void *get() const;