Skip to content

Commit

Permalink
memory reporting (#757)
Browse files Browse the repository at this point in the history
* memory reporting

Add arena stats, count BlockFetcher allocations, print db memory stats
to logs
  • Loading branch information
ofriedma authored Jan 22, 2024
1 parent b2143ae commit 0d7234d
Show file tree
Hide file tree
Showing 40 changed files with 909 additions and 102 deletions.
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# Copyright (C) 2023 Speedb Ltd. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Prerequisites for Windows:
# This cmake build is for Windows 64-bit only.
#
Expand Down Expand Up @@ -573,6 +587,10 @@ if(HAVE_AUXV_GETAUXVAL)
add_definitions(-DROCKSDB_AUXV_GETAUXVAL_PRESENT)
endif()

if(MEMORY_REPORTING AND HAVE_MALLOC_USABLE_SIZE)
add_definitions(-DMEMORY_REPORTING)
endif()

set(FSYNC_MODE AUTO CACHE STRING "Enable RTTI in builds")
set_property(CACHE FSYNC_MODE PROPERTY STRINGS AUTO FULL BARRIER OFF)
if(NOT FSYNC_MODE STREQUAL "OFF")
Expand Down
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Based on RocksDB 8.6.7
* Rebase on RocksDB 8.6.7

### Enhancements
* Added memory reporting to the logs to be able to monitor which component in the Arena is using the memory and CacheAllocation overall memory usage, print some statistics. This feature requires compiling with MEMORY_REPORTING flag (#481)
* Added a kUseBaseAddress flag and GetBaseOffset flag to OptionTypeInfo. If this flag is set and a function is used for processing options, the function is passed the base address of the struct rather than the specific field (#397)
* Export GetFlushReasonString/GetCompactionReasonString in listener.h (#785).
* Enabled speedb features in C and Java (#722)
Expand Down
18 changes: 18 additions & 0 deletions build_tools/build_detect_platform
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
#!/usr/bin/env bash

# Copyright (C) 2023 Speedb Ltd. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Detects OS we're compiling on and outputs a file specified by the first
# argument, which in turn gets read while processing Makefile.
#
Expand Down Expand Up @@ -456,7 +470,11 @@ EOF
EOF
if [ "$?" = 0 ]; then
COMMON_FLAGS="$COMMON_FLAGS -DROCKSDB_MALLOC_USABLE_SIZE"
if test $MEMORY_REPORTING; then
COMMON_FLAGS="$COMMON_FLAGS -DMEMORY_REPORTING"
fi
fi

fi

if ! test $ROCKSDB_DISABLE_MEMKIND; then
Expand Down
21 changes: 20 additions & 1 deletion db/arena_wrapped_db_iter.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
// Copyright (C) 2023 Speedb Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).

// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
Expand Down Expand Up @@ -37,7 +55,8 @@ void ArenaWrappedDBIter::Init(
const SequenceNumber& sequence, uint64_t max_sequential_skip_in_iteration,
uint64_t version_number, ReadCallback* read_callback, DBImpl* db_impl,
ColumnFamilyData* cfd, bool expose_blob_index, bool allow_refresh) {
auto mem = arena_.AllocateAligned(sizeof(DBIter));
auto mem = arena_.AllocateAligned(
sizeof(DBIter), ArenaTracker::ArenaStats::ArenaWrappedDBIter);
db_iter_ =
new (mem) DBIter(env, read_options, ioptions, mutable_cf_options,
ioptions.user_comparator, /* iter */ nullptr, version,
Expand Down
40 changes: 40 additions & 0 deletions db/db_impl/db_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,46 @@ void DBImpl::DumpStats() {
ROCKS_LOG_INFO(immutable_db_options_.info_log, "%s",
malloc_stats.c_str());
}
#ifdef MEMORY_REPORTING
std::ostringstream oss;
oss << std::endl << "** Memory Reporting **" << std::endl;
oss << "Arena Stats:" << std::endl
<< "Total: " << NumberToHumanString(Arena::arena_tracker_.total.load())
<< std::endl;
for (const auto& it : Arena::arena_tracker_.arena_stats) {
oss << it.first << ": " << NumberToHumanString(it.second.load())
<< std::endl;
}
oss << "CF Stats: " << std::endl;
uint64_t cfs_total_memory = 0;
std::ostringstream cf_oss;
for (auto cfd : *versions_->GetColumnFamilySet()) {
if (cfd->initialized()) {
std::string cf_name = cfd->GetName();
uint64_t allocated_cf = cfd->mem()->ApproximateMemoryUsageFast() +
cfd->imm()->ApproximateMemoryUsage();
cfs_total_memory += allocated_cf;
cf_oss << "[" << cf_name.c_str()
<< "]: " << NumberToHumanString(allocated_cf) << std::endl;
}
}
oss << "Total: " << NumberToHumanString(cfs_total_memory) << std::endl
<< cf_oss.str();
size_t out;
this->GetIntProperty("rocksdb.block-cache-usage", &out);
oss << "rocksdb.block-cache-usage: " << NumberToHumanString(out)
<< std::endl;
this->GetIntProperty("rocksdb.estimate-table-readers-mem", &out);
oss << "rocksdb.estimate-table-readers-mem: " << NumberToHumanString(out)
<< std::endl;
this->GetIntProperty("rocksdb.block-cache-pinned-usage", &out);
oss << "rocksdb.block-cache-pinned-usage: " << NumberToHumanString(out)
<< std::endl;
oss << "Total CacheAllocationUsage: "
<< NumberToHumanString(ROCKSDB_NAMESPACE::blockfetchermem::mem.load())
<< std::endl;
ROCKS_LOG_INFO(immutable_db_options_.info_log, "%s", oss.str().c_str());
#endif
}

PrintStatistics();
Expand Down
26 changes: 24 additions & 2 deletions db/file_indexer.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
// Copyright (C) 2023 Speedb Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).

// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).
Expand Down Expand Up @@ -86,7 +104,9 @@ void FileIndexer::UpdateIndex(Arena* arena, const size_t num_levels,
num_levels_ = num_levels;
next_level_index_.resize(num_levels);

char* mem = arena->AllocateAligned(num_levels_ * sizeof(int32_t));
char* mem =
arena->AllocateAligned(num_levels_ * sizeof(int32_t),
ArenaTracker::ArenaStats::FileIndexerUpdateIndex);
level_rb_ = new (mem) int32_t[num_levels_];
for (size_t i = 0; i < num_levels_; i++) {
level_rb_[i] = -1;
Expand All @@ -103,7 +123,9 @@ void FileIndexer::UpdateIndex(Arena* arena, const size_t num_levels,
}
IndexLevel& index_level = next_level_index_[level];
index_level.num_index = upper_size;
mem = arena->AllocateAligned(upper_size * sizeof(IndexUnit));
mem = arena->AllocateAligned(
upper_size * sizeof(IndexUnit),
ArenaTracker::ArenaStats::FileIndexerUpdateIndex);
index_level.index_units = new (mem) IndexUnit[upper_size];

CalculateLB(
Expand Down
6 changes: 4 additions & 2 deletions db/memtable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,8 @@ Slice MemTableRep::UserKey(const char* key) const {
}

KeyHandle MemTableRep::Allocate(const size_t len, char** buf) {
*buf = allocator_->Allocate(len);
*buf =
allocator_->Allocate(len, ArenaTracker::ArenaStats::DefaultMemtableImpl);
return static_cast<KeyHandle>(*buf);
}

Expand Down Expand Up @@ -560,7 +561,8 @@ class MemTableIterator : public InternalIterator {
InternalIterator* MemTable::NewIterator(const ReadOptions& read_options,
Arena* arena) {
assert(arena != nullptr);
auto mem = arena->AllocateAligned(sizeof(MemTableIterator));
auto mem = arena->AllocateAligned(
sizeof(MemTableIterator), ArenaTracker::ArenaStats::MemTableNewIterator);
return new (mem) MemTableIterator(*this, read_options, arena);
}

Expand Down
19 changes: 14 additions & 5 deletions db/version_set.cc
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,9 @@ void DoGenerateLevelFilesBrief(LevelFilesBrief* file_level,

size_t num = files.size();
file_level->num_files = num;
char* mem = arena->AllocateAligned(num * sizeof(FdWithKeyRange));
char* mem = arena->AllocateAligned(
num * sizeof(FdWithKeyRange),
ArenaTracker::ArenaStats::DoGenerateLevelFilesBrief);
file_level->files = new (mem) FdWithKeyRange[num];

for (size_t i = 0; i < num; i++) {
Expand All @@ -880,7 +882,9 @@ void DoGenerateLevelFilesBrief(LevelFilesBrief* file_level,
// Copy key slice to sequential memory
size_t smallest_size = smallest_key.size();
size_t largest_size = largest_key.size();
mem = arena->AllocateAligned(smallest_size + largest_size);
mem = arena->AllocateAligned(
smallest_size + largest_size,
ArenaTracker::ArenaStats::DoGenerateLevelFilesBrief);
memcpy(mem, smallest_key.data(), smallest_size);
memcpy(mem + smallest_size, largest_key.data(), largest_size);

Expand Down Expand Up @@ -1906,7 +1910,8 @@ InternalIterator* Version::TEST_GetLevelIterator(
const ReadOptions& read_options, MergeIteratorBuilder* merge_iter_builder,
int level, bool allow_unprepared_value) {
auto* arena = merge_iter_builder->GetArena();
auto* mem = arena->AllocateAligned(sizeof(LevelIterator));
auto* mem = arena->AllocateAligned(
sizeof(LevelIterator), ArenaTracker::ArenaStats::TEST_GetLevelIterator);
TruncatedRangeDelIterator*** tombstone_iter_ptr = nullptr;
auto level_iter = new (mem) LevelIterator(
cfd_->table_cache(), read_options, file_options_,
Expand Down Expand Up @@ -2040,7 +2045,9 @@ void Version::AddIteratorsForLevel(const ReadOptions& read_options,
// For levels > 0, we can use a concatenating iterator that sequentially
// walks through the non-overlapping files in the level, opening them
// lazily.
auto* mem = arena->AllocateAligned(sizeof(LevelIterator));
auto* mem = arena->AllocateAligned(
sizeof(LevelIterator),
ArenaTracker::ArenaStats::VersionAddIteratorsForLevel);
TruncatedRangeDelIterator*** tombstone_iter_ptr = nullptr;
auto level_iter = new (mem) LevelIterator(
cfd_->table_cache(), read_options, soptions,
Expand Down Expand Up @@ -2103,7 +2110,9 @@ Status Version::OverlapWithLevelIterator(const ReadOptions& read_options,
}
}
} else if (storage_info_.LevelFilesBrief(level).num_files > 0) {
auto mem = arena.AllocateAligned(sizeof(LevelIterator));
auto mem = arena.AllocateAligned(
sizeof(LevelIterator),
ArenaTracker::ArenaStats::VersionOverlapWithLevelIterator);
ScopedArenaIterator iter(new (mem) LevelIterator(
cfd_->table_cache(), read_options, file_options,
cfd_->internal_comparator(), &storage_info_.LevelFilesBrief(level),
Expand Down
6 changes: 4 additions & 2 deletions db/version_set_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,8 @@ class FindLevelFileTest : public testing::Test {
~FindLevelFileTest() override {}

void LevelFileInit(size_t num = 0) {
char* mem = arena_.AllocateAligned(num * sizeof(FdWithKeyRange));
char* mem = arena_.AllocateAligned(num * sizeof(FdWithKeyRange),
ArenaTracker::ArenaStats::LevelFileInit);
file_level_.files = new (mem) FdWithKeyRange[num];
file_level_.num_files = 0;
}
Expand All @@ -1001,7 +1002,8 @@ class FindLevelFileTest : public testing::Test {
Slice largest_slice = largest_key.Encode();

char* mem =
arena_.AllocateAligned(smallest_slice.size() + largest_slice.size());
arena_.AllocateAligned(smallest_slice.size() + largest_slice.size(),
ArenaTracker::ArenaStats::FindLevelFileTestAdd);
memcpy(mem, smallest_slice.data(), smallest_slice.size());
memcpy(mem + smallest_slice.size(), largest_slice.data(),
largest_slice.size());
Expand Down
21 changes: 20 additions & 1 deletion logging/log_buffer.cc
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
// Copyright (C) 2023 Speedb Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).

// This source code is licensed under both the GPLv2 (found in the
// COPYING file in the root directory) and Apache 2.0 License
// (found in the LICENSE.Apache file in the root directory).

#include "logging/log_buffer.h"

#include "port/port.h"
Expand All @@ -20,7 +38,8 @@ void LogBuffer::AddLogToBuffer(size_t max_log_size, const char* format,
return;
}

char* alloc_mem = arena_.AllocateAligned(max_log_size);
char* alloc_mem = arena_.AllocateAligned(
max_log_size, ArenaTracker::ArenaStats::LogBufferAddLogToBuffer);
BufferedLog* buffered_log = new (alloc_mem) BufferedLog();
char* p = buffered_log->message;
char* limit = alloc_mem + max_log_size - 1;
Expand Down
5 changes: 3 additions & 2 deletions memory/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ class Allocator {
public:
virtual ~Allocator() {}

virtual char* Allocate(size_t bytes) = 0;
virtual char* AllocateAligned(size_t bytes, size_t huge_page_size = 0,
virtual char* Allocate(size_t bytes, uint8_t caller_name) = 0;
virtual char* AllocateAligned(size_t bytes, uint8_t caller_name,
size_t huge_page_size = 0,
Logger* logger = nullptr) = 0;

virtual size_t BlockSize() const = 0;
Expand Down
Loading

0 comments on commit 0d7234d

Please sign in to comment.