Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize unit tests #848

Merged
merged 15 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions libraries/net/test/test_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,14 @@ struct WasmMemoryCache
struct TempDatabase
{
TempDatabase()
: dir("psibase-test"),
sharedState{std::make_shared<psibase::SharedState>(
psibase::SharedDatabase{dir.path.native(), 1ull << 27, 1ull << 27, 1ull << 27,
1ull << 27},
: sharedState{std::make_shared<psibase::SharedState>(
psibase::SharedDatabase{std::filesystem::temp_directory_path(),
{1ull << 27, 1ull << 27, 1ull << 27, 1ull << 27},
triedent::open_mode::temporary},
psibase::WasmCache{16})}
{
dir.reset();
}
auto getSystemContext() { return sharedState->getSystemContext(); }
TempDir dir;
auto getSystemContext() { return sharedState->getSystemContext(); }
std::shared_ptr<psibase::SharedState> sharedState;
};

Expand Down
22 changes: 14 additions & 8 deletions libraries/psibase/native/include/psibase/db.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
#include <psio/fracpack.hpp>
#include <psio/from_bin.hpp>
#include <psio/to_key.hpp>
#include <triedent/file_fwd.hpp>

#include <boost/filesystem/path.hpp>
#include <filesystem>

namespace triedent
{
class write_session;
class root;
struct database_config;
} // namespace triedent

namespace psibase
Expand Down Expand Up @@ -55,17 +57,20 @@ namespace psibase
std::shared_ptr<SharedDatabaseImpl> impl;

SharedDatabase() = default;
SharedDatabase(const boost::filesystem::path& dir,
uint64_t hot_addr_bits = 1ull << 32,
uint64_t warm_addr_bits = 1ull << 32,
uint64_t cool_addr_bits = 1ull << 32,
uint64_t cold_addr_bits = 1ull << 32);
SharedDatabase(const std::filesystem::path& dir,
const triedent::database_config& config,
triedent::open_mode mode = triedent::open_mode::create);
SharedDatabase(const SharedDatabase&) = default;
SharedDatabase(SharedDatabase&&) = default;

SharedDatabase& operator=(const SharedDatabase&) = default;
SharedDatabase& operator=(SharedDatabase&&) = default;

// Returns a fork of the database.
// Warning: this should only be used for temporary databases as
// the storage is shared.
SharedDatabase clone() const;

ConstRevisionPtr getHead();
ConstRevisionPtr emptyRevision();
WriterPtr createWriter();
Expand Down Expand Up @@ -190,8 +195,9 @@ namespace psibase
std::optional<KVResult> kvMaxRaw(DbId db, psio::input_stream key);

template <typename K, typename V>
auto kvPut(DbId db, const K& key, const V& value)
-> std::enable_if_t<!psio::is_std_optional<V>(), void>
auto kvPut(DbId db,
const K& key,
const V& value) -> std::enable_if_t<!psio::is_std_optional<V>(), void>
{
kvPutRaw(db, psio::convert_to_key(key), psio::convert_to_frac(value));
}
Expand Down
100 changes: 46 additions & 54 deletions libraries/psibase/native/src/useTriedent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,47 +270,42 @@ namespace psibase
{
std::shared_ptr<triedent::database> trie;

std::mutex topMutex;
std::mutex topMutex;
std::shared_ptr<triedent::root> topRoot;

std::mutex headMutex;
std::shared_ptr<const Revision> head;

std::mutex subjectiveMutex;
std::shared_ptr<triedent::root> subjective;

SharedDatabaseImpl(const std::filesystem::path& dir,
uint64_t hot_bytes,
uint64_t warm_bytes,
uint64_t cool_bytes,
uint64_t cold_bytes)
SharedDatabaseImpl(const std::filesystem::path& dir,
const triedent::database_config& config,
triedent::open_mode mode)
{
// The largest object is 16 MiB
// Each file must be at least double this
constexpr std::uint64_t min_size = 32 * 1024 * 1024;
if (hot_bytes < min_size || warm_bytes < min_size || cool_bytes < min_size ||
cold_bytes < min_size)
if (config.hot_bytes < min_size || config.warm_bytes < min_size ||
config.cool_bytes < min_size || config.cold_bytes < min_size)
{
throw std::runtime_error("Requested database size is too small");
}
if (!std::filesystem::exists(dir / "db"))
{
// std::cout << "Creating " << dir << "\n";
triedent::database::create( //
dir, //
triedent::database::config{
.hot_bytes = hot_bytes,
.warm_bytes = warm_bytes,
.cool_bytes = cool_bytes,
.cold_bytes = cold_bytes,
});
}
else
{
// std::cout << "Open existing " << dir << "\n";
}
trie = std::make_shared<triedent::database>(dir.c_str(), triedent::database::read_write);
auto s = trie->start_write_session();
head = loadRevision(*s, s->get_top_root(), revisionHeadKey);
trie = std::make_shared<triedent::database>(dir.c_str(), config, mode);
auto s = trie->start_write_session();
topRoot = s->get_top_root();
head = loadRevision(*s, topRoot, revisionHeadKey);
}

SharedDatabaseImpl(const SharedDatabaseImpl& other)
: trie(other.trie), topRoot(other.topRoot), head(other.head), subjective(other.subjective)
{
}

auto getTopRoot()
{
std::lock_guard lock{topMutex};
return topRoot;
}

auto getHead()
Expand All @@ -323,7 +318,6 @@ namespace psibase
{
{
std::lock_guard lock{topMutex};
auto topRoot = session.get_top_root();
session.upsert(topRoot, revisionHeadKey, r->roots);
session.set_top_root(topRoot);
}
Expand All @@ -337,25 +331,25 @@ namespace psibase
const Revision& r)
{
std::lock_guard lock{topMutex};
auto topRoot = session.get_top_root();
session.upsert(topRoot, revisionById(blockId), r.roots);
session.set_top_root(topRoot);
}
}; // SharedDatabaseImpl

SharedDatabase::SharedDatabase(const boost::filesystem::path& dir,
uint64_t hot_bytes,
uint64_t warm_bytes,
uint64_t cool_bytes,
uint64_t cold_bytes)
: impl{std::make_shared<SharedDatabaseImpl>(dir.c_str(),
hot_bytes,
warm_bytes,
cool_bytes,
cold_bytes)}
SharedDatabase::SharedDatabase(const std::filesystem::path& dir,
const triedent::database_config& config,
triedent::open_mode mode)
: impl{std::make_shared<SharedDatabaseImpl>(dir, config, mode)}
{
}

SharedDatabase SharedDatabase::clone() const
{
SharedDatabase result{*this};
result.impl = std::make_shared<SharedDatabaseImpl>(*impl);
return result;
}

ConstRevisionPtr SharedDatabase::getHead()
{
return impl->getHead();
Expand All @@ -378,25 +372,24 @@ namespace psibase

ConstRevisionPtr SharedDatabase::getRevision(Writer& writer, const Checksum256& blockId)
{
return loadRevision(writer, writer.get_top_root(), revisionById(blockId), true);
return loadRevision(writer, impl->getTopRoot(), revisionById(blockId), true);
}

// TODO: move triedent::root destruction to a gc thread
void SharedDatabase::removeRevisions(Writer& writer, const Checksum256& irreversible)
{
// TODO: Reduce critical section
std::lock_guard lock{impl->topMutex};
auto topRoot = writer.get_top_root();
std::vector<char> key{revisionByIdPrefix};

// Remove everything with a blockNum <= irreversible's, except irreversible.
while (writer.get_greater_equal(topRoot, key, &key, nullptr, nullptr))
while (writer.get_greater_equal(impl->topRoot, key, &key, nullptr, nullptr))
{
if (key.size() != 1 + irreversible.size() || key[0] != revisionByIdPrefix ||
memcmp(key.data() + 1, irreversible.data(), sizeof(BlockNum)) > 0)
break;
if (memcmp(key.data() + 1, irreversible.data(), irreversible.size()))
writer.remove(topRoot, key);
writer.remove(impl->topRoot, key);
key.push_back(0);
}

Expand All @@ -405,7 +398,7 @@ namespace psibase
std::vector<std::shared_ptr<triedent::root>> roots;
std::vector<char> statusBytes;
auto sk = psio::convert_to_key(statusKey());
while (writer.get_greater_equal(topRoot, key, &key, nullptr, &roots))
while (writer.get_greater_equal(impl->topRoot, key, &key, nullptr, &roots))
{
if (key.size() != 1 + irreversible.size() || key[0] != revisionByIdPrefix)
break;
Expand All @@ -415,12 +408,13 @@ namespace psibase
auto status = psio::from_frac<StatusRow>(psio::prevalidated{statusBytes});
if (!status.head)
throw std::runtime_error("Status row is missing head information in fork");
if (!writer.get(topRoot, revisionById(status.head->header.previous), nullptr, nullptr))
writer.remove(topRoot, key);
if (!writer.get(impl->topRoot, revisionById(status.head->header.previous), nullptr,
nullptr))
writer.remove(impl->topRoot, key);
key.push_back(0);
}

writer.set_top_root(topRoot);
writer.set_top_root(impl->topRoot);
} // removeRevisions

void SharedDatabase::setBlockData(Writer& writer,
Expand All @@ -434,16 +428,15 @@ namespace psibase
fullKey.insert(fullKey.end(), blockId.begin(), blockId.end());
fullKey.insert(fullKey.end(), key.begin(), key.end());
std::lock_guard lock{impl->topMutex};
auto topRoot = writer.get_top_root();
writer.upsert(topRoot, fullKey, value);
writer.set_top_root(topRoot);
writer.upsert(impl->topRoot, fullKey, value);
writer.set_top_root(impl->topRoot);
}

std::optional<std::vector<char>> SharedDatabase::getBlockData(Writer& reader,
const Checksum256& blockId,
std::span<const char> key)
{
auto topRoot = reader.get_top_root();
auto topRoot = impl->getTopRoot();
std::vector<char> fullKey;
fullKey.reserve(1 + blockId.size() + key.size());
fullKey.push_back(blockDataPrefix);
Expand Down Expand Up @@ -486,9 +479,8 @@ namespace psibase
writer.splice(impl->subjective, updated, dbKey(r.lower), dbKey(r.upper));
}
std::lock_guard lock{impl->topMutex};
auto r = writer.get_top_root();
writer.upsert(r, subjectiveKey, {&impl->subjective, 1});
writer.set_top_root(std::move(r));
writer.upsert(impl->topRoot, subjectiveKey, {&impl->subjective, 1});
writer.set_top_root(impl->topRoot);
}
return true;
}
Expand Down
8 changes: 5 additions & 3 deletions libraries/psibase/tester/include/psibase/DefaultTestChain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ namespace psibase
public:
// default excludes Docs and TokenUsers
static std::vector<std::string> defaultPackages();
DefaultTestChain(const std::vector<std::string>& packageNames = defaultPackages(),
bool installUI = false,
const DatabaseConfig& dbconfig = {});
DefaultTestChain();
DefaultTestChain(const std::vector<std::string>& packageNames,
bool installUI = false,
const DatabaseConfig& dbconfig = {},
bool pub = true);

AccountNumber addService(const char* acc, const char* filename, bool show = false);
AccountNumber addService(AccountNumber acc, const char* filename, bool show = false);
Expand Down
Loading
Loading