Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #7654 from EOSIO/checktime_timer_only
Browse files Browse the repository at this point in the history
exclusively use timer for checktime
  • Loading branch information
spoonincode authored Aug 15, 2019
2 parents f4d0b0b + 858379c commit 725d4f0
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 154 deletions.
12 changes: 6 additions & 6 deletions libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ file(GLOB HEADERS "include/eosio/chain/*.hpp"
"${CMAKE_CURRENT_BINARY_DIR}/include/eosio/chain/core_symbol.hpp" )

if(APPLE AND UNIX)
set(CHECKTIME_TIMER_IMPL checktime_timer_macos.cpp)
set(PLATFORM_TIMER_IMPL platform_timer_macos.cpp)
else()
try_run(POSIX_TIMER_TEST_RUN_RESULT POSIX_TIMER_TEST_COMPILE_RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/checktime_timer_posix_test.c)
try_run(POSIX_TIMER_TEST_RUN_RESULT POSIX_TIMER_TEST_COMPILE_RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/platform_timer_posix_test.c)
if(POSIX_TIMER_TEST_RUN_RESULT EQUAL 0)
set(CHECKTIME_TIMER_IMPL checktime_timer_posix.cpp)
set(PLATFORM_TIMER_IMPL platform_timer_posix.cpp)
else()
set(CHECKTIME_TIMER_IMPL checktime_timer_dummy.cpp)
set(PLATFORM_TIMER_IMPL platform_timer_asio_fallback.cpp)
endif()
endif()

Expand Down Expand Up @@ -65,8 +65,8 @@ add_library( eosio_chain
genesis_intrinsics.cpp
whitelisted_intrinsics.cpp
thread_utils.cpp
checktime_timer_calibrate.cpp
${CHECKTIME_TIMER_IMPL}
platform_timer_accuracy.cpp
${PLATFORM_TIMER_IMPL}
${HEADERS}
)

Expand Down
16 changes: 0 additions & 16 deletions libraries/chain/checktime_timer_dummy.cpp

This file was deleted.

13 changes: 8 additions & 5 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/chain_snapshot.hpp>
#include <eosio/chain/thread_utils.hpp>
#include <eosio/chain/checktime_timer.hpp>
#include <eosio/chain/platform_timer.hpp>

