Skip to content

Commit ccf0fcd

Browse files
A number of smaller fixes and performance improvements:
- Implemented Get() directly instead of building on top of a full merging iterator stack. This speeds up the "readrandom" benchmark by up to 15-30%. - Fixed an opensource compilation problem. Added --db=<name> flag to control where the database is placed. - Automatically compact a file when we have done enough overlapping seeks to that file. - Fixed a performance bug where we would read from at least one file in a level even if none of the files overlapped the key being read. - Makefile fix for Mac OSX installations that have XCode 4 without XCode 3. - Unified the two occurrences of binary search in a file-list into one routine. - Found and fixed a bug where we would unnecessarily search the last file when looking for a key larger than all data in the level. - A fix to avoid the need for trivial move compactions and therefore gets rid of two out of five syncs in "fillseq". - Removed the MANIFEST file write when switching to a new memtable/log-file for a 10-20% improvement on fill speed on ext4. - Adding a SNAPPY setting in the Makefile for folks who have Snappy installed. Snappy compresses values and speeds up writes. git-svn-id: https://leveldb.googlecode.com/svn/trunk@32 62dab493-f737-651d-591e-8d6aee1b9529
1 parent 80e5b0d commit ccf0fcd

19 files changed

+783
-152
lines changed

Makefile

+24-4
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,22 @@ PLATFORM_CFLAGS = -DLEVELDB_PLATFORM_POSIX -std=c++0x
2828
PORT_MODULE = port_posix.o
2929
endif # UNAME
3030

31-
CFLAGS = -c -I. -I./include $(PLATFORM_CFLAGS) $(OPT)
31+
# Set 'SNAPPY' to 1 if you have the Snappy compression library
32+
# installed and want to enable its use in LevelDB
33+
# (see http://code.google.com/p/snappy/)
34+
SNAPPY=0
35+
36+
ifeq ($(SNAPPY), 0)
37+
SNAPPY_CFLAGS=
38+
SNAPPY_LDFLAGS=
39+
else
40+
SNAPPY_CFLAGS=-DSNAPPY
41+
SNAPPY_LDFLAGS=-lsnappy
42+
endif
3243

33-
LDFLAGS=-lpthread
44+
CFLAGS = -c -I. -I./include $(PLATFORM_CFLAGS) $(OPT) $(SNAPPY_CFLAGS)
45+
46+
LDFLAGS=-lpthread $(SNAPPY_LDFLAGS)
3447

3548
LIBOBJECTS = \
3649
./db/builder.o \
@@ -85,6 +98,7 @@ TESTS = \
8598
skiplist_test \
8699
table_test \
87100
version_edit_test \
101+
version_set_test \
88102
write_batch_test
89103

90104
PROGRAMS = db_bench $(TESTS)
@@ -151,17 +165,23 @@ skiplist_test: db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS)
151165
version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS)
152166
$(CC) $(LDFLAGS) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
153167

168+
version_set_test: db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS)
169+
$(CC) $(LDFLAGS) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
170+
154171
write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS)
155172
$(CC) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
156173

