Improve debug profiler usage for investigating CPU usage of server

This commit is contained in:
Perttu Ahola 2011-10-16 21:16:44 +03:00
parent 07d000cc54
commit b8f2dcea4d
4 changed files with 98 additions and 73 deletions

@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapgen.h" #include "mapgen.h"
#include "settings.h" #include "settings.h"
#include "log.h" #include "log.h"
#include "profiler.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@ -682,37 +683,40 @@ void ServerEnvironment::step(float dtime)
/* /*
Handle players Handle players
*/ */
for(core::list<Player*>::Iterator i = m_players.begin();
i != m_players.end(); i++)
{ {
Player *player = *i; ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_LOWPASS);
for(core::list<Player*>::Iterator i = m_players.begin();
// Ignore disconnected players i != m_players.end(); i++)
if(player->peer_id == 0)
continue;
v3f playerpos = player->getPosition();
// Move
player->move(dtime, *m_map, 100*BS);
/*
Add footsteps to grass
*/
if(footprints)
{ {
// Get node that is at BS/4 under player Player *player = *i;
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
try{ // Ignore disconnected players
MapNode n = m_map->getNode(bottompos); if(player->peer_id == 0)
if(n.getContent() == CONTENT_GRASS) continue;
{
n.setContent(CONTENT_GRASS_FOOTSTEPS); v3f playerpos = player->getPosition();
m_map->setNode(bottompos, n);
} // Move
} player->move(dtime, *m_map, 100*BS);
catch(InvalidPositionException &e)
/*
Add footsteps to grass
*/
if(footprints)
{ {
// Get node that is at BS/4 under player
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
try{
MapNode n = m_map->getNode(bottompos);
if(n.getContent() == CONTENT_GRASS)
{
n.setContent(CONTENT_GRASS_FOOTSTEPS);
m_map->setNode(bottompos, n);
}
}
catch(InvalidPositionException &e)
{
}
} }
} }
} }
@ -722,6 +726,7 @@ void ServerEnvironment::step(float dtime)
*/ */
if(m_active_blocks_management_interval.step(dtime, 2.0)) if(m_active_blocks_management_interval.step(dtime, 2.0))
{ {
ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg", SPT_LOWPASS);
/* /*
Get player block positions Get player block positions
*/ */
@ -798,6 +803,8 @@ void ServerEnvironment::step(float dtime)
*/ */
if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0)) if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0))
{ {
ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg", SPT_LOWPASS);
float dtime = 1.0; float dtime = 1.0;
for(core::map<v3s16, bool>::Iterator for(core::map<v3s16, bool>::Iterator
@ -832,8 +839,10 @@ void ServerEnvironment::step(float dtime)
} }
} }
} }
if(m_active_blocks_test_interval.step(dtime, 10.0)) if(m_active_blocks_test_interval.step(dtime, 10.0))
{ {
ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg", SPT_LOWPASS);
//float dtime = 10.0; //float dtime = 10.0;
for(core::map<v3s16, bool>::Iterator for(core::map<v3s16, bool>::Iterator
@ -1036,6 +1045,7 @@ void ServerEnvironment::step(float dtime)
Step active objects Step active objects
*/ */
{ {
ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_LOWPASS);
//TimeTaker timer("Step active objects"); //TimeTaker timer("Step active objects");
// This helps the objects to send data at the same time // This helps the objects to send data at the same time
@ -1076,6 +1086,7 @@ void ServerEnvironment::step(float dtime)
*/ */
if(m_object_management_interval.step(dtime, 0.5)) if(m_object_management_interval.step(dtime, 0.5))
{ {
ScopeProfiler sp(g_profiler, "SEnv: remove removed objs avg", SPT_LOWPASS);
/* /*
Remove objects that satisfy (m_removed && m_known_by_count==0) Remove objects that satisfy (m_removed && m_known_by_count==0)
*/ */

@ -1070,6 +1070,8 @@ void the_game(
object_hit_delay_timer -= dtime; object_hit_delay_timer -= dtime;
g_profiler->add("Elapsed time", dtime * 1000);
/* /*
Log frametime for visualization Log frametime for visualization
*/ */

@ -38,24 +38,38 @@ public:
m_mutex.Init(); m_mutex.Init();
} }
void add(const std::string &name, u32 duration) void add(const std::string &name, float value)
{ {
JMutexAutoLock lock(m_mutex); JMutexAutoLock lock(m_mutex);
core::map<std::string, u32>::Node *n = m_data.find(name); core::map<std::string, float>::Node *n = m_data.find(name);
if(n == NULL) if(n == NULL)
{ {
m_data[name] = duration; m_data[name] = value;
} }
else else
{ {
n->setValue(n->getValue()+duration); n->setValue(n->getValue() + value);
}
}
void lowpass(const std::string &name, float value, float factor)
{
JMutexAutoLock lock(m_mutex);
core::map<std::string, float>::Node *n = m_data.find(name);
if(n == NULL)
{
m_data[name] = value;
}
else
{
n->setValue(n->getValue() * (1.0 - 1.0/factor) + value / factor);
} }
} }
void clear() void clear()
{ {
JMutexAutoLock lock(m_mutex); JMutexAutoLock lock(m_mutex);
for(core::map<std::string, u32>::Iterator for(core::map<std::string, float>::Iterator
i = m_data.getIterator(); i = m_data.getIterator();
i.atEnd() == false; i++) i.atEnd() == false; i++)
{ {
@ -66,14 +80,14 @@ public:
void print(std::ostream &o) void print(std::ostream &o)
{ {
JMutexAutoLock lock(m_mutex); JMutexAutoLock lock(m_mutex);
for(core::map<std::string, u32>::Iterator for(core::map<std::string, float>::Iterator
i = m_data.getIterator(); i = m_data.getIterator();
i.atEnd() == false; i++) i.atEnd() == false; i++)
{ {
std::string name = i.getNode()->getKey(); std::string name = i.getNode()->getKey();
o<<name<<": "; o<<" "<<name<<": ";
s32 clampsize = 40; s32 clampsize = 40;
s32 space = clampsize-name.size(); s32 space = clampsize - name.size();
for(s32 j=0; j<space; j++) for(s32 j=0; j<space; j++)
{ {
if(j%2 == 0 && j < space - 1) if(j%2 == 0 && j < space - 1)
@ -88,25 +102,34 @@ public:
private: private:
JMutex m_mutex; JMutex m_mutex;
core::map<std::string, u32> m_data; core::map<std::string, float> m_data;
};
enum ScopeProfilerType{
SPT_ADD,
SPT_LOWPASS
}; };
class ScopeProfiler class ScopeProfiler
{ {
public: public:
ScopeProfiler(Profiler *profiler, const std::string &name): ScopeProfiler(Profiler *profiler, const std::string &name,
enum ScopeProfilerType type = SPT_ADD):
m_profiler(profiler), m_profiler(profiler),
m_name(name), m_name(name),
m_timer(NULL) m_timer(NULL),
m_type(type)
{ {
if(m_profiler) if(m_profiler)
m_timer = new TimeTaker(m_name.c_str()); m_timer = new TimeTaker(m_name.c_str());
} }
// name is copied // name is copied
ScopeProfiler(Profiler *profiler, const char *name): ScopeProfiler(Profiler *profiler, const char *name,
enum ScopeProfilerType type = SPT_ADD):
m_profiler(profiler), m_profiler(profiler),
m_name(name), m_name(name),
m_timer(NULL) m_timer(NULL),
m_type(type)
{ {
if(m_profiler) if(m_profiler)
m_timer = new TimeTaker(m_name.c_str()); m_timer = new TimeTaker(m_name.c_str());
@ -116,8 +139,16 @@ public:
if(m_timer) if(m_timer)
{ {
u32 duration = m_timer->stop(true); u32 duration = m_timer->stop(true);
if(m_profiler) if(m_profiler){
m_profiler->add(m_name, duration); switch(m_type){
case SPT_ADD:
m_profiler->add(m_name, duration);
break;
case SPT_LOWPASS:
m_profiler->lowpass(m_name, duration, 20.0);
break;
}
}
delete m_timer; delete m_timer;
} }
} }
@ -125,6 +156,7 @@ private:
Profiler *m_profiler; Profiler *m_profiler;
std::string m_name; std::string m_name;
TimeTaker *m_timer; TimeTaker *m_timer;
enum ScopeProfilerType m_type;
}; };
#endif #endif

@ -842,31 +842,9 @@ void RemoteClient::SendObjectData(
} }
/* /*
Get and write object data Get and write object data (dummy, for compatibility)
*/ */
/*
Get nearby blocks.
For making players to be able to build to their nearby
environment (building is not possible on blocks that are not
in memory):
- Set blocks changed
- Add blocks to emerge queue if they are not found
SUGGESTION: These could be ignored from the backside of the player
*/
Player *player = server->m_env.getPlayer(peer_id);
assert(player);
v3f playerpos = player->getPosition();
v3f playerspeed = player->getSpeed();
v3s16 center_nodepos = floatToInt(playerpos, BS);
v3s16 center = getNodeBlockPos(center_nodepos);
// Write block count // Write block count
writeU16(buf, 0); writeU16(buf, 0);
os.write((char*)buf, 2); os.write((char*)buf, 2);
@ -1143,6 +1121,8 @@ void Server::AsyncRunStep()
{ {
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
g_profiler->add("Server::AsyncRunStep (num)", 1);
float dtime; float dtime;
{ {
JMutexAutoLock lock1(m_step_dtime_mutex); JMutexAutoLock lock1(m_step_dtime_mutex);
@ -1150,14 +1130,15 @@ void Server::AsyncRunStep()
} }
{ {
ScopeProfiler sp(g_profiler, "Server: selecting and sending " ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
"blocks to clients");
// Send blocks to clients // Send blocks to clients
SendBlocks(dtime); SendBlocks(dtime);
} }
if(dtime < 0.001) if(dtime < 0.001)
return; return;
g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
//infostream<<"Server steps "<<dtime<<std::endl; //infostream<<"Server steps "<<dtime<<std::endl;
//infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl; //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
@ -1184,7 +1165,6 @@ void Server::AsyncRunStep()
{ {
// This has to be called so that the client list gets synced // This has to be called so that the client list gets synced
// with the peer list of the connection // with the peer list of the connection
ScopeProfiler sp(g_profiler, "Server: peer change handling");
handlePeerChanges(); handlePeerChanges();
} }
@ -1233,7 +1213,8 @@ void Server::AsyncRunStep()
{ {
JMutexAutoLock lock(m_env_mutex); JMutexAutoLock lock(m_env_mutex);
// Step environment // Step environment
ScopeProfiler sp(g_profiler, "Server: environment step"); ScopeProfiler sp(g_profiler, "SEnv step");
ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_LOWPASS);
m_env.step(dtime); m_env.step(dtime);
} }
@ -1340,7 +1321,7 @@ void Server::AsyncRunStep()
JMutexAutoLock envlock(m_env_mutex); JMutexAutoLock envlock(m_env_mutex);
JMutexAutoLock conlock(m_con_mutex); JMutexAutoLock conlock(m_con_mutex);
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objects"); ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
// Radius inside which objects are active // Radius inside which objects are active
s16 radius = g_settings->getS16("active_object_send_range_blocks"); s16 radius = g_settings->getS16("active_object_send_range_blocks");
@ -1720,7 +1701,6 @@ void Server::AsyncRunStep()
/* /*
Send object positions Send object positions
TODO: Get rid of MapBlockObjects
*/ */
{ {
float &counter = m_objectdata_timer; float &counter = m_objectdata_timer;
@ -1730,7 +1710,7 @@ void Server::AsyncRunStep()
JMutexAutoLock lock1(m_env_mutex); JMutexAutoLock lock1(m_env_mutex);
JMutexAutoLock lock2(m_con_mutex); JMutexAutoLock lock2(m_con_mutex);
ScopeProfiler sp(g_profiler, "Server: sending mbo positions"); ScopeProfiler sp(g_profiler, "Server: sending player positions");
SendObjectData(counter); SendObjectData(counter);