#include <chainbase/chainbase.hpp>
#include <fc/io/json.hpp>
Expand Down Expand Up @@ -233,7 +233,7 @@ struct controller_impl {
bool trusted_producer_light_validation = false;
uint32_t snapshot_head_block = 0;
named_thread_pool thread_pool;
checktime_timer timer;
platform_timer timer;

typedef pair<scope_name,action_name> handler_key;
map< account_name, map<handler_key, apply_handler> > apply_handlers;
Expand Down Expand Up @@ -1036,7 +1036,8 @@ struct controller_impl {
etrx.set_reference_block( self.head_block_id() );
}

transaction_context trx_context( self, etrx, etrx.id(), timer, start );
transaction_checktime_timer trx_timer(timer);
transaction_context trx_context( self, etrx, etrx.id(), std::move(trx_timer), start );
trx_context.deadline = deadline;
trx_context.explicit_billed_cpu_time = explicit_billed_cpu_time;
trx_context.billed_cpu_time_us = billed_cpu_time_us;
Expand Down Expand Up @@ -1158,7 +1159,8 @@ struct controller_impl {

uint32_t cpu_time_to_bill_us = billed_cpu_time_us;

transaction_context trx_context( self, dtrx, gtrx.trx_id, timer );
transaction_checktime_timer trx_timer(timer);
transaction_context trx_context( self, dtrx, gtrx.trx_id, std::move(trx_timer) );
trx_context.leeway = fc::microseconds(0); // avoid stealing cpu resource
trx_context.deadline = deadline;
trx_context.explicit_billed_cpu_time = explicit_billed_cpu_time;
Expand Down Expand Up @@ -1323,7 +1325,8 @@ struct controller_impl {
}

const signed_transaction& trn = trx->packed_trx()->get_signed_transaction();
transaction_context trx_context(self, trn, trx->id(), timer, start);
transaction_checktime_timer trx_timer(timer);
transaction_context trx_context(self, trn, trx->id(), std::move(trx_timer), start);
if ((bool)subjective_cpu_leeway && pending->_block_status == controller::block_status::incomplete) {
trx_context.leeway = *subjective_cpu_leeway;
}
Expand Down
27 changes: 0 additions & 27 deletions libraries/chain/include/eosio/chain/checktime_timer_calibrate.hpp

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

namespace eosio { namespace chain {

struct checktime_timer {
checktime_timer();
~checktime_timer();
struct platform_timer {
platform_timer();
~platform_timer();

void start(fc::time_point tp);
void stop();
Expand All @@ -21,13 +21,4 @@ struct checktime_timer {
fc::fwd<impl,fwd_size> my;
};

struct checktime_timer_scoped_stop {
checktime_timer_scoped_stop(checktime_timer& t) : _timer(t) {}
~checktime_timer_scoped_stop() {
_timer.stop();
}
private:
checktime_timer& _timer;
};

}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

namespace eosio { namespace chain {

struct platform_timer;
void compute_and_print_timer_accuracy(platform_timer& t);

}}
25 changes: 21 additions & 4 deletions libraries/chain/include/eosio/chain/transaction_context.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
#pragma once
#include <eosio/chain/controller.hpp>
#include <eosio/chain/trace.hpp>
#include <eosio/chain/checktime_timer.hpp>
#include <eosio/chain/platform_timer.hpp>
#include <signal.h>

namespace eosio { namespace chain {

struct transaction_checktime_timer {
public:
transaction_checktime_timer() = delete;
transaction_checktime_timer(const transaction_checktime_timer&) = delete;
transaction_checktime_timer(transaction_checktime_timer&&) = default;
~transaction_checktime_timer();

void start(fc::time_point tp);
void stop();

volatile sig_atomic_t& expired;
private:
platform_timer& _timer;

transaction_checktime_timer(platform_timer& timer);
friend controller_impl;
};

class transaction_context {
private:
void init( uint64_t initial_net_usage);
Expand All @@ -15,7 +33,7 @@ namespace eosio { namespace chain {
transaction_context( controller& c,
const signed_transaction& t,
const transaction_id_type& trx_id,
checktime_timer& timer,
transaction_checktime_timer&& timer,
fc::time_point start = fc::time_point::now() );

void init_for_implicit_trx( uint64_t initial_net_usage = 0 );
Expand Down Expand Up @@ -128,8 +146,7 @@ namespace eosio { namespace chain {
fc::microseconds billed_time;
fc::microseconds billing_timer_duration_limit;

checktime_timer& deadline_timer;
checktime_timer_scoped_stop timer_stopper;
transaction_checktime_timer transaction_timer;
};

} }
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include <eosio/chain/checktime_timer_calibrate.hpp>
#include <eosio/chain/checktime_timer.hpp>
#include <eosio/chain/platform_timer_accuracy.hpp>
#include <eosio/chain/platform_timer.hpp>

#include <fc/time.hpp>
#include <fc/log/logger.hpp>
Expand All @@ -18,10 +18,7 @@ namespace eosio { namespace chain {

namespace bacc = boost::accumulators;

checktime_timer_calibrate::checktime_timer_calibrate() = default;
checktime_timer_calibrate::~checktime_timer_calibrate() = default;

void checktime_timer_calibrate::do_calibrate(checktime_timer& timer) {
void compute_and_print_timer_accuracy(platform_timer& timer) {
static std::mutex m;
static bool once_is_enough;

Expand All @@ -33,7 +30,7 @@ void checktime_timer_calibrate::do_calibrate(checktime_timer& timer) {
bacc::accumulator_set<int, bacc::stats<bacc::tag::mean, bacc::tag::min, bacc::tag::max, bacc::tag::variance>, float> samples;

//keep longest first in list. You're effectively going to take test_intervals[0]*sizeof(test_intervals[0])
//time to do the the "calibration"
//time to do the the test
int test_intervals[] = {50000, 10000, 5000, 1000, 500, 100, 50, 10};

for(int& interval : test_intervals) {
Expand All @@ -56,21 +53,17 @@ void checktime_timer_calibrate::do_calibrate(checktime_timer& timer) {
samples(timer_slop, bacc::weight = interval/(float)test_intervals[0]);
}
}
_timer_overhead = bacc::mean(samples) + sqrt(bacc::variance(samples))*2; //target 95% of expirations before deadline
_use_timer = _timer_overhead < 1000;

#define TIMER_STATS_FORMAT "min:${min}us max:${max}us mean:${mean}us stddev:${stddev}us"
#define TIMER_STATS \
("min", bacc::min(samples))("max", bacc::max(samples)) \
("mean", (int)bacc::mean(samples))("stddev", (int)sqrt(bacc::variance(samples))) \
("t", _timer_overhead)
("mean", (int)bacc::mean(samples))("stddev", (int)sqrt(bacc::variance(samples)))

if(_use_timer)
ilog("Using ${t}us deadline timer for checktime: " TIMER_STATS_FORMAT, TIMER_STATS);
else
wlog("Using polled checktime; deadline timer too inaccurate: " TIMER_STATS_FORMAT, TIMER_STATS);
ilog("Checktime timer accuracy: " TIMER_STATS_FORMAT, TIMER_STATS);
if(bacc::mean(samples) + sqrt(bacc::variance(samples))*2 > 250)
wlog("Checktime timer accuracy on this platform and hardware combination is poor; accuracy of subjective transaction deadline enforcement will suffer");

once_is_enough = true;
}

}}
}}
91 changes: 91 additions & 0 deletions libraries/chain/platform_timer_asio_fallback.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include <eosio/chain/platform_timer.hpp>
#include <eosio/chain/platform_timer_accuracy.hpp>

#include <fc/fwd_impl.hpp>
#include <fc/log/logger_config.hpp> //set_os_thread_name()

#include <boost/asio.hpp>

#include <mutex>
#include <thread>

namespace eosio { namespace chain {

//a thread is shared for all instances
static std::mutex timer_ref_mutex;
static unsigned refcount;
static std::thread checktime_thread;
static std::unique_ptr<boost::asio::io_service> checktime_ios;

struct platform_timer::impl {
std::unique_ptr<boost::asio::high_resolution_timer> timer;
};

platform_timer::platform_timer() {
static_assert(sizeof(impl) <= fwd_size);

std::lock_guard guard(timer_ref_mutex);

if(refcount++ == 0) {
std::promise<void> p;
checktime_thread = std::thread([&p]() {
fc::set_os_thread_name("checktime");
checktime_ios = std::make_unique<boost::asio::io_service>();
boost::asio::io_service::work work(*checktime_ios);
p.set_value();

checktime_ios->run();
});
p.get_future().get();
}

my->timer = std::make_unique<boost::asio::high_resolution_timer>(*checktime_ios);

//compute_and_print_timer_accuracy(*this);
}

platform_timer::~platform_timer() {
stop();
if(std::lock_guard guard(timer_ref_mutex); --refcount == 0) {
checktime_ios->stop();
checktime_thread.join();
checktime_ios.reset();
}
}

void platform_timer::start(fc::time_point tp) {
if(tp == fc::time_point::maximum()) {
expired = 0;
return;
}
fc::microseconds x = tp.time_since_epoch() - fc::time_point::now().time_since_epoch();
if(x.count() <= 0)
expired = 1;
else {
#if 0
std::promise<void> p;
checktime_ios->post([&p,this]() {
expired = 0;
p.set_value();
});
p.get_future().get();
#endif
expired = 0;
my->timer->expires_after(std::chrono::microseconds((int)x.count()));
my->timer->async_wait([this](const boost::system::error_code& ec) {
if(ec)
return;
expired = 1;
});
}
}

void platform_timer::stop() {
if(expired)
return;

my->timer->cancel();
expired = 1;
}

}}
Loading

0 comments on commit 725d4f0

Please sign in to comment.