mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-27 01:00:58 +00:00
Compare commits
17 Commits
supported_
...
smart-escr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
543366c1fb | ||
|
|
5820b9cad7 | ||
|
|
338eb50814 | ||
|
|
de2a913ad4 | ||
|
|
2d8fad840a | ||
|
|
bc6455b8b9 | ||
|
|
ca97c98b68 | ||
|
|
26f9488b5d | ||
|
|
fca18f59cd | ||
|
|
d1d3e3c72e | ||
|
|
b9df9c9c45 | ||
|
|
3bb6904946 | ||
|
|
d430010b36 | ||
|
|
d88f7d8f68 | ||
|
|
1825f38a10 | ||
|
|
e70623d0cb | ||
|
|
19631a6d92 |
@@ -207,6 +207,7 @@ xrpl.conditions > xrpl.basics
|
||||
xrpl.conditions > xrpl.protocol
|
||||
xrpl.config > xrpl.basics
|
||||
xrpl.core > xrpl.basics
|
||||
xrpl.core > xrpl.config
|
||||
xrpl.core > xrpl.json
|
||||
xrpl.core > xrpl.protocol
|
||||
xrpl.json > xrpl.basics
|
||||
@@ -310,6 +311,7 @@ xrpld.rpc > xrpl.server
|
||||
xrpld.rpc > xrpl.shamap
|
||||
xrpld.rpc > xrpl.tx
|
||||
xrpld.shamap > xrpl.basics
|
||||
xrpld.shamap > xrpl.core
|
||||
xrpld.shamap > xrpld.core
|
||||
xrpld.shamap > xrpl.nodestore
|
||||
xrpld.shamap > xrpl.protocol
|
||||
|
||||
@@ -91,14 +91,19 @@ def main():
|
||||
if not os.environ.get("TIDY"):
|
||||
return 0
|
||||
|
||||
repo_root = Path(
|
||||
subprocess.check_output(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
cwd=Path(__file__).parent,
|
||||
text=True,
|
||||
).strip()
|
||||
# Derive the repo root from git so this keeps working regardless of where
|
||||
# under the tree this script lives. Fall back to the script location
|
||||
# (bin/pre-commit/ is two levels below the repo root) if git is unavailable.
|
||||
result = subprocess.run(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=Path(__file__).parent,
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
repo_root = Path(result.stdout.strip())
|
||||
else:
|
||||
repo_root = Path(__file__).parent.parent.parent
|
||||
files = staged_files(repo_root)
|
||||
if not files:
|
||||
return 0
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/contract.h>
|
||||
#include <xrpl/beast/insight/Event.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
@@ -107,6 +108,12 @@ public:
|
||||
return j_;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual beast::insight::Event
|
||||
executionTimeEvent(std::string_view name) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
|
||||
[[nodiscard]] virtual bool
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/insight/Event.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/CollectorManager.h>
|
||||
#include <xrpl/core/ServiceRegistry.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
#include <xrpl/protocol/Asset.h>
|
||||
@@ -83,6 +85,15 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
beast::insight::Event
|
||||
executionTimeEvent(std::string_view name) const override
|
||||
{
|
||||
return ctx_.registry.get()
|
||||
.getCollectorManager()
|
||||
.group(std::string{name.data(), name.size()})
|
||||
->makeEvent("finish_time");
|
||||
}
|
||||
|
||||
bool
|
||||
checkSelf() const override
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <xrpl/beast/insight/Meter.h>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
@@ -87,6 +88,7 @@ public:
|
||||
|
||||
Collector::ptr collector;
|
||||
Items items;
|
||||
mutable std::mutex groupMutex;
|
||||
|
||||
explicit GroupsImp(Collector::ptr collector) : collector(std::move(collector))
|
||||
{
|
||||
@@ -97,6 +99,7 @@ public:
|
||||
Group::ptr const&
|
||||
get(std::string const& name) override
|
||||
{
|
||||
std::scoped_lock const _{groupMutex};
|
||||
std::pair<Items::iterator, bool> const result(items.emplace(name, Group::ptr()));
|
||||
Group::ptr& group(result.first->second);
|
||||
if (result.second)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <xrpl/tx/wasm/WasmCommon.h>
|
||||
#include <xrpl/tx/wasm/WasmImportsHelper.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <string>
|
||||
@@ -127,9 +128,19 @@ runEscrowWasm(
|
||||
auto& vm = WasmEngine::instance();
|
||||
// vm.initMaxPages(MAX_PAGES);
|
||||
|
||||
auto const start = std::chrono::steady_clock::now();
|
||||
|
||||
auto const ret =
|
||||
vm.run(wasmCode, hfs, gasLimit, funcName, params, createWasmImport(hfs), hfs.getJournal());
|
||||
|
||||
// microseconds is intentional. The resolution of the StatsD is milliseconds,
|
||||
// but this runs too fast for that.
|
||||
hfs.executionTimeEvent("runEscrowWasm_us")
|
||||
.notify(
|
||||
std::chrono::milliseconds{std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count()});
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
#ifdef DEBUG_OUTPUT
|
||||
@@ -158,9 +169,19 @@ preflightEscrowWasm(
|
||||
auto& vm = WasmEngine::instance();
|
||||
// vm.initMaxPages(MAX_PAGES);
|
||||
|
||||
auto const start = std::chrono::steady_clock::now();
|
||||
|
||||
auto const ret =
|
||||
vm.check(wasmCode, hfs, funcName, params, createWasmImport(hfs), hfs.getJournal());
|
||||
|
||||
// microseconds is intentional. The resolution of the StatsD is milliseconds,
|
||||
// but this runs too fast for that.
|
||||
hfs.executionTimeEvent("preflightEscrowWasm_us")
|
||||
.notify(
|
||||
std::chrono::milliseconds{std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - start)
|
||||
.count()});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <xrpl/basics/Slice.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/insight/Event.h>
|
||||
#include <xrpl/beast/insight/EventImpl.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/ledger/detail/ApplyViewBase.h>
|
||||
#include <xrpl/protocol/AccountID.h>
|
||||
@@ -19,14 +21,76 @@
|
||||
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
/**
|
||||
* Lets a test assert that the WASM execution-timing path fired and inspect the
|
||||
* recorded durations, without needing a StatsD sink or a full Collector.
|
||||
*/
|
||||
struct RecordingEventImpl : public beast::insight::EventImpl
|
||||
{
|
||||
std::size_t count{};
|
||||
value_type last{};
|
||||
value_type total{};
|
||||
value_type min{value_type::max()};
|
||||
value_type max{value_type::min()};
|
||||
std::vector<value_type> samples;
|
||||
bool printOnDestruction{};
|
||||
|
||||
~RecordingEventImpl() override
|
||||
{
|
||||
if (printOnDestruction && count > 0)
|
||||
{
|
||||
std::cout << "Mean (us): " << meanUs() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
notify(value_type const& value) override
|
||||
{
|
||||
++count;
|
||||
last = value;
|
||||
total += value;
|
||||
min = std::min(min, value);
|
||||
max = std::max(max, value);
|
||||
samples.push_back(value);
|
||||
}
|
||||
|
||||
[[nodiscard]] double
|
||||
meanUs() const
|
||||
{
|
||||
return count != 0 ? static_cast<double>(total.count()) / static_cast<double>(count) : 0.0;
|
||||
}
|
||||
|
||||
[[nodiscard]] value_type
|
||||
percentile(double p) const
|
||||
{
|
||||
if (samples.empty())
|
||||
{
|
||||
return value_type{};
|
||||
}
|
||||
auto sorted = samples;
|
||||
std::ranges::sort(sorted);
|
||||
auto rank = static_cast<std::size_t>((p / 100.0) * static_cast<double>(sorted.size()));
|
||||
if (rank >= sorted.size())
|
||||
{
|
||||
rank = sorted.size() - 1;
|
||||
}
|
||||
return sorted[rank];
|
||||
}
|
||||
};
|
||||
|
||||
class TestLedgerDataProvider : public HostFunctions
|
||||
{
|
||||
jtx::Env& env_;
|
||||
@@ -49,6 +113,7 @@ protected:
|
||||
test::jtx::Env& env_;
|
||||
AccountID accountID_;
|
||||
Bytes data_;
|
||||
std::shared_ptr<RecordingEventImpl> execTimeEvent_ = std::make_shared<RecordingEventImpl>();
|
||||
|
||||
public:
|
||||
TestHostFunctions(test::jtx::Env& env) : HostFunctions(env.journal), env_(env)
|
||||
@@ -58,6 +123,21 @@ public:
|
||||
data_ = Bytes{t.begin(), t.end()};
|
||||
}
|
||||
|
||||
// Return an Event backed by our recording impl so a test can assert that
|
||||
// the WASM execution was timed. The name is ignored -- every call records
|
||||
// into the same impl.
|
||||
[[nodiscard]] beast::insight::Event
|
||||
executionTimeEvent(std::string_view name) const override
|
||||
{
|
||||
return beast::insight::Event(execTimeEvent_);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<RecordingEventImpl>&
|
||||
getExecutionTimeEventImpl()
|
||||
{
|
||||
return execTimeEvent_;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::expected<std::uint32_t, HostFunctionError>
|
||||
getLedgerSqn() const override
|
||||
{
|
||||
|
||||
95
src/test/app/WasmPerf_test.cpp
Normal file
95
src/test/app/WasmPerf_test.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include <test/app/wasm_fixtures/fixtures.h>
|
||||
#include <test/jtx/Env.h>
|
||||
|
||||
#include <xrpl/beast/unit_test/suite.h>
|
||||
#include <xrpl/tx/wasm/HostFuncWrapper.h> // IWYU pragma: keep
|
||||
#include <xrpl/tx/wasm/WasmVM.h>
|
||||
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#ifdef _DEBUG
|
||||
// #define DEBUG_OUTPUT 1
|
||||
#endif
|
||||
|
||||
#include <test/app/TestHostFunctions.h>
|
||||
|
||||
namespace xrpl::test {
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<uint8_t>
|
||||
hexToBytes(std::string const& hex)
|
||||
{
|
||||
auto const ws = boost::algorithm::unhex(hex);
|
||||
return Bytes(ws.begin(), ws.end());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
struct WasmPerf_test : public beast::unit_test::Suite
|
||||
{
|
||||
template <typename Functor>
|
||||
void
|
||||
perf(TestHostFunctions& hfs, size_t runs, Functor&& f)
|
||||
{
|
||||
for (auto i = size_t{}; i < runs; ++i)
|
||||
{
|
||||
auto result = f();
|
||||
BEAST_EXPECT(result);
|
||||
}
|
||||
BEAST_EXPECT(hfs.getExecutionTimeEventImpl()->count == runs);
|
||||
}
|
||||
|
||||
void
|
||||
perfEscrowFinish()
|
||||
{
|
||||
testcase("perf escrow finish");
|
||||
using namespace test::jtx;
|
||||
|
||||
static constexpr auto kRuns = 1000;
|
||||
|
||||
auto const wasm = hexToBytes(kAllHostFunctionsWasmHex);
|
||||
|
||||
Env env{*this};
|
||||
auto hfns = TestHostFunctions{env};
|
||||
hfns.getExecutionTimeEventImpl()->printOnDestruction = true;
|
||||
|
||||
perf(hfns, kRuns, [&] {
|
||||
return runEscrowWasm(wasm, hfns, 1'000'000, escrowFunctionName, {}).has_value();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
perfEscrowCreate()
|
||||
{
|
||||
testcase("perf escrow create");
|
||||
using namespace test::jtx;
|
||||
|
||||
static constexpr auto kRuns = 1000;
|
||||
|
||||
auto const wasm = hexToBytes(kAllHostFunctionsWasmHex);
|
||||
|
||||
Env env{*this};
|
||||
auto hfns = TestHostFunctions{env};
|
||||
hfns.getExecutionTimeEventImpl()->printOnDestruction = true;
|
||||
|
||||
perf(hfns, kRuns, [&] { return !preflightEscrowWasm(wasm, hfns, escrowFunctionName); });
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
using namespace test::jtx;
|
||||
|
||||
perfEscrowFinish();
|
||||
perfEscrowCreate();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE_MANUAL(WasmPerf, app, xrpl);
|
||||
|
||||
} // namespace xrpl::test
|
||||
@@ -47,12 +47,14 @@ add(HostFunctions&, wasm_val_vec_t const* params, wasm_val_vec_t* results)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::vector<uint8_t>
|
||||
hexToBytes(std::string const& hex)
|
||||
{
|
||||
auto const ws = boost::algorithm::unhex(hex);
|
||||
return Bytes(ws.begin(), ws.end());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <class IT, class T>
|
||||
unsigned
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <xrpld/app/ledger/OrderBookDBImpl.h>
|
||||
#include <xrpld/app/ledger/TransactionMaster.h>
|
||||
#include <xrpld/app/main/BasicApp.h>
|
||||
#include <xrpld/app/main/CollectorManager.h>
|
||||
#include <xrpld/app/main/GRPCServer.h>
|
||||
#include <xrpld/app/main/LoadManager.h>
|
||||
#include <xrpld/app/main/NodeIdentity.h>
|
||||
@@ -57,6 +56,7 @@
|
||||
#include <xrpl/config/BasicConfig.h>
|
||||
#include <xrpl/config/Constants.h>
|
||||
#include <xrpl/core/ClosureCounter.h>
|
||||
#include <xrpl/core/CollectorManager.h>
|
||||
#include <xrpl/core/HashRouter.h>
|
||||
#include <xrpl/core/Job.h>
|
||||
#include <xrpl/core/NetworkIDService.h>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <xrpld/app/main/CollectorManager.h>
|
||||
|
||||
#include <xrpl/core/CollectorManager.h>
|
||||
|
||||
#include <xrpl/beast/insight/Collector.h>
|
||||
#include <xrpl/beast/insight/Group.h>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/main/CollectorManager.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
#include <xrpld/rpc/detail/WSInfoSub.h>
|
||||
|
||||
@@ -9,6 +8,7 @@
|
||||
#include <xrpl/beast/insight/Event.h>
|
||||
#include <xrpl/beast/net/IPEndpoint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/CollectorManager.h>
|
||||
#include <xrpl/core/JobQueue.h>
|
||||
#include <xrpl/json/Output.h>
|
||||
#include <xrpl/resource/ResourceManager.h>
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
#include <xrpld/app/ledger/InboundLedgers.h>
|
||||
#include <xrpld/app/ledger/LedgerMaster.h>
|
||||
#include <xrpld/app/main/Application.h>
|
||||
#include <xrpld/app/main/CollectorManager.h>
|
||||
#include <xrpld/app/main/Tuning.h>
|
||||
#include <xrpld/core/Config.h>
|
||||
|
||||
#include <xrpl/basics/Log.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/chrono.h>
|
||||
#include <xrpl/core/CollectorManager.h>
|
||||
#include <xrpl/shamap/FullBelowCache.h>
|
||||
#include <xrpl/shamap/TreeNodeCache.h>
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpld/app/main/CollectorManager.h>
|
||||
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
#include <xrpl/core/CollectorManager.h>
|
||||
#include <xrpl/nodestore/Database.h>
|
||||
#include <xrpl/protocol/Protocol.h>
|
||||
#include <xrpl/shamap/Family.h>
|
||||
|
||||
Reference in New Issue
Block a user