Skip to content

Introduce a TablePinningPolicy to control how and when memory is pinned - #459

Merged
Yuval-Ariel merged 18 commits into
speedb-io:mainfrom
mrambacher:PinningPolicy
Aug 2, 2023
Merged

Introduce a TablePinningPolicy to control how and when memory is pinned#459
Yuval-Ariel merged 18 commits into
speedb-io:mainfrom
mrambacher:PinningPolicy

Conversation

@mrambacher

Copy link
Copy Markdown
Contributor

This PR adds a TablePinningPolicy to the BlockBasedTableOptions. This new class is Customizable and can be created from strings. The class has methods to limit the amount of pin data in the system.

The basic approach is that the unit probes (MayPin) if it believes data is available at the time. If so, the code does it normal checks and then attempts to pin the new data (PinData). Once the code is done with the data, UnPinData puts the memory back into the available pool

@Guyme Guyme linked an issue Apr 13, 2023 that may be closed by this pull request
Comment thread db/db_block_cache_test.cc Outdated

options.ignore_unsupported_options = false;
const auto& id = GetParam();
EXPECT_OK(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why EXPECT_OK and not ASSERT_OK?

Comment thread db/db_block_cache_test.cc Outdated
ASSERT_EQ(pinning_policy_->GetUsage(), 0);
}

static const std::vector<std::string>& GetPinningPolicies() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really minor, but unnamed namespaces should be the way to go instead of static functions.

struct ConfigOptions;
// Struct that contains information about the table being evaluated for pinning
struct TablePinningOptions {
TablePinningOptions() {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you choos the {} and not = default on purpose?

Comment thread db/db_block_cache_test.cc Outdated
}
ASSERT_EQ(pinning_policy_->GetUsage(), used);
}
printf("MJR: Pinned=%d\n", (int)used);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is printing really necessary? I would avoid printing to the console during unit tests as it just bothers users running unit tests who just want to see the tests pass.
The unit test should use assertions to verify it is passing.

Comment thread db/db_block_cache_test.cc Outdated
const auto& id = GetParam();
EXPECT_OK(
TablePinningPolicy::CreateFromString(options, id, &pinning_policy_));
printf("MJR: Loaded pinning policy (%s)\n", id.c_str());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the printing (which, btw, may be done using std::cout in unit tests). Please also see my comment below regarding the printf there.

Comment thread plugin/speedb/pinning_policy/scoped_pinning_policy.cc
Comment thread plugin/speedb/pinning_policy/scoped_pinning_policy_test.cc
Comment thread plugin/speedb/pinning_policy/scoped_pinning_policy_test.cc
Comment thread plugin/speedb/pinning_policy/scoped_pinning_policy_test.cc Outdated
Comment thread plugin/speedb/pinning_policy/scoped_pinning_policy_test.cc
@udi-speedb

Copy link
Copy Markdown
Contributor

@mrambacher - First batch of comments. Haven't finished the review.

@udi-speedb

Copy link
Copy Markdown
Contributor

@mrambacher - In case it wasn't clear. I am waiting for you to address the comments I have given before continuing my review.