157174
ifeq ($(PLATFORM), IOS)
158175
# For iOS, create universal object files to be used on both the simulator and
159176
# a device.
177+
SIMULATORROOT=/Developer/Platforms/iPhoneSimulator.platform/Developer
178+
DEVICEROOT=/Developer/Platforms/iPhoneOS.platform/Developer
179+
IOSVERSION=$(shell defaults read /Developer/Platforms/iPhoneOS.platform/version CFBundleShortVersionString)
160180
.cc.o:
161181
mkdir -p ios-x86/$(dir $@)
162-
$(CC) $(CFLAGS) -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk -arch i686 $< -o ios-x86/$@
182+
$(SIMULATORROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 $< -o ios-x86/$@
163183
mkdir -p ios-arm/$(dir $@)
164-
$(CC) $(CFLAGS) -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk -arch armv6 -arch armv7 $< -o ios-arm/$@
184+
$(DEVICEROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 $< -o ios-arm/$@
165185
lipo ios-x86/$@ ios-arm/$@ -create -output $@
166186
else
167187
.cc.o:

TODO

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ db
88
object stores, etc. can be done in the background anyway, so
99
probably not that important.
1010

11-
api changes:
12-
- Make it wrappable
13-
14-
Faster Get implementation
11+
After a range is completely deleted, what gets rid of the
12+
corresponding files if we do no future changes to that range. Make
13+
the conditions for triggering compactions fire in more situations?

db/builder.cc

+2-4
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ Status BuildTable(const std::string& dbname,
1919
const Options& options,
2020
TableCache* table_cache,
2121
Iterator* iter,
22-
FileMetaData* meta,
23-
VersionEdit* edit) {
22+
FileMetaData* meta) {
2423
Status s;
2524
meta->file_size = 0;
2625
iter->SeekToFirst();
@@ -79,8 +78,7 @@ Status BuildTable(const std::string& dbname,
7978
}
8079

8180
if (s.ok() && meta->file_size > 0) {
82-
edit->AddFile(0, meta->number, meta->file_size,
83-
meta->smallest, meta->largest);
81+
// Keep it
8482
} else {
8583
env->DeleteFile(fname);
8684
}

db/builder.h

+4-6
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,15 @@ class VersionEdit;
1919

2020
// Build a Table file from the contents of *iter. The generated file
2121
// will be named according to meta->number. On success, the rest of
22-
// *meta will be filled with metadata about the generated table, and
23-
// the file information will be added to *edit. If no data is present
24-
// in *iter, meta->file_size will be set to zero, and no Table file
25-
// will be produced.
22+
// *meta will be filled with metadata about the generated table.
23+
// If no data is present in *iter, meta->file_size will be set to
24+
// zero, and no Table file will be produced.
2625
extern Status BuildTable(const std::string& dbname,
2726
Env* env,
2827
const Options& options,
2928
TableCache* table_cache,
3029
Iterator* iter,
31-
FileMetaData* meta,
32-
VersionEdit* edit);
30+
FileMetaData* meta);
3331

3432
}
3533

db/corruption_test.cc

+18-13
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ static const int kValueSize = 1000;
2727
class CorruptionTest {
2828
public:
2929
test::ErrorEnv env_;
30-
Random rnd_;
3130
std::string dbname_;
3231
Cache* tiny_cache_;
3332
Options options_;
3433
DB* db_;
3534

36-
CorruptionTest() : rnd_(test::RandomSeed()) {
35+
CorruptionTest() {
3736
tiny_cache_ = NewLRUCache(100);
3837
options_.env = &env_;
3938
dbname_ = test::TmpDir() + "/db_test";
@@ -122,15 +121,17 @@ class CorruptionTest {
122121
ASSERT_OK(env_.GetChildren(dbname_, &filenames));
123122
uint64_t number;
124123
FileType type;
125-
std::vector<std::string> candidates;
124+
std::string fname;
125+
int picked_number = -1;
126126
for (int i = 0; i < filenames.size(); i++) {
127127
if (ParseFileName(filenames[i], &number, &type) &&
128-
type == filetype) {
129-
candidates.push_back(dbname_ + "/" + filenames[i]);
128+
type == filetype &&
129+
int(number) > picked_number) { // Pick latest file
130+
fname = dbname_ + "/" + filenames[i];
131+
picked_number = number;
130132
}
131133
}
132-
ASSERT_TRUE(!candidates.empty()) << filetype;
133-
std::string fname = candidates[rnd_.Uniform(candidates.size())];
134+
ASSERT_TRUE(!fname.empty()) << filetype;
134135

135136
struct stat sbuf;
136137
if (stat(fname.c_str(), &sbuf) != 0) {
@@ -239,8 +240,6 @@ TEST(CorruptionTest, TableFileIndexData) {
239240
Build(10000); // Enough to build multiple Tables
240241
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
241242
dbi->TEST_CompactMemTable();
242-
dbi->TEST_CompactRange(0, "", "~");
243-
dbi->TEST_CompactRange(1, "", "~");
244243

245244
Corrupt(kTableFile, -2000, 500);
246245
Reopen();
@@ -296,26 +295,32 @@ TEST(CorruptionTest, CompactionInputError) {
296295
Build(10);
297296
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
298297
dbi->TEST_CompactMemTable();
299-
ASSERT_EQ(1, Property("leveldb.num-files-at-level0"));
298+
const int last = config::kNumLevels - 1;
299+
ASSERT_EQ(1, Property("leveldb.num-files-at-level" + NumberToString(last)));
300300

301301
Corrupt(kTableFile, 100, 1);
302302
Check(9, 9);
303303

304304
// Force compactions by writing lots of values
305305
Build(10000);
306306
Check(10000, 10000);
307-
dbi->TEST_CompactRange(0, "", "~");
308-
ASSERT_EQ(0, Property("leveldb.num-files-at-level0"));
309307
}
310308

311309
TEST(CorruptionTest, CompactionInputErrorParanoid) {
312310
Options options;
313311
options.paranoid_checks = true;
314312
options.write_buffer_size = 1048576;
315313
Reopen(&options);
314+
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
315+
316+
// Fill levels >= 1 so memtable compaction outputs to level 1
317+
for (int level = 1; level < config::kNumLevels; level++) {
318+
dbi->Put(WriteOptions(), "", "begin");
319+
dbi->Put(WriteOptions(), "~", "end");
320+
dbi->TEST_CompactMemTable();
321+
}
316322

317323
Build(10);
318-
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
319324
dbi->TEST_CompactMemTable();
320325
ASSERT_EQ(1, Property("leveldb.num-files-at-level0"));
321326

db/db_bench.cc

+12-7
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ static int FLAGS_open_files = 0;
8686
// benchmark will fail.
8787
static bool FLAGS_use_existing_db = false;
8888

89+
// Use the db with the following name.
90+
static const char* FLAGS_db = "/tmp/dbbench";
91+
8992
namespace leveldb {
9093

9194
// Helper for quickly generating random data.
@@ -318,14 +321,14 @@ class Benchmark {
318321
bytes_(0),
319322
rand_(301) {
320323
std::vector<std::string> files;
321-
Env::Default()->GetChildren("/tmp/dbbench", &files);
324+
Env::Default()->GetChildren(FLAGS_db, &files);
322325
for (int i = 0; i < files.size(); i++) {
323326
if (Slice(files[i]).starts_with("heap-")) {
324-
Env::Default()->DeleteFile("/tmp/dbbench/" + files[i]);
327+
Env::Default()->DeleteFile(std::string(FLAGS_db) + "/" + files[i]);
325328
}
326329
}
327330
if (!FLAGS_use_existing_db) {
328-
DestroyDB("/tmp/dbbench", Options());
331+
DestroyDB(FLAGS_db, Options());
329332
}
330333
}
331334

@@ -364,7 +367,7 @@ class Benchmark {
364367
Write(write_options, RANDOM, EXISTING, num_, FLAGS_value_size, 1);
365368
} else if (name == Slice("fillsync")) {
366369
write_options.sync = true;
367-
Write(write_options, RANDOM, FRESH, num_ / 100, FLAGS_value_size, 1);
370+
Write(write_options, RANDOM, FRESH, num_ / 1000, FLAGS_value_size, 1);
368371
} else if (name == Slice("fill100K")) {
369372
Write(write_options, RANDOM, FRESH, num_ / 1000, 100 * 1000, 1);
370373
} else if (name == Slice("readseq")) {
@@ -490,7 +493,7 @@ class Benchmark {
490493
options.create_if_missing = !FLAGS_use_existing_db;
491494
options.block_cache = cache_;
492495
options.write_buffer_size = FLAGS_write_buffer_size;
493-
Status s = DB::Open(options, "/tmp/dbbench", &db_);
496+
Status s = DB::Open(options, FLAGS_db, &db_);
494497
if (!s.ok()) {
495498
fprintf(stderr, "open error: %s\n", s.ToString().c_str());
496499
exit(1);
@@ -506,7 +509,7 @@ class Benchmark {
506509
}
507510
delete db_;
508511
db_ = NULL;
509-
DestroyDB("/tmp/dbbench", Options());
512+
DestroyDB(FLAGS_db, Options());
510513
Open();
511514
Start(); // Do not count time taken to destroy/open
512515
}
@@ -617,7 +620,7 @@ class Benchmark {
617620

618621
void HeapProfile() {
619622
char fname[100];
620-
snprintf(fname, sizeof(fname), "/tmp/dbbench/heap-%04d", ++heap_counter_);
623+
snprintf(fname, sizeof(fname), "%s/heap-%04d", FLAGS_db, ++heap_counter_);
621624
WritableFile* file;
622625
Status s = Env::Default()->NewWritableFile(fname, &file);
623626
if (!s.ok()) {
@@ -665,6 +668,8 @@ int main(int argc, char** argv) {
665668
FLAGS_cache_size = n;
666669
} else if (sscanf(argv[i], "--open_files=%d%c", &n, &junk) == 1) {
667670
FLAGS_open_files = n;
671+
} else if (strncmp(argv[i], "--db=", 5) == 0) {
672+
FLAGS_db = argv[i] + 5;
668673
} else {
669674
fprintf(stderr, "Invalid flag '%s'\n", argv[i]);
670675
exit(1);

0 commit comments

Comments
 (0)