Make compression options configurable. These include window-bits, level and strategy for ZlibCompression

Summary: Leveldb currently uses windowBits=-14 while using zlib compression.(It was earlier 15). This makes the setting configurable. Related changes here: https://reviews.facebook.net/D6105

Test Plan: make all check

Reviewers: dhruba, MarkCallaghan, sheki, heyongqiang

Differential Revision: https://reviews.facebook.net/D6393
main
amayank 12 years ago
parent 3096fa7534
commit 854c66b089
  1. 7
      db/c.cc
  2. 1
      db/c_test.c
  3. 15
      db/db_bench.cc
  4. 50
      db/db_test.cc
  5. 16
      include/leveldb/options.h
  6. 18
      port/port_posix.h
  7. 9
      table/table_builder.cc
  8. 10
      table/table_test.cc
  9. 6
      util/options.cc

@ -502,6 +502,13 @@ void leveldb_options_set_compression(leveldb_options_t* opt, int t) {
opt->rep.compression = static_cast<CompressionType>(t); opt->rep.compression = static_cast<CompressionType>(t);
} }
void leveldb_options_set_compression_options(
leveldb_options_t* opt, int w_bits, int level, int strategy) {
opt->rep.compression_opts.window_bits = w_bits;
opt->rep.compression_opts.level = level;
opt->rep.compression_opts.strategy = strategy;
}
void leveldb_options_set_disable_data_sync( void leveldb_options_set_disable_data_sync(
leveldb_options_t* opt, bool disable_data_sync) { leveldb_options_t* opt, bool disable_data_sync) {
opt->rep.disableDataSync = disable_data_sync; opt->rep.disableDataSync = disable_data_sync;

@ -187,6 +187,7 @@ int main(int argc, char** argv) {
leveldb_options_set_block_size(options, 1024); leveldb_options_set_block_size(options, 1024);
leveldb_options_set_block_restart_interval(options, 8); leveldb_options_set_block_restart_interval(options, 8);
leveldb_options_set_compression(options, leveldb_no_compression); leveldb_options_set_compression(options, leveldb_no_compression);
leveldb_options_set_compression_options(options, -14, -1, 0);
roptions = leveldb_readoptions_create(); roptions = leveldb_readoptions_create();
leveldb_readoptions_set_verify_checksums(roptions, 1); leveldb_readoptions_set_verify_checksums(roptions, 1);

@ -509,15 +509,18 @@ class Benchmark {
switch (FLAGS_compression_type) { switch (FLAGS_compression_type) {
case kSnappyCompression: case kSnappyCompression:
result = port::Snappy_Compress(text, strlen(text), &compressed); result = port::Snappy_Compress(Options().compression_opts, text,
strlen(text), &compressed);
name = "Snappy"; name = "Snappy";
break; break;
case kZlibCompression: case kZlibCompression:
result = port::Zlib_Compress(text, strlen(text), &compressed); result = port::Zlib_Compress(Options().compression_opts, text,
strlen(text), &compressed);
name = "Zlib"; name = "Zlib";
break; break;
case kBZip2Compression: case kBZip2Compression:
result = port::BZip2_Compress(text, strlen(text), &compressed); result = port::BZip2_Compress(Options().compression_opts, text,
strlen(text), &compressed);
name = "BZip2"; name = "BZip2";
break; break;
} }
@ -855,7 +858,8 @@ class Benchmark {
bool ok = true; bool ok = true;
std::string compressed; std::string compressed;
while (ok && bytes < 1024 * 1048576) { // Compress 1G while (ok && bytes < 1024 * 1048576) { // Compress 1G
ok = port::Snappy_Compress(input.data(), input.size(), &compressed); ok = port::Snappy_Compress(Options().compression_opts, input.data(),
input.size(), &compressed);
produced += compressed.size(); produced += compressed.size();
bytes += input.size(); bytes += input.size();
thread->stats.FinishedSingleOp(NULL); thread->stats.FinishedSingleOp(NULL);
@ -876,7 +880,8 @@ class Benchmark {
RandomGenerator gen; RandomGenerator gen;
Slice input = gen.Generate(Options().block_size); Slice input = gen.Generate(Options().block_size);
std::string compressed; std::string compressed;
bool ok = port::Snappy_Compress(input.data(), input.size(), &compressed); bool ok = port::Snappy_Compress(Options().compression_opts, input.data(),
input.size(), &compressed);
int64_t bytes = 0; int64_t bytes = 0;
char* uncompressed = new char[input.size()]; char* uncompressed = new char[input.size()];
while (ok && bytes < 1024 * 1048576) { // Compress 1G while (ok && bytes < 1024 * 1048576) { // Compress 1G

@ -20,22 +20,22 @@
namespace leveldb { namespace leveldb {
static bool SnappyCompressionSupported() { static bool SnappyCompressionSupported(const CompressionOptions& options) {
std::string out; std::string out;
Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
return port::Snappy_Compress(in.data(), in.size(), &out); return port::Snappy_Compress(options, in.data(), in.size(), &out);
} }
static bool ZlibCompressionSupported() { static bool ZlibCompressionSupported(const CompressionOptions& options) {
std::string out; std::string out;
Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
return port::Zlib_Compress(in.data(), in.size(), &out); return port::Zlib_Compress(options, in.data(), in.size(), &out);
} }
static bool BZip2CompressionSupported() { static bool BZip2CompressionSupported(const CompressionOptions& options) {
std::string out; std::string out;
Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
return port::BZip2_Compress(in.data(), in.size(), &out); return port::BZip2_Compress(options, in.data(), in.size(), &out);
} }
static std::string RandomString(Random* rnd, int len) { static std::string RandomString(Random* rnd, int len) {
@ -1105,22 +1105,25 @@ void MinLevelHelper(DBTest* self, Options& options) {
ASSERT_EQ(self->NumTableFilesAtLevel(1), 1); ASSERT_EQ(self->NumTableFilesAtLevel(1), 1);
} }
TEST(DBTest, MinLevelToCompress) { void MinLevelToCompress(CompressionType& type, Options& options, int wbits,
Options options = CurrentOptions(); int lev, int strategy) {
fprintf(stderr, "Test with compression options : window_bits = %d, level = %d
, strategy = %d}\n", wbits, lev, strategy);
options.write_buffer_size = 100<<10; //100KB options.write_buffer_size = 100<<10; //100KB
options.num_levels = 3; options.num_levels = 3;
options.max_mem_compaction_level = 0; options.max_mem_compaction_level = 0;
options.level0_file_num_compaction_trigger = 3; options.level0_file_num_compaction_trigger = 3;
options.create_if_missing = true; options.create_if_missing = true;
CompressionType type;
if (SnappyCompressionSupported()) { if (SnappyCompressionSupported(CompressionOptions(wbits, lev, strategy))) {
type = kSnappyCompression; type = kSnappyCompression;
fprintf(stderr, "using snappy\n"); fprintf(stderr, "using snappy\n");
} else if (ZlibCompressionSupported()) { } else if (ZlibCompressionSupported(
CompressionOptions(wbits, lev, strategy))) {
type = kZlibCompression; type = kZlibCompression;
fprintf(stderr, "using zlib\n"); fprintf(stderr, "using zlib\n");
} else if (BZip2CompressionSupported()) { } else if (BZip2CompressionSupported(
CompressionOptions(wbits, lev, strategy))) {
type = kBZip2Compression; type = kBZip2Compression;
fprintf(stderr, "using bzip2\n"); fprintf(stderr, "using bzip2\n");
} else { } else {
@ -1136,6 +1139,29 @@ TEST(DBTest, MinLevelToCompress) {
for (int i = 1; i < options.num_levels; i++) { for (int i = 1; i < options.num_levels; i++) {
options.compression_per_level[i] = type; options.compression_per_level[i] = type;
} }
}
TEST(DBTest, MinLevelToCompress1) {
Options options = CurrentOptions();
CompressionType type;
MinLevelToCompress(type, options, -14, -1, 0);
Reopen(&options);
MinLevelHelper(this, options);
// do not compress L0 and L1
for (int i = 0; i < 2; i++) {
options.compression_per_level[i] = kNoCompression;
}
for (int i = 2; i < options.num_levels; i++) {
options.compression_per_level[i] = type;
}
DestroyAndReopen(&options);
MinLevelHelper(this, options);
}
TEST(DBTest, MinLevelToCompress2) {
Options options = CurrentOptions();
CompressionType type;
MinLevelToCompress(type, options, 15, -1, 0);
Reopen(&options); Reopen(&options);
MinLevelHelper(this, options); MinLevelHelper(this, options);

@ -32,6 +32,19 @@ enum CompressionType {
kBZip2Compression = 0x3 kBZip2Compression = 0x3
}; };
// Compression options for different compression algorithms like Zlib
struct CompressionOptions {
int window_bits;
int level;
int strategy;
CompressionOptions():window_bits(-14),
level(-1),
strategy(0){}
CompressionOptions(int wbits, int lev, int strategy):window_bits(wbits),
level(lev),
strategy(strategy){}
};
// Options to control the behavior of a database (passed to DB::Open) // Options to control the behavior of a database (passed to DB::Open)
struct Options { struct Options {
// ------------------- // -------------------
@ -148,6 +161,9 @@ struct Options {
// java/C api hard to construct. // java/C api hard to construct.
CompressionType* compression_per_level; CompressionType* compression_per_level;
//different options for compression algorithms
CompressionOptions compression_opts;
// If non-NULL, use the specified filter policy to reduce disk reads. // If non-NULL, use the specified filter policy to reduce disk reads.
// Many applications will benefit from passing the result of // Many applications will benefit from passing the result of
// NewBloomFilterPolicy() here. // NewBloomFilterPolicy() here.

@ -44,6 +44,7 @@
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <string.h> #include <string.h>
#include "leveldb/options.h"
#include "port/atomic_pointer.h" #include "port/atomic_pointer.h"
#ifndef PLATFORM_IS_LITTLE_ENDIAN #ifndef PLATFORM_IS_LITTLE_ENDIAN
@ -131,8 +132,8 @@ typedef pthread_once_t OnceType;
#define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT #define LEVELDB_ONCE_INIT PTHREAD_ONCE_INIT
extern void InitOnce(OnceType* once, void (*initializer)()); extern void InitOnce(OnceType* once, void (*initializer)());
inline bool Snappy_Compress(const char* input, size_t length, inline bool Snappy_Compress(const CompressionOptions& opts, const char* input,
::std::string* output) { size_t length, ::std::string* output) {
#ifdef SNAPPY #ifdef SNAPPY
output->resize(snappy::MaxCompressedLength(length)); output->resize(snappy::MaxCompressedLength(length));
size_t outlen; size_t outlen;
@ -162,9 +163,8 @@ inline bool Snappy_Uncompress(const char* input, size_t length,
#endif #endif
} }
inline bool Zlib_Compress(const char* input, size_t length, inline bool Zlib_Compress(const CompressionOptions& opts, const char* input,
::std::string* output, int windowBits = -14, int level = -1, size_t length, ::std::string* output) {
int strategy = 0) {
#ifdef ZLIB #ifdef ZLIB
// The memLevel parameter specifies how much memory should be allocated for // The memLevel parameter specifies how much memory should be allocated for
// the internal compression state. // the internal compression state.
@ -174,8 +174,8 @@ inline bool Zlib_Compress(const char* input, size_t length,
static const int memLevel = 8; static const int memLevel = 8;
z_stream _stream; z_stream _stream;
memset(&_stream, 0, sizeof(z_stream)); memset(&_stream, 0, sizeof(z_stream));
int st = deflateInit2(&_stream, level, Z_DEFLATED, windowBits, int st = deflateInit2(&_stream, opts.level, Z_DEFLATED, opts.window_bits,
memLevel, strategy); memLevel, opts.strategy);
if (st != Z_OK) { if (st != Z_OK) {
return false; return false;
} }
@ -284,8 +284,8 @@ inline char* Zlib_Uncompress(const char* input_data, size_t input_length,
return NULL; return NULL;
} }
inline bool BZip2_Compress(const char* input, size_t length, inline bool BZip2_Compress(const CompressionOptions& opts, const char* input,
::std::string* output) { size_t length, ::std::string* output) {
#ifdef BZIP2 #ifdef BZIP2
bz_stream _stream; bz_stream _stream;
memset(&_stream, 0, sizeof(bz_stream)); memset(&_stream, 0, sizeof(bz_stream));

@ -175,7 +175,8 @@ void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) {
case kSnappyCompression: { case kSnappyCompression: {
std::string* compressed = &r->compressed_output; std::string* compressed = &r->compressed_output;
if (port::Snappy_Compress(raw.data(), raw.size(), compressed) && if (port::Snappy_Compress(r->options.compression_opts, raw.data(),
raw.size(), compressed) &&
GoodCompressionRatio(compressed->size(), raw.size())) { GoodCompressionRatio(compressed->size(), raw.size())) {
block_contents = *compressed; block_contents = *compressed;
} else { } else {
@ -187,7 +188,8 @@ void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) {
break; break;
} }
case kZlibCompression: case kZlibCompression:
if (port::Zlib_Compress(raw.data(), raw.size(), compressed) && if (port::Zlib_Compress(r->options.compression_opts, raw.data(),
raw.size(), compressed) &&
GoodCompressionRatio(compressed->size(), raw.size())) { GoodCompressionRatio(compressed->size(), raw.size())) {
block_contents = *compressed; block_contents = *compressed;
} else { } else {
@ -198,7 +200,8 @@ void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) {
} }
break; break;
case kBZip2Compression: case kBZip2Compression:
if (port::BZip2_Compress(raw.data(), raw.size(), compressed) && if (port::BZip2_Compress(r->options.compression_opts, raw.data(),
raw.size(), compressed) &&
GoodCompressionRatio(compressed->size(), raw.size())) { GoodCompressionRatio(compressed->size(), raw.size())) {
block_contents = *compressed; block_contents = *compressed;
} else { } else {

@ -247,6 +247,7 @@ class TableConstructor: public Constructor {
source_ = new StringSource(sink.contents()); source_ = new StringSource(sink.contents());
Options table_options; Options table_options;
table_options.comparator = options.comparator; table_options.comparator = options.comparator;
table_options.compression_opts = options.compression_opts;
return Table::Open(table_options, source_, sink.contents().size(), &table_); return Table::Open(table_options, source_, sink.contents().size(), &table_);
} }
@ -399,19 +400,22 @@ class DBConstructor: public Constructor {
static bool SnappyCompressionSupported() { static bool SnappyCompressionSupported() {
std::string out; std::string out;
Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
return port::Snappy_Compress(in.data(), in.size(), &out); return port::Snappy_Compress(Options().compression_opts, in.data(), in.size(),
&out);
} }
static bool ZlibCompressionSupported() { static bool ZlibCompressionSupported() {
std::string out; std::string out;
Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
return port::Zlib_Compress(in.data(), in.size(), &out); return port::Zlib_Compress(Options().compression_opts, in.data(), in.size(),
&out);
} }
static bool BZip2CompressionSupported() { static bool BZip2CompressionSupported() {
std::string out; std::string out;
Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; Slice in = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
return port::BZip2_Compress(in.data(), in.size(), &out); return port::BZip2_Compress(Options().compression_opts, in.data(), in.size(),
&out);
} }
enum TestType { enum TestType {

@ -85,6 +85,12 @@ Options::Dump(
Log(log," Options.max_log_file_size: %d", max_log_file_size); Log(log," Options.max_log_file_size: %d", max_log_file_size);
Log(log," Options.db_stats_log_interval: %d", Log(log," Options.db_stats_log_interval: %d",
db_stats_log_interval); db_stats_log_interval);
Log(log," Options.compression_opts.window_bits: %d",
compression_opts.window_bits);
Log(log," Options.compression_opts.level: %d",
compression_opts.level);
Log(log," Options.compression_opts.strategy: %d",
compression_opts.strategy);
Log(log," Options.level0_file_num_compaction_trigger: %d", Log(log," Options.level0_file_num_compaction_trigger: %d",
level0_file_num_compaction_trigger); level0_file_num_compaction_trigger);
Log(log," Options.level0_slowdown_writes_trigger: %d", Log(log," Options.level0_slowdown_writes_trigger: %d",

Loading…
Cancel
Save