ScopedPinningPolicy::ScopedPinningPolicy() {
static const uint8_t kNumTypes = 7;
static const int kNumLevels = 7;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that just for testing the concept?


std::atomic<size_t> usage_;
std::vector<std::atomic_size_t> usage_by_level_;
std::vector<std::atomic_size_t> usage_by_type_;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not initialize the vectors to 0 here and avoid the necessity in the ctor?

}
for (uint8_t t = 0; t < kNumTypes; t++) {
usage_by_type_[t].store(0);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't you use std::fill?
But a better options IMO is to init all of the fields in the header as I suggest
And you could delegate to the non default ctor by calling here ScopedPinningPolicy(ScopedPinningOptions()) and avoid the code duplication in the ctor-s.

}
for (uint8_t t = 0; t < kNumTypes; t++) {
usage_by_type_[t].store(0);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comments above for the default ctor.

usage_by_type_[type] += size;
} else {
usage_by_level_[level] += size;
usage_by_type_[type] += size;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you decrease the usage by level / type when pinned == false?

} else if (pinned) {
usage_by_type_[type] = size;
if (level >= kNumLevels) level = kNumLevels - 1;
if (type >= kNumTypes) type = kNumTypes - 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only for testing the concept or is that how it's going to be in production code?

size_t size) const {
auto limit = GetUsage();
return CheckPin(tpo, type, size, limit);
return CheckPin(tpo, type, size, usage_);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is MayPin()? used for?
And, it should be clear to the users that they MayPin() may return true but actual pinning may still fail.

@udi-speedb
udi-speedb self-requested a review May 31, 2023 01:37
@erez-speedb

erez-speedb commented Jun 11, 2023

Copy link
Copy Markdown

build db_bench failed
CC plugin/speedb/speedb_registry.o
CC plugin/speedb/memtable/hash_spd_rep.o
CC plugin/speedb/paired_filter/speedb_paired_bloom.o
CC plugin/speedb/paired_filter/speedb_paired_bloom_internal.o
CC plugin/speedb/pinning_policy/scoped_pinning_policy.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/concurrent_tree.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/keyrange.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/lock_request.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/locktree.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/manager.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/range_buffer.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/treenode.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/txnid_set.o
CC utilities/transactions/lock/range/range_tree/lib/locktree/wfg.o
plugin/speedb/pinning_policy/scoped_pinning_policy.cc: In member function ‘virtual bool rocksdb::ScopedPinningPolicy::CheckPin(const rocksdb::TablePinningOptions&, uint8_t, size_t, size_t) const’:
plugin/speedb/pinning_policy/scoped_pinning_policy.cc:56:48: error: comparison of unsigned expression >= 0 is always true [-Werror=type-limits]
56 | if (tpo.is_bottom && options_.bottom_percent >= 0) {
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~
plugin/speedb/pinning_policy/scoped_pinning_policy.cc:60:52: error: comparison of unsigned expression >= 0 is always true [-Werror=type-limits]
60 | } else if (tpo.level > 0 && options_.mid_percent >= 0) {
| ~~~~~~~~~~~~~~~~~~~~~^~~~
CC utilities/transactions/lock/range/range_tree/lib/standalone_port.o
CC utilities/transactions/lock/range/range_tree/lib/util/dbt.o
CC utilities/transactions/lock/range/range_tree/lib/util/memarena.o
CC utilities/transactions/lock/range/range_tree/range_tree_lock_manager.o
CC utilities/transactions/lock/range/range_tree/range_tree_lock_tracker.o
cc1plus: all warnings being treated as errors
make: *** [Makefile:2418: plugin/speedb/pinning_policy/scoped_pinning_policy.o] Error 1

comparison of unsigned expression >= 0 is always true [-Werror=type-limits]
@udi-speedb
udi-speedb self-requested a review June 14, 2023 06:52
@Yuval-Ariel

Copy link
Copy Markdown
Contributor

blocked until #573 is fixed @maxb-io FYI

@Guyme
Guyme requested review from erez-speedb and removed request for erez-speedb June 29, 2023 12:12
@Yuval-Ariel
Yuval-Ariel self-requested a review July 3, 2023 12:56
@Yuval-Ariel

Copy link
Copy Markdown
Contributor

@mrambacher plz also add to the HISTORY.md file

@Yuval-Ariel

Copy link
Copy Markdown
Contributor

https://github.com/speedb-io/speedb/actions/runs/5444728254/jobs/9904106132#step:6:571

==15027==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000010398 at pc 0x7f21e95a2c2e bp 0x7f21dcdb9f20 sp 0x7f21dcdb9f10
WRITE of size 8 at 0x606000010398 thread T6
#0 0x7f21e95a2c2d in std::__atomic_base::operator+=(unsigned long) /usr/include/c++/7/bits/atomic_base.h:312
#1 0x7f21e95a2c2d in rocksdb::RecordingPinningPolicy::RecordPinned(int, unsigned char, unsigned long, bool) table/block_based/table_pinning_policy.cc:145
#2 0x7f21e95a2e92 in rocksdb::RecordingPinningPolicy::PinData(rocksdb::TablePinningOptions const&, unsigned char, unsigned long, std::unique_ptr<rocksdb::PinnedEntry, std::default_deleterocksdb::PinnedEntry >) table/block_based/table_pinning_policy.cc:126
#3 0x7f21e959030e in rocksdb::PartitionIndexReader::Create(rocksdb::BlockBasedTable const
, rocksdb::ReadOptions const&, rocksdb::TablePinningOptions const&, rocksdb::FilePrefetchBuffer*, bool, bool, bool, rocksdb::BlockCacheLookupContext*,

Not sure how it disappeared as part of the rebase...
Comment thread db_stress_tool/db_stress_gflags.cc

@Yuval-Ariel Yuval-Ariel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove foo file.

@Yuval-Ariel

Copy link
Copy Markdown
Contributor

failed unit tests:
FAILED TESTS (1/11819):
752 ms: /__w/speedb/speedb/options_settable_test OptionsSettableTest.BlockBasedTableOptionsAllFieldsSettable

@Yuval-Ariel
Yuval-Ariel merged commit 6e05428 into speedb-io:main Aug 2, 2023
udi-speedb pushed a commit that referenced this pull request Nov 22, 2023
udi-speedb pushed a commit that referenced this pull request Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Clean data phase 1: Pinning metadata to the cache

4 participants