mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated smartcontracts
- updated smartcontracts - updated fullnode database layout - fixed memory leak in blockchain-explorer - updated tonlib
This commit is contained in:
parent
9c9248a9ae
commit
c860ce3d1e
104 changed files with 7309 additions and 1335 deletions
|
@ -1145,6 +1145,273 @@ void run_queue_bench(int n, int m) {
|
|||
#endif
|
||||
}
|
||||
|
||||
struct Sem {
|
||||
public:
|
||||
void post() {
|
||||
if (++cnt_ == 0) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(mutex_);
|
||||
}
|
||||
cnd_.notify_one();
|
||||
}
|
||||
}
|
||||
void wait(int cnt = 1) {
|
||||
auto was = cnt_.fetch_sub(cnt);
|
||||
if (was >= cnt) {
|
||||
return;
|
||||
}
|
||||
std::unique_lock<std::mutex> lk(mutex_);
|
||||
cnd_.wait(lk, [&] { return cnt_ >= 0; });
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cnd_;
|
||||
std::atomic<int> cnt_{0};
|
||||
};
|
||||
|
||||
class ChainedSpawn : public td::Benchmark {
|
||||
public:
|
||||
ChainedSpawn(bool use_io) : use_io_(use_io) {
|
||||
}
|
||||
std::string get_description() const {
|
||||
return PSTRING() << "Chained create_actor use_io(" << use_io_ << ")";
|
||||
}
|
||||
|
||||
void run(int n) {
|
||||
class Task : public td::actor::Actor {
|
||||
public:
|
||||
Task(int n, Sem *sem) : n_(n), sem_(sem) {
|
||||
}
|
||||
void start_up() override {
|
||||
if (n_ == 0) {
|
||||
sem_->post();
|
||||
} else {
|
||||
td::actor::create_actor<Task>("Task", n_ - 1, sem_).release();
|
||||
}
|
||||
stop();
|
||||
};
|
||||
|
||||
private:
|
||||
int n_;
|
||||
Sem *sem_{nullptr};
|
||||
};
|
||||
td::actor::Scheduler scheduler{{8}};
|
||||
auto sch = td::thread([&] { scheduler.run(); });
|
||||
|
||||
Sem sem;
|
||||
scheduler.run_in_context_external([&] {
|
||||
for (int i = 0; i < n; i++) {
|
||||
td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), 1000, &sem)
|
||||
.release();
|
||||
sem.wait();
|
||||
}
|
||||
td::actor::SchedulerContext::get()->stop();
|
||||
});
|
||||
|
||||
sch.join();
|
||||
}
|
||||
|
||||
private:
|
||||
bool use_io_{false};
|
||||
};
|
||||
|
||||
class ChainedSpawnInplace : public td::Benchmark {
|
||||
public:
|
||||
ChainedSpawnInplace(bool use_io) : use_io_(use_io) {
|
||||
}
|
||||
std::string get_description() const {
|
||||
return PSTRING() << "Chained send_signal(self) use_io(" << use_io_ << ")";
|
||||
}
|
||||
|
||||
void run(int n) {
|
||||
class Task : public td::actor::Actor {
|
||||
public:
|
||||
Task(int n, Sem *sem) : n_(n), sem_(sem) {
|
||||
}
|
||||
void loop() override {
|
||||
if (n_ == 0) {
|
||||
sem_->post();
|
||||
stop();
|
||||
} else {
|
||||
n_--;
|
||||
send_signals(actor_id(this), td::actor::ActorSignals::wakeup());
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
int n_;
|
||||
Sem *sem_;
|
||||
};
|
||||
td::actor::Scheduler scheduler{{8}};
|
||||
auto sch = td::thread([&] { scheduler.run(); });
|
||||
|
||||
Sem sem;
|
||||
scheduler.run_in_context_external([&] {
|
||||
for (int i = 0; i < n; i++) {
|
||||
td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), 1000, &sem)
|
||||
.release();
|
||||
sem.wait();
|
||||
}
|
||||
td::actor::SchedulerContext::get()->stop();
|
||||
});
|
||||
|
||||
sch.join();
|
||||
}
|
||||
|
||||
private:
|
||||
bool use_io_{false};
|
||||
};
|
||||
|
||||
class PingPong : public td::Benchmark {
|
||||
public:
|
||||
PingPong(bool use_io) : use_io_(use_io) {
|
||||
}
|
||||
std::string get_description() const {
|
||||
return PSTRING() << "PingPong use_io(" << use_io_ << ")";
|
||||
}
|
||||
|
||||
void run(int n) {
|
||||
if (n < 3) {
|
||||
n = 3;
|
||||
}
|
||||
class Task : public td::actor::Actor {
|
||||
public:
|
||||
explicit Task(Sem *sem) : sem_(sem) {
|
||||
}
|
||||
void set_peer(td::actor::ActorId<Task> peer) {
|
||||
peer_ = peer;
|
||||
}
|
||||
void ping(int n) {
|
||||
if (n < 0) {
|
||||
sem_->post();
|
||||
stop();
|
||||
}
|
||||
send_closure(peer_, &Task::ping, n - 1);
|
||||
}
|
||||
|
||||
private:
|
||||
td::actor::ActorId<Task> peer_;
|
||||
Sem *sem_;
|
||||
};
|
||||
td::actor::Scheduler scheduler{{8}};
|
||||
auto sch = td::thread([&] { scheduler.run(); });
|
||||
|
||||
Sem sem;
|
||||
scheduler.run_in_context_external([&] {
|
||||
for (int i = 0; i < n; i++) {
|
||||
auto a = td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem)
|
||||
.release();
|
||||
auto b = td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem)
|
||||
.release();
|
||||
send_closure(a, &Task::set_peer, b);
|
||||
send_closure(b, &Task::set_peer, a);
|
||||
send_closure(a, &Task::ping, 1000);
|
||||
sem.wait(2);
|
||||
}
|
||||
td::actor::SchedulerContext::get()->stop();
|
||||
});
|
||||
|
||||
sch.join();
|
||||
}
|
||||
|
||||
private:
|
||||
bool use_io_{false};
|
||||
};
|
||||
|
||||
class SpawnMany : public td::Benchmark {
|
||||
public:
|
||||
SpawnMany(bool use_io) : use_io_(use_io) {
|
||||
}
|
||||
std::string get_description() const {
|
||||
return PSTRING() << "Spawn many use_io(" << use_io_ << ")";
|
||||
}
|
||||
|
||||
void run(int n) {
|
||||
class Task : public td::actor::Actor {
|
||||
public:
|
||||
Task(Sem *sem) : sem_(sem) {
|
||||
}
|
||||
void start_up() override {
|
||||
sem_->post();
|
||||
stop();
|
||||
};
|
||||
|
||||
private:
|
||||
Sem *sem_;
|
||||
};
|
||||
td::actor::Scheduler scheduler{{8}};
|
||||
Sem sem;
|
||||
auto sch = td::thread([&] { scheduler.run(); });
|
||||
scheduler.run_in_context_external([&] {
|
||||
for (int i = 0; i < n; i++) {
|
||||
int spawn_cnt = 10000;
|
||||
for (int j = 0; j < spawn_cnt; j++) {
|
||||
td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), &sem).release();
|
||||
}
|
||||
sem.wait(spawn_cnt);
|
||||
}
|
||||
td::actor::SchedulerContext::get()->stop();
|
||||
});
|
||||
sch.join();
|
||||
}
|
||||
|
||||
private:
|
||||
bool use_io_{false};
|
||||
};
|
||||
|
||||
class YieldMany : public td::Benchmark {
|
||||
public:
|
||||
YieldMany(bool use_io) : use_io_(use_io) {
|
||||
}
|
||||
std::string get_description() const {
|
||||
return PSTRING() << "Yield many use_io(" << use_io_ << ")";
|
||||
}
|
||||
|
||||
void run(int n) {
|
||||
int num_yield = 1000;
|
||||
unsigned tasks_per_cpu = 50;
|
||||
unsigned cpu_n = td::thread::hardware_concurrency();
|
||||
class Task : public td::actor::Actor {
|
||||
public:
|
||||
explicit Task(int n, Sem *sem) : n_(n), sem_(sem) {
|
||||
}
|
||||
void loop() override {
|
||||
if (n_ == 0) {
|
||||
sem_->post();
|
||||
stop();
|
||||
} else {
|
||||
n_--;
|
||||
yield();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
int n_;
|
||||
Sem *sem_;
|
||||
};
|
||||
td::actor::Scheduler scheduler{{cpu_n}};
|
||||
auto sch = td::thread([&] { scheduler.run(); });
|
||||
unsigned tasks = tasks_per_cpu * cpu_n;
|
||||
Sem sem;
|
||||
scheduler.run_in_context_external([&] {
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (unsigned j = 0; j < tasks; j++) {
|
||||
td::actor::create_actor<Task>(td::actor::ActorOptions().with_name("Task").with_poll(use_io_), num_yield, &sem)
|
||||
.release();
|
||||
}
|
||||
sem.wait(tasks);
|
||||
}
|
||||
});
|
||||
|
||||
scheduler.run_in_context_external([&] { td::actor::SchedulerContext::get()->stop(); });
|
||||
sch.join();
|
||||
}
|
||||
|
||||
private:
|
||||
bool use_io_{false};
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 1) {
|
||||
if (argv[1][0] == 'a') {
|
||||
|
@ -1159,6 +1426,18 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bench(YieldMany(false));
|
||||
bench(YieldMany(true));
|
||||
bench(SpawnMany(false));
|
||||
bench(SpawnMany(true));
|
||||
bench(PingPong(false));
|
||||
bench(PingPong(true));
|
||||
bench(ChainedSpawnInplace(false));
|
||||
bench(ChainedSpawnInplace(true));
|
||||
bench(ChainedSpawn(false));
|
||||
bench(ChainedSpawn(true));
|
||||
return 0;
|
||||
|
||||
bench(ActorDummyQuery());
|
||||
bench(ActorExecutorBenchmark());
|
||||
bench(ActorSignalQuery());
|
||||
|
|
|
@ -225,6 +225,7 @@ class Promise {
|
|||
promise_->set_error(std::move(error));
|
||||
promise_.reset();
|
||||
}
|
||||
|
||||
void set_result(Result<T> &&result) {
|
||||
if (!promise_) {
|
||||
return;
|
||||
|
@ -260,6 +261,28 @@ class Promise {
|
|||
explicit operator bool() {
|
||||
return static_cast<bool>(promise_);
|
||||
}
|
||||
template <class V, class F>
|
||||
auto do_wrap(V &&value, F &&func) {
|
||||
if (value.is_ok()) {
|
||||
set_result(func(value.move_as_ok()));
|
||||
} else {
|
||||
set_error(value.move_as_error());
|
||||
}
|
||||
}
|
||||
|
||||
template <class F>
|
||||
auto do_wrap(td::Status status, F &&func) {
|
||||
set_error(std::move(status));
|
||||
}
|
||||
|
||||
template <class F>
|
||||
auto wrap(F &&func) {
|
||||
return [promise = std::move(*this), func = std::move(func)](auto &&res) mutable {
|
||||
promise.do_wrap(std::move(res), std::move(func));
|
||||
};
|
||||
}
|
||||
template <class... ArgsT>
|
||||
auto send_closure(ArgsT &&... args);
|
||||
|
||||
private:
|
||||
std::unique_ptr<PromiseInterface<T>> promise_;
|
||||
|
|
|
@ -162,4 +162,29 @@ void send_signals_later(ActorIdT &&actor_id, ActorSignals signals) {
|
|||
detail::send_signals_later(id.as_actor_ref(), signals);
|
||||
}
|
||||
} // namespace actor
|
||||
|
||||
class SendClosure {
|
||||
public:
|
||||
template <class... ArgsT>
|
||||
void operator()(ArgsT &&... args) const {
|
||||
td::actor::send_closure(std::forward<ArgsT>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
template <class... ArgsT>
|
||||
auto Promise<T>::send_closure(ArgsT &&... args) {
|
||||
return [promise = std::move(*this), t = std::make_tuple(std::forward<ArgsT>(args)...)](auto &&r_res) mutable {
|
||||
TRY_RESULT_PROMISE(promise, res, std::move(r_res));
|
||||
td::call_tuple(SendClosure(), std::tuple_cat(std::move(t), std::make_tuple(std::move(res), std::move(promise))));
|
||||
};
|
||||
}
|
||||
|
||||
template <class... ArgsT>
|
||||
auto promise_send_closure(ArgsT &&... args) {
|
||||
return [t = std::make_tuple(std::forward<ArgsT>(args)...)](auto &&res) mutable {
|
||||
td::call_tuple(SendClosure(), std::tuple_cat(std::move(t), std::make_tuple(std::move(res))));
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue