Adding some stats for serverinfo

This commit is contained in:
KimLS 2019-04-09 00:14:15 -07:00
parent e9dcc88f29
commit d0af7e4fa9
7 changed files with 235 additions and 64 deletions

View file

@ -195,6 +195,7 @@ SET(common_headers
say_link.h
seperator.h
serialize_buffer.h
server_stats.h
serverinfo.h
servertalk.h
shareddb.h

View file

@ -6,6 +6,7 @@
#include "../opcodemgr.h"
#include "../eqemu_logsys.h"
#include "../eqemu_logsys_fmt.h"
#include "../server_stats.h"
#include "daybreak_connection.h"
#include <thread>
#include <concurrentqueue.h>
@ -85,20 +86,27 @@ void EQ::Net::ConcurrentEQStreamManager::_BackgroundThread() {
_impl->background_update_stats_timer.reset(new EQ::Timer(&loop, 500, true,
std::bind(&ConcurrentEQStreamManager::_BackgroundUpdateStatsTimer, this, std::placeholders::_1)));
int sleep_time = 16;
while (true == _impl->background_running) {
auto now = std::chrono::high_resolution_clock::now();
EQ::ServerStats::Get().BeginNetworkFrame();
loop.Process();
switch (_impl->priority) {
case EQStreamPriority::Low:
Sleep(10);
sleep_time = 200;
break;
case EQStreamPriority::Normal:
Sleep(5);
sleep_time = 100;
break;
case EQStreamPriority::High:
Sleep(1);
sleep_time = 16;
break;
}
EQ::ServerStats::Get().EndNetworkFrame();
auto end = now + std::chrono::milliseconds(sleep_time);
std::this_thread::sleep_until(end);
}
_impl->background_loop_timer.release();

164
common/server_stats.h Normal file
View file

@ -0,0 +1,164 @@
#pragma once
#include <chrono>
#include <string>
#include <mutex>
#include <vector>
#include <uv.h>
namespace EQ
{
struct ResourceUsageStats
{
double user_cpu_time;
double system_cpu_time;
};
struct OSInfoStats
{
std::string system_name;
std::string release;
std::string version;
std::string machine;
};
class ServerStats
{
typedef std::chrono::high_resolution_clock clock;
typedef std::chrono::high_resolution_clock::time_point timestamp;
typedef std::chrono::duration<double> seconds;
public:
~ServerStats() {
}
static ServerStats& Get() {
static ServerStats inst;
return inst;
}
void BeginFrame()
{
auto now = clock::now();
auto inactive = now - m_last_end;
m_inactive_time = std::chrono::duration_cast<seconds>(inactive).count();
m_last_begin = now;
}
void EndFrame() {
auto now = clock::now();
auto active = now - m_last_begin;
m_active_time = std::chrono::duration_cast<seconds>(active).count();
m_last_end = now;
}
double InactiveFrameTime() const {
return m_inactive_time;
}
double ActiveFrameTime() const {
return m_active_time;
}
double FrameTime() const {
return m_inactive_time + m_active_time;
}
void BeginNetworkFrame()
{
std::lock_guard<std::mutex> lock(m_network_lock);
auto now = clock::now();
auto inactive = now - m_network_last_end;
m_network_inactive_time = std::chrono::duration_cast<seconds>(inactive).count();
m_network_last_begin = now;
}
void EndNetworkFrame()
{
std::lock_guard<std::mutex> lock(m_network_lock);
auto now = clock::now();
auto active = now - m_network_last_begin;
m_network_active_time = std::chrono::duration_cast<seconds>(active).count();
m_network_last_end = now;
}
double NetworkInactiveFrameTime() {
std::lock_guard<std::mutex> lock(m_network_lock);
return m_network_inactive_time;
}
double NetworkActiveFrameTime() {
std::lock_guard<std::mutex> lock(m_network_lock);
return m_network_active_time;
}
double NetworkFrameTime() {
std::lock_guard<std::mutex> lock(m_network_lock);
return m_network_inactive_time + m_network_active_time;
}
//OS Related Stuff
int PID() {
return uv_os_getpid();
}
int ParentPID() {
return uv_os_getppid();
}
ResourceUsageStats ResourceUsage() {
uv_rusage_t usage;
if(0 != uv_getrusage(&usage)) {
return ResourceUsageStats();
}
ResourceUsageStats ret;
ret.user_cpu_time = static_cast<double>(usage.ru_utime.tv_sec) + static_cast<double>(usage.ru_utime.tv_usec / 1000000.0);
ret.system_cpu_time = static_cast<double>(usage.ru_stime.tv_sec) + static_cast<double>(usage.ru_stime.tv_usec / 1000000.0);
return ret;
}
OSInfoStats OSInfo() {
uv_utsname_t osn;
if (0 != uv_os_uname(&osn)) {
return OSInfoStats();
}
OSInfoStats ret;
ret.system_name = osn.sysname;
ret.release = osn.release;
ret.version = osn.version;
ret.machine = osn.machine;
return ret;
}
//Compile related things
bool IsDebug() {
#ifdef NDEBUG
return false;
#else
return true;
#endif
}
private:
ServerStats() {
m_last_begin = clock::now();
m_last_end = clock::now();
m_network_last_begin = clock::now();
m_network_last_end = clock::now();
}
//Main thread
timestamp m_last_begin;
timestamp m_last_end;
double m_inactive_time;
double m_active_time;
//Network thread
std::mutex m_network_lock;
timestamp m_network_last_begin;
timestamp m_network_last_end;
double m_network_inactive_time;
double m_network_active_time;
};
}

View file

@ -56,6 +56,7 @@
#include "../common/eqemu_logsys.h"
#include "../common/profanity_manager.h"
#include "../common/net/eqstream.h"
#include "../common/server_stats.h"
#include "data_bucket.h"
#include "command.h"
@ -351,7 +352,7 @@ int command_init(void)
command_add("scribespells", "[max level] [min level] - Scribe all spells for you or your player target that are usable by them, up to level specified. (may freeze client for a few seconds)", 150, command_scribespells) ||
command_add("sendzonespawns", "- Refresh spawn list for all clients in zone", 150, command_sendzonespawns) ||
command_add("sensetrap", "Analog for ldon sense trap for the newer clients since we still don't have it working.", 0, command_sensetrap) ||
command_add("serverinfo", "- Get OS info about server host", 200, command_serverinfo) ||
command_add("serverinfo", "- Various info about the current running instance.", 200, command_serverinfo) ||
command_add("serverrules", "- Read this server's rules", 0, command_serverrules) ||
command_add("setaapts", "[value] - Set your or your player target's available AA points", 100, command_setaapts) ||
command_add("setaaxp", "[value] - Set your or your player target's AA experience", 100, command_setaaxp) ||
@ -843,22 +844,6 @@ void command_setanim(Client *c, const Seperator *sep)
}
}
void command_serverinfo(Client *c, const Seperator *sep)
{
#ifdef _WINDOWS
char intbuffer [sizeof(unsigned long)];
c->Message(0, "Operating system information.");
c->Message(0, " %s", Ver_name);
c->Message(0, " Build number: %s", ultoa(Ver_build, intbuffer, 10));
c->Message(0, " Minor version: %s", ultoa(Ver_min, intbuffer, 10));
c->Message(0, " Major version: %s", ultoa(Ver_maj, intbuffer, 10));
c->Message(0, " Platform Id: %s", ultoa(Ver_pid, intbuffer, 10));
#else
char buffer[255];
c->Message(0, "Operating system information: %s", GetOS(buffer));
#endif
}
void command_getvariable(Client *c, const Seperator *sep)
{
std::string tmp;
@ -12371,6 +12356,35 @@ void command_network(Client *c, const Seperator *sep)
}
}
void command_serverinfo(Client *c, const Seperator *sep)
{
auto &stats = EQ::ServerStats::Get();
auto rusage = stats.ResourceUsage();
auto osn = stats.OSInfo();
c->Message(0, "------------------------------------------------");
c->Message(0, "Process");
c->Message(0, "------------------------------------------------");
c->Message(0, "PID: %u", stats.PID());
c->Message(0, "DEBUG: %s", stats.IsDebug() ? "ON" : "OFF");
c->Message(0, "%s (%s %s %s)", osn.version.c_str(), osn.system_name.c_str(), osn.release.c_str(), osn.machine.c_str());
c->Message(0, "------------------------------------------------");
c->Message(0, "CPU");
c->Message(0, "------------------------------------------------");
c->Message(0, "Usage: User %.2f sec, System %.2f sec", rusage.user_cpu_time, rusage.system_cpu_time);
c->Message(0, "Frame Time (Main): %.2f ms (active: %.2f ms) (inactive: %.2f ms) (%.2f fps)",
stats.FrameTime() * 1000.0,
stats.ActiveFrameTime() * 1000.0,
stats.InactiveFrameTime() * 1000.0,
1.0 / stats.FrameTime());
c->Message(0, "Frame Time (Network): %.2f ms (active: %.2f ms) (inactive: %.2f ms) (%.2f fps)",
stats.NetworkFrameTime() * 1000.0,
stats.NetworkActiveFrameTime() * 1000.0,
stats.NetworkInactiveFrameTime() * 1000.0,
1.0 / stats.NetworkFrameTime());
}
// All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block.
#ifdef BOTS
#include "bot_command.h"

View file

@ -7,13 +7,13 @@
#include "../common/eq_packet_structs.h"
#include "../common/misc_functions.h"
#include "../common/data_verification.h"
#include "../common/server_stats.h"
#include <vector>
#include <deque>
#include <map>
#include <stdlib.h>
extern double frame_time;
extern Zone *zone;
class IMovementCommand
@ -69,7 +69,7 @@ public:
}
}
auto td = rotate_to_speed * 19.0 * frame_time;
auto td = rotate_to_speed * 19.0 * EQ::ServerStats::Get().FrameTime();
if (td >= dist) {
m->SetHeading(to);
@ -186,7 +186,7 @@ public:
glm::vec2 dir = tar - pos;
glm::vec2 ndir = glm::normalize(dir);
double distance_moved = frame_time * current_speed * 0.4f * 1.45f;
double distance_moved = EQ::ServerStats::Get().FrameTime() * current_speed * 0.4f * 1.45f;
if (distance_moved > len) {
if (m->IsNPC()) {
@ -313,7 +313,7 @@ public:
glm::vec2 dir = tar - pos;
glm::vec2 ndir = glm::normalize(dir);
double distance_moved = frame_time * current_speed * 0.4f * 1.45f;
double distance_moved = EQ::ServerStats::Get().FrameTime() * current_speed * 0.4f * 1.45f;
if (distance_moved > len) {
if (m->IsNPC()) {

View file

@ -71,6 +71,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../common/event/timer.h"
#include "../common/net/eqstream.h"
#include "../common/net/servertalk_server.h"
#include "../common/server_stats.h"
#include <iostream>
#include <string>
@ -118,7 +119,6 @@ EQEmuLogSys LogSys;
const SPDat_Spell_Struct* spells;
int32 SPDAT_RECORDS = -1;
const ZoneConfig *Config;
double frame_time = 0.0;
void Shutdown();
extern void MapOpcodes();
@ -466,16 +466,24 @@ int main(int argc, char** argv) {
std::chrono::time_point<std::chrono::system_clock> frame_prev = std::chrono::system_clock::now();
std::unique_ptr<EQ::Net::ConsoleServer> console;
auto loop_fn = [&](EQ::Timer* t) {
//Advance the timer to our current point in time
Timer::SetCurrentTime();
int sleep_time = 16;
while (RunLoops) {
auto now = std::chrono::high_resolution_clock::now();
/**
* Calculate frame time
*/
std::chrono::time_point<std::chrono::system_clock> frame_now = std::chrono::system_clock::now();
frame_time = std::chrono::duration_cast<std::chrono::duration<double>>(frame_now - frame_prev).count();
frame_prev = frame_now;
EQ::ServerStats::Get().BeginFrame();
bool previous_loaded = is_zone_loaded && numclients > 0;
Timer::SetCurrentTime();
EQ::EventLoop::GetDefault().Process();
bool current_loaded = is_zone_loaded && numclients > 0;
if (previous_loaded && !current_loaded) {
sleep_time = 100;
eqsm->SetPriority(EQStreamPriority::Low);
}
else if (!previous_loaded && current_loaded) {
sleep_time = 16;
eqsm->SetPriority(EQStreamPriority::High);
}
/**
* Telnet server
@ -512,7 +520,7 @@ int main(int argc, char** argv) {
eqsm->OnNewConnection([&stream_identifier](std::shared_ptr<EQStreamInterface> stream) {
stream_identifier.AddStream(stream);
LogF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->GetRemoteIP(), ntohs(stream->GetRemotePort()));
LogF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->GetRemoteAddr(), ntohs(stream->GetRemotePort()));
});
}
@ -581,33 +589,10 @@ int main(int argc, char** argv) {
database.ping();
entity_list.UpdateWho();
}
};
EQ::Timer process_timer(loop_fn);
process_timer.Start(1000, true);
while (RunLoops) {
bool previous_loaded = is_zone_loaded && numclients > 0;
EQ::EventLoop::GetDefault().Process();
bool current_loaded = is_zone_loaded && numclients > 0;
if (previous_loaded && !current_loaded) {
process_timer.Stop();
process_timer.Start(1000, true);
eqsm->SetPriority(EQStreamPriority::Low);
}
else if (!previous_loaded && current_loaded) {
process_timer.Stop();
process_timer.Start(32, true);
eqsm->SetPriority(EQStreamPriority::High);
}
if (current_loaded) {
Sleep(1);
}
else {
Sleep(10);
}
EQ::ServerStats::Get().EndFrame();
auto end = now + std::chrono::milliseconds(sleep_time);
std::this_thread::sleep_until(end);
}
entity_list.Clear();

View file

@ -18,6 +18,7 @@
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "../common/server_stats.h"
#include "client.h"
#include "entity.h"
@ -27,8 +28,6 @@
#include <string.h>
extern double frame_time;
int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target)
{
int base = EQEmu::skills::GetBaseDamage(skill);
@ -1033,7 +1032,7 @@ void Mob::ProjectileAttack()
ProjectileAtk[i].skill = 0;
ProjectileAtk[i].speed_mod = 0.0f;
} else {
ProjectileAtk[i].increment += 1000 * frame_time;
ProjectileAtk[i].increment += 1000 * EQ::ServerStats::Get().FrameTime();
}
}