75
75
#include " block/precompiled-smc/PrecompiledSmartContract.h"
76
76
#include " interfaces/validator-manager.h"
77
77
78
+ #if TON_USE_JEMALLOC
79
+ #include < jemalloc/jemalloc.h>
80
+ #endif
81
+
78
82
Config::Config () {
79
83
out_port = 3278 ;
80
84
full_node = ton::PublicKeyHash::zero ();
@@ -1179,6 +1183,55 @@ class CheckDhtServerStatusQuery : public td::actor::Actor {
1179
1183
td::Promise<td::BufferSlice> promise_;
1180
1184
};
1181
1185
1186
+ #if TON_USE_JEMALLOC
1187
+ class JemallocStatsWriter : public td ::actor::Actor {
1188
+ public:
1189
+ void start_up () override {
1190
+ alarm ();
1191
+ }
1192
+
1193
+ void alarm () override {
1194
+ alarm_timestamp () = td::Timestamp::in (60.0 );
1195
+ auto r_stats = get_stats ();
1196
+ if (r_stats.is_error ()) {
1197
+ LOG (WARNING) << " Jemalloc stats error : " << r_stats.move_as_error ();
1198
+ } else {
1199
+ auto s = r_stats.move_as_ok ();
1200
+ LOG (WARNING) << " JEMALLOC_STATS : [ timestamp=" << (ton::UnixTime)td::Clocks::system ()
1201
+ << " allocated=" << s.allocated << " active=" << s.active << " metadata=" << s.metadata
1202
+ << " resident=" << s.resident << " ]" ;
1203
+ }
1204
+ }
1205
+
1206
+ private:
1207
+ struct JemallocStats {
1208
+ size_t allocated, active, metadata, resident;
1209
+ };
1210
+
1211
+ static td::Result<JemallocStats> get_stats () {
1212
+ size_t sz = sizeof (size_t );
1213
+ static size_t epoch = 1 ;
1214
+ if (mallctl (" epoch" , &epoch, &sz, &epoch, sz)) {
1215
+ return td::Status::Error (" Failed to refrash stats" );
1216
+ }
1217
+ JemallocStats stats;
1218
+ if (mallctl (" stats.allocated" , &stats.allocated , &sz, nullptr , 0 )) {
1219
+ return td::Status::Error (" Cannot get stats.allocated" );
1220
+ }
1221
+ if (mallctl (" stats.active" , &stats.active , &sz, nullptr , 0 )) {
1222
+ return td::Status::Error (" Cannot get stats.active" );
1223
+ }
1224
+ if (mallctl (" stats.metadata" , &stats.metadata , &sz, nullptr , 0 )) {
1225
+ return td::Status::Error (" Cannot get stats.metadata" );
1226
+ }
1227
+ if (mallctl (" stats.resident" , &stats.resident , &sz, nullptr , 0 )) {
1228
+ return td::Status::Error (" Cannot get stats.resident" );
1229
+ }
1230
+ return stats;
1231
+ }
1232
+ };
1233
+ #endif
1234
+
1182
1235
void ValidatorEngine::set_local_config (std::string str) {
1183
1236
local_config_ = str;
1184
1237
}
@@ -1202,6 +1255,9 @@ void ValidatorEngine::schedule_shutdown(double at) {
1202
1255
}
1203
1256
void ValidatorEngine::start_up () {
1204
1257
alarm_timestamp () = td::Timestamp::in (1.0 + td::Random::fast (0 , 100 ) * 0.01 );
1258
+ #if TON_USE_JEMALLOC
1259
+ td::actor::create_actor<JemallocStatsWriter>(" mem-stat" ).release ();
1260
+ #endif
1205
1261
}
1206
1262
1207
1263
void ValidatorEngine::alarm () {
@@ -1412,6 +1468,18 @@ td::Status ValidatorEngine::load_global_config() {
1412
1468
}
1413
1469
validator_options_.write ().set_hardforks (std::move (h));
1414
1470
1471
+ auto r_total_ram = td::get_total_ram ();
1472
+ if (r_total_ram.is_error ()) {
1473
+ LOG (ERROR) << " Failed to get total RAM size: " << r_total_ram.move_as_error ();
1474
+ } else {
1475
+ td::uint64 total_ram = r_total_ram.move_as_ok ();
1476
+ LOG (WARNING) << " Total RAM = " << td::format::as_size (total_ram);
1477
+ if (total_ram >= (90ULL << 30 )) {
1478
+ fast_state_serializer_enabled_ = true ;
1479
+ }
1480
+ }
1481
+ validator_options_.write ().set_fast_state_serializer_enabled (fast_state_serializer_enabled_);
1482
+
1415
1483
return td::Status::OK ();
1416
1484
}
1417
1485
@@ -3894,7 +3962,7 @@ void need_scheduler_status(int sig) {
3894
3962
need_scheduler_status_flag.store (true );
3895
3963
}
3896
3964
3897
- void dump_memory_stats () {
3965
+ void dump_memprof_stats () {
3898
3966
if (!is_memprof_on ()) {
3899
3967
return ;
3900
3968
}
@@ -3919,8 +3987,20 @@ void dump_memory_stats() {
3919
3987
LOG (WARNING) << td::tag (" fast_backtrace_success_rate" , get_fast_backtrace_success_rate ());
3920
3988
}
3921
3989
3990
+ void dump_jemalloc_prof () {
3991
+ #if TON_USE_JEMALLOC
3992
+ const char *filename = " /tmp/validator-jemalloc.dump" ;
3993
+ if (mallctl (" prof.dump" , nullptr , nullptr , &filename, sizeof (const char *)) == 0 ) {
3994
+ LOG (ERROR) << " Written jemalloc dump to " << filename;
3995
+ } else {
3996
+ LOG (ERROR) << " Failed to write jemalloc dump to " << filename;
3997
+ }
3998
+ #endif
3999
+ }
4000
+
3922
4001
void dump_stats () {
3923
- dump_memory_stats ();
4002
+ dump_memprof_stats ();
4003
+ dump_jemalloc_prof ();
3924
4004
LOG (WARNING) << td::NamedThreadSafeCounter::get_default ();
3925
4005
}
3926
4006
@@ -4158,6 +4238,13 @@ int main(int argc, char *argv[]) {
4158
4238
acts.push_back ([&x, v]() { td::actor::send_closure (x, &ValidatorEngine::set_catchain_max_block_delay, v); });
4159
4239
return td::Status::OK ();
4160
4240
});
4241
+ p.add_option (
4242
+ ' \0 ' , " fast-state-serializer" ,
4243
+ " faster persistent state serializer, but requires more RAM (enabled automatically on machines with >= 90GB RAM)" ,
4244
+ [&]() {
4245
+ acts.push_back (
4246
+ [&x]() { td::actor::send_closure (x, &ValidatorEngine::set_fast_state_serializer_enabled, true ); });
4247
+ });
4161
4248
auto S = p.run (argc, argv);
4162
4249
if (S.is_error ()) {
4163
4250
LOG (ERROR) << " failed to parse options: " << S.move_as_error ();
0 commit comments