This commit is contained in:
sfan5 2024-04-19 11:39:01 +00:00 committed by GitHub
commit a137dc601f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 234 additions and 230 deletions

View File

@ -47,11 +47,6 @@ gui::IGUIEnvironment *guienv = nullptr;
gui::IGUIStaticText *guiroot = nullptr; gui::IGUIStaticText *guiroot = nullptr;
MainMenuManager g_menumgr; MainMenuManager g_menumgr;
bool isMenuActive()
{
return g_menumgr.menuCount() != 0;
}
// Passed to menus to allow disconnecting and exiting // Passed to menus to allow disconnecting and exiting
MainGameCallback *g_gamecallback = nullptr; MainGameCallback *g_gamecallback = nullptr;
@ -74,13 +69,20 @@ ClientLauncher::~ClientLauncher()
{ {
delete input; delete input;
delete receiver;
delete g_fontengine; delete g_fontengine;
g_fontengine = nullptr;
delete g_gamecallback; delete g_gamecallback;
g_gamecallback = nullptr;
guiroot = nullptr;
guienv = nullptr;
assert(g_menumgr.menuCount() == 0);
delete m_rendering_engine; delete m_rendering_engine;
// delete event receiver only after all Irrlicht stuff is gone
delete receiver;
#if USE_SOUND #if USE_SOUND
g_sound_manager_singleton.reset(); g_sound_manager_singleton.reset();
#endif #endif
@ -103,10 +105,8 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
g_sound_manager_singleton = createSoundManagerSingleton(); g_sound_manager_singleton = createSoundManagerSingleton();
#endif #endif
if (!init_engine()) { if (!init_engine())
errorstream << "Could not initialize game engine." << std::endl;
return false; return false;
}
if (!m_rendering_engine->get_video_driver()) { if (!m_rendering_engine->get_video_driver()) {
errorstream << "Could not initialize video driver." << std::endl; errorstream << "Could not initialize video driver." << std::endl;
@ -129,7 +129,6 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
init_guienv(guienv); init_guienv(guienv);
g_fontengine = new FontEngine(guienv); g_fontengine = new FontEngine(guienv);
FATAL_ERROR_IF(!g_fontengine, "Font engine creation failed.");
// Create the menu clouds // Create the menu clouds
// This is only global so it can be used by RenderingEngine::draw_load_screen(). // This is only global so it can be used by RenderingEngine::draw_load_screen().
@ -258,6 +257,13 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
} }
} // Menu-game loop } // Menu-game loop
// If profiler was enabled print it one last time
if (g_settings->getFloat("profiler_print_interval") > 0) {
infostream << "Profiler:" << std::endl;
g_profiler->print(infostream);
g_profiler->clear();
}
assert(g_menucloudsmgr->getReferenceCount() == 1); assert(g_menucloudsmgr->getReferenceCount() == 1);
g_menucloudsmgr->drop(); g_menucloudsmgr->drop();
g_menucloudsmgr = nullptr; g_menucloudsmgr = nullptr;
@ -294,8 +300,12 @@ void ClientLauncher::init_args(GameStartData &start_data, const Settings &cmd_ar
bool ClientLauncher::init_engine() bool ClientLauncher::init_engine()
{ {
receiver = new MyEventReceiver(); receiver = new MyEventReceiver();
m_rendering_engine = new RenderingEngine(receiver); try {
return m_rendering_engine->get_raw_device() != nullptr; m_rendering_engine = new RenderingEngine(receiver);
} catch (std::exception &e) {
errorstream << e.what() << std::endl;
}
return !!m_rendering_engine;
} }
void ClientLauncher::init_input() void ClientLauncher::init_input()

View File

@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "camera.h" // CameraModes #include "camera.h" // CameraModes
#include "collision.h" #include "collision.h"
#include "content_cso.h" #include "content_cso.h"
#include "clientobject.h"
#include "environment.h" #include "environment.h"
#include "itemdef.h" #include "itemdef.h"
#include "localplayer.h" #include "localplayer.h"
@ -218,14 +219,15 @@ private:
}; };
// Prototype // Prototype
TestCAO proto_TestCAO(NULL, NULL); static TestCAO proto_TestCAO(nullptr, nullptr);
TestCAO::TestCAO(Client *client, ClientEnvironment *env): TestCAO::TestCAO(Client *client, ClientEnvironment *env):
ClientActiveObject(0, client, env), ClientActiveObject(0, client, env),
m_node(NULL), m_node(NULL),
m_position(v3f(0,10*BS,0)) m_position(v3f(0,10*BS,0))
{ {
ClientActiveObject::registerType(getType(), create); if (!client)
ClientActiveObject::registerType(getType(), create);
} }
std::unique_ptr<ClientActiveObject> TestCAO::create(Client *client, ClientEnvironment *env) std::unique_ptr<ClientActiveObject> TestCAO::create(Client *client, ClientEnvironment *env)
@ -322,8 +324,6 @@ void TestCAO::processMessage(const std::string &data)
GenericCAO GenericCAO
*/ */
#include "clientobject.h"
GenericCAO::GenericCAO(Client *client, ClientEnvironment *env): GenericCAO::GenericCAO(Client *client, ClientEnvironment *env):
ClientActiveObject(0, client, env) ClientActiveObject(0, client, env)
{ {
@ -2082,4 +2082,4 @@ void GenericCAO::updateMeshCulling()
} }
// Prototype // Prototype
GenericCAO proto_GenericCAO(NULL, NULL); static GenericCAO proto_GenericCAO(nullptr, nullptr);

View File

@ -27,16 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlicht_changes/CGUITTFont.h" #include "irrlicht_changes/CGUITTFont.h"
#include "util/numeric.h" // rangelim #include "util/numeric.h" // rangelim
/** maximum size distance for getting a "similar" font size */
#define MAX_FONT_SIZE_OFFSET 10
/** reference to access font engine, has to be initialized by main */ /** reference to access font engine, has to be initialized by main */
FontEngine* g_fontengine = NULL; FontEngine *g_fontengine = nullptr;
/** callback to be used on change of font size setting */ /** callback to be used on change of font size setting */
static void font_setting_changed(const std::string &name, void *userdata) static void font_setting_changed(const std::string &name, void *userdata)
{ {
g_fontengine->readSettings(); if (g_fontengine)
g_fontengine->readSettings();
} }
/******************************************************************************/ /******************************************************************************/
@ -226,7 +224,7 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec)
u16 divisible_by = g_settings->getU16(setting_prefix + "font_size_divisible_by"); u16 divisible_by = g_settings->getU16(setting_prefix + "font_size_divisible_by");
if (divisible_by > 1) { if (divisible_by > 1) {
size = std::max<u32>( size = std::max<u32>(
std::round((double)size / divisible_by) * divisible_by, divisible_by); std::round((float)size / divisible_by) * divisible_by, divisible_by);
} }
sanity_check(size != 0); sanity_check(size != 0);

View File

@ -1132,9 +1132,11 @@ void Game::run()
FpsControl draw_times; FpsControl draw_times;
f32 dtime; // in seconds f32 dtime; // in seconds
/* Clear the profiler */ // Clear the profiler
Profiler::GraphValues dummyvalues; {
g_profiler->graphGet(dummyvalues); Profiler::GraphValues dummyvalues;
g_profiler->graphPop(dummyvalues);
}
draw_times.reset(); draw_times.reset();
@ -1902,7 +1904,8 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
g_settings->getFloat("profiler_print_interval"); g_settings->getFloat("profiler_print_interval");
bool print_to_log = true; bool print_to_log = true;
if (profiler_print_interval == 0) { // Update game UI anyway but don't log
if (profiler_print_interval <= 0) {
print_to_log = false; print_to_log = false;
profiler_print_interval = 3; profiler_print_interval = 3;
} }
@ -1917,12 +1920,12 @@ void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
g_profiler->clear(); g_profiler->clear();
} }
// Update update graphs // Update graphs
g_profiler->graphAdd("Time non-rendering [us]", g_profiler->graphAdd("Time non-rendering [us]",
draw_times.busy_time - stats.drawtime); draw_times.busy_time - stats.drawtime);
g_profiler->graphAdd("Sleep [us]", draw_times.sleep_time); g_profiler->graphAdd("Sleep [us]", draw_times.sleep_time);
g_profiler->graphAdd("FPS", 1.0f / dtime);
g_profiler->graphSet("FPS", 1.0f / dtime);
} }
void Game::updateStats(RunStats *stats, const FpsControl &draw_times, void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
@ -4229,7 +4232,7 @@ void Game::updateClouds(float dtime)
inline void Game::updateProfilerGraphs(ProfilerGraph *graph) inline void Game::updateProfilerGraphs(ProfilerGraph *graph)
{ {
Profiler::GraphValues values; Profiler::GraphValues values;
g_profiler->graphGet(values); g_profiler->graphPop(values);
graph->put(values); graph->put(values);
} }

View File

@ -29,12 +29,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
* converting textures back into images repeatedly, and some don't even * converting textures back into images repeatedly, and some don't even
* allow it at all. * allow it at all.
*/ */
std::map<io::path, video::IImage *> g_imgCache; static std::map<io::path, video::IImage *> g_imgCache;
/* Maintain a static cache of all pre-scaled textures. These need to be /* Maintain a static cache of all pre-scaled textures. These need to be
* cleared as well when the cached images. * cleared as well when the cached images.
*/ */
std::map<io::path, video::ITexture *> g_txrCache; static std::map<io::path, video::ITexture *> g_txrCache;
/* Manually insert an image into the cache, useful to avoid texture-to-image /* Manually insert an image into the cache, useful to avoid texture-to-image
* conversion whenever we can intercept it. * conversion whenever we can intercept it.

View File

@ -355,12 +355,11 @@ const KeyPress CancelKey("KEY_CANCEL");
*/ */
// A simple cache for quicker lookup // A simple cache for quicker lookup
std::unordered_map<std::string, KeyPress> g_key_setting_cache; static std::unordered_map<std::string, KeyPress> g_key_setting_cache;
KeyPress getKeySetting(const char *settingname) KeyPress getKeySetting(const char *settingname)
{ {
std::unordered_map<std::string, KeyPress>::iterator n; auto n = g_key_setting_cache.find(settingname);
n = g_key_setting_cache.find(settingname);
if (n != g_key_setting_cache.end()) if (n != g_key_setting_cache.end())
return n->second; return n->second;

View File

@ -253,8 +253,11 @@ RenderingEngine::RenderingEngine(IEventReceiver *receiver)
RenderingEngine::~RenderingEngine() RenderingEngine::~RenderingEngine()
{ {
sanity_check(s_singleton == this);
core.reset(); core.reset();
m_device->closeDevice(); m_device->closeDevice();
m_device->drop();
s_singleton = nullptr; s_singleton = nullptr;
} }
@ -278,10 +281,7 @@ void RenderingEngine::removeMesh(const scene::IMesh* mesh)
void RenderingEngine::cleanupMeshCache() void RenderingEngine::cleanupMeshCache()
{ {
auto mesh_cache = m_device->getSceneManager()->getMeshCache(); auto mesh_cache = m_device->getSceneManager()->getMeshCache();
while (mesh_cache->getMeshCount() != 0) { mesh_cache->clear();
if (scene::IAnimatedMesh *mesh = mesh_cache->getMeshByIndex(0))
mesh_cache->removeMesh(mesh);
}
} }
bool RenderingEngine::setupTopLevelWindow() bool RenderingEngine::setupTopLevelWindow()

View File

@ -46,7 +46,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
/* /*
A cache from shader name to shader path A cache from shader name to shader path
*/ */
MutexedMap<std::string, std::string> g_shadername_to_path_cache; static MutexedMap<std::string, std::string> g_shadername_to_path_cache;
/* /*
Gets the path to a shader by first checking if the file Gets the path to a shader by first checking if the file

View File

@ -191,7 +191,7 @@ private:
scene::IMesh *m_cube; scene::IMesh *m_cube;
}; };
ExtrusionMeshCache *g_extrusion_mesh_cache = NULL; static ExtrusionMeshCache *g_extrusion_mesh_cache = nullptr;
WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting): WieldMeshSceneNode::WieldMeshSceneNode(scene::ISceneManager *mgr, s32 id, bool lighting):

View File

@ -70,7 +70,7 @@ enum EmergeAction {
EMERGE_GENERATED, EMERGE_GENERATED,
}; };
const static std::string emergeActionStrs[] = { constexpr const char *emergeActionStrs[] = {
"cancelled", "cancelled",
"errored", "errored",
"from_memory", "from_memory",

View File

@ -26,10 +26,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class BaseException : public std::exception class BaseException : public std::exception
{ {
public: public:
BaseException(const std::string &s) throw(): m_s(s) {} BaseException(const std::string &s) noexcept: m_s(s) {}
~BaseException() throw() = default; ~BaseException() throw() = default;
virtual const char * what() const throw() virtual const char * what() const noexcept
{ {
return m_s.c_str(); return m_s.c_str();
} }

View File

@ -23,14 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string> #include <string>
#include <mutex> #include <mutex>
enum TimePrecision
{
PRECISION_SECONDS,
PRECISION_MILLI,
PRECISION_MICRO,
PRECISION_NANO
};
inline struct tm mt_localtime() inline struct tm mt_localtime()
{ {
// initialize the time zone on first invocation // initialize the time zone on first invocation

View File

@ -80,7 +80,7 @@ public:
return mm && mm->preprocessEvent(event); return mm && mm->preprocessEvent(event);
} }
u32 menuCount() size_t menuCount() const
{ {
return m_stack.size(); return m_stack.size();
} }
@ -95,12 +95,16 @@ public:
return false; return false;
} }
// FIXME: why isn't this private?
std::list<gui::IGUIElement*> m_stack; std::list<gui::IGUIElement*> m_stack;
}; };
extern MainMenuManager g_menumgr; extern MainMenuManager g_menumgr;
extern bool isMenuActive(); static inline bool isMenuActive()
{
return g_menumgr.menuCount() != 0;
}
class MainGameCallback : public IGameCallback class MainGameCallback : public IGameCallback
{ {
@ -138,7 +142,8 @@ public:
keyconfig_changed = true; keyconfig_changed = true;
} }
void showOpenURLDialog(const std::string &url) override { void showOpenURLDialog(const std::string &url) override
{
show_open_url_dialog = url; show_open_url_dialog = url;
} }

View File

@ -215,21 +215,22 @@ void MapBlock::expireIsAirCache()
// List relevant id-name pairs for ids in the block using nodedef // List relevant id-name pairs for ids in the block using nodedef
// Renumbers the content IDs (starting at 0 and incrementing) // Renumbers the content IDs (starting at 0 and incrementing)
// Note that there's no technical reason why we *have to* renumber the IDs,
// but we do it anyway as it also helps compressability.
static void getBlockNodeIdMapping(NameIdMapping *nimap, MapNode *nodes, static void getBlockNodeIdMapping(NameIdMapping *nimap, MapNode *nodes,
const NodeDefManager *nodedef) const NodeDefManager *nodedef)
{ {
// The static memory requires about 65535 * sizeof(int) RAM in order to be // The static memory requires about 65535 * 2 bytes RAM in order to be
// sure we can handle all content ids. But it's absolutely worth it as it's // sure we can handle all content ids. But it's absolutely worth it as it's
// a speedup of 4 for one of the major time consuming functions on storing // a speedup of 4 for one of the major time consuming functions on storing
// mapblocks. // mapblocks.
thread_local std::unique_ptr<content_t[]> mapping; thread_local std::unique_ptr<content_t[]> mapping;
static_assert(sizeof(content_t) == 2, "content_t must be 16-bit"); static_assert(sizeof(content_t) == 2, "content_t must be 16-bit");
if (!mapping) if (!mapping)
mapping = std::make_unique<content_t[]>(USHRT_MAX + 1); mapping = std::make_unique<content_t[]>(CONTENT_MAX + 1);
memset(mapping.get(), 0xFF, (USHRT_MAX + 1) * sizeof(content_t)); memset(mapping.get(), 0xFF, (CONTENT_MAX + 1) * sizeof(content_t));
std::unordered_set<content_t> unknown_contents;
content_t id_counter = 0; content_t id_counter = 0;
for (u32 i = 0; i < MapBlock::nodecount; i++) { for (u32 i = 0; i < MapBlock::nodecount; i++) {
content_t global_id = nodes[i].getContent(); content_t global_id = nodes[i].getContent();
@ -243,21 +244,13 @@ static void getBlockNodeIdMapping(NameIdMapping *nimap, MapNode *nodes,
id = id_counter++; id = id_counter++;
mapping[global_id] = id; mapping[global_id] = id;
const ContentFeatures &f = nodedef->get(global_id); const auto &name = nodedef->get(global_id).name;
const std::string &name = f.name; nimap->set(id, name);
if (name.empty())
unknown_contents.insert(global_id);
else
nimap->set(id, name);
} }
// Update the MapNode // Update the MapNode
nodes[i].setContent(id); nodes[i].setContent(id);
} }
for (u16 unknown_content : unknown_contents) {
errorstream << "getBlockNodeIdMapping(): IGNORING ERROR: "
<< "Name for node id " << unknown_content << " not known" << std::endl;
}
} }
// Correct ids in the block to match nodedef based on names. // Correct ids in the block to match nodedef based on names.

View File

@ -708,15 +708,17 @@ Buffer<u8> MapNode::serializeBulk(int version,
Buffer<u8> databuf(nodecount * (content_width + params_width)); Buffer<u8> databuf(nodecount * (content_width + params_width));
u32 start1 = content_width * nodecount; // Writing to the buffer linearly is faster
u32 start2 = (content_width + 1) * nodecount; u8 *p = &databuf[0];
for (u32 i = 0; i < nodecount; i++, p += 2)
writeU16(p, nodes[i].param0);
for (u32 i = 0; i < nodecount; i++, p++)
writeU8(p, nodes[i].param1);
for (u32 i = 0; i < nodecount; i++, p++)
writeU8(p, nodes[i].param2);
// Serialize content
for (u32 i = 0; i < nodecount; i++) {
writeU16(&databuf[i * 2], nodes[i].param0);
writeU8(&databuf[start1 + i], nodes[i].param1);
writeU8(&databuf[start2 + i], nodes[i].param2);
}
return databuf; return databuf;
} }

View File

@ -21,8 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <set>
#include <unordered_map> #include <unordered_map>
#include <cassert>
#include "irrlichttypes_bloated.h" #include "irrlichttypes_bloated.h"
typedef std::unordered_map<u16, std::string> IdToNameMap; typedef std::unordered_map<u16, std::string> IdToNameMap;
@ -42,6 +42,7 @@ public:
void set(u16 id, const std::string &name) void set(u16 id, const std::string &name)
{ {
assert(!name.empty());
m_id_to_name[id] = name; m_id_to_name[id] = name;
m_name_to_id[name] = id; m_name_to_id[name] = id;
} }
@ -67,8 +68,7 @@ public:
} }
bool getName(u16 id, std::string &result) const bool getName(u16 id, std::string &result) const
{ {
IdToNameMap::const_iterator i; auto i = m_id_to_name.find(id);
i = m_id_to_name.find(id);
if (i == m_id_to_name.end()) if (i == m_id_to_name.end())
return false; return false;
result = i->second; result = i->second;
@ -76,8 +76,7 @@ public:
} }
bool getId(const std::string &name, u16 &result) const bool getId(const std::string &name, u16 &result) const
{ {
NameToIdMap::const_iterator i; auto i = m_name_to_id.find(name);
i = m_name_to_id.find(name);
if (i == m_name_to_id.end()) if (i == m_name_to_id.end())
return false; return false;
result = i->second; result = i->second;

View File

@ -1098,7 +1098,7 @@ enum NetProtoCompressionMode {
NETPROTO_COMPRESSION_NONE = 0, NETPROTO_COMPRESSION_NONE = 0,
}; };
const static std::string accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = { constexpr const char *accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
"Invalid password", "Invalid password",
"Your client sent something the server didn't expect. Try reconnecting or updating your client.", "Your client sent something the server didn't expect. Try reconnecting or updating your client.",
"The server is running in simple singleplayer mode. You cannot connect.", "The server is running in simple singleplayer mode. You cannot connect.",

View File

@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h" // u64 #include "irrlichttypes.h" // u64
#include "debug.h" #include "debug.h"
#include "constants.h" #include "constants.h"
#include "gettime.h" #include "util/timetaker.h" // TimePrecision
#ifdef _MSC_VER #ifdef _MSC_VER
#define SWPRINTF_CHARSTRING L"%S" #define SWPRINTF_CHARSTRING L"%S"

View File

@ -22,40 +22,37 @@ with this program; if not, write to the Free Software Foundation, Inc.,
static Profiler main_profiler; static Profiler main_profiler;
Profiler *g_profiler = &main_profiler; Profiler *g_profiler = &main_profiler;
ScopeProfiler::ScopeProfiler(
Profiler *profiler, const std::string &name, ScopeProfilerType type) : ScopeProfiler::ScopeProfiler(Profiler *profiler, const std::string &name,
m_profiler(profiler), ScopeProfilerType type, TimePrecision prec) :
m_name(name), m_type(type) m_profiler(profiler),
m_name(name), m_type(type), m_precision(prec)
{ {
m_name.append(" [ms]"); m_name.append(" [").append(TimePrecision_units[prec]).append("]");
if (m_profiler) m_time1 = porting::getTime(prec);
m_timer = new TimeTaker(m_name, nullptr, PRECISION_MILLI);
} }
ScopeProfiler::~ScopeProfiler() ScopeProfiler::~ScopeProfiler()
{ {
if (!m_timer) if (!m_profiler)
return; return;
float duration_ms = m_timer->stop(true); float duration = porting::getTime(m_precision) - m_time1;
float duration = duration_ms;
if (m_profiler) { switch (m_type) {
switch (m_type) { case SPT_ADD:
case SPT_ADD: m_profiler->add(m_name, duration);
m_profiler->add(m_name, duration); break;
break; case SPT_AVG:
case SPT_AVG: m_profiler->avg(m_name, duration);
m_profiler->avg(m_name, duration); break;
break; case SPT_GRAPH_ADD:
case SPT_GRAPH_ADD: m_profiler->graphAdd(m_name, duration);
m_profiler->graphAdd(m_name, duration); break;
break; case SPT_MAX:
case SPT_MAX: m_profiler->max(m_name, duration);
m_profiler->max(m_name, duration); break;
break;
}
} }
delete m_timer;
} }
Profiler::Profiler() Profiler::Profiler()
@ -66,92 +63,68 @@ Profiler::Profiler()
void Profiler::add(const std::string &name, float value) void Profiler::add(const std::string &name, float value)
{ {
MutexAutoLock lock(m_mutex); MutexAutoLock lock(m_mutex);
{
/* No average shall have been used; mark add/max used as -2 */ auto it = m_data.find(name);
std::map<std::string, int>::iterator n = m_avgcounts.find(name); if (it == m_data.end()) {
if (n == m_avgcounts.end()) { // mark with special value for checking
m_avgcounts[name] = -2; m_data.emplace(name, DataPair{value, -SPT_ADD});
} else { } else {
if (n->second == -1) assert(it->second.avgcount == -SPT_ADD);
n->second = -2; it->second.value += value;
assert(n->second == -2);
}
}
{
std::map<std::string, float>::iterator n = m_data.find(name);
if (n == m_data.end())
m_data[name] = value;
else
n->second += value;
} }
} }
void Profiler::max(const std::string &name, float value) void Profiler::max(const std::string &name, float value)
{ {
MutexAutoLock lock(m_mutex); MutexAutoLock lock(m_mutex);
{
/* No average shall have been used; mark add/max used as -2 */ auto it = m_data.find(name);
auto n = m_avgcounts.find(name); if (it == m_data.end()) {
if (n == m_avgcounts.end()) { // mark with special value for checking
m_avgcounts[name] = -2; m_data.emplace(name, DataPair{value, -SPT_MAX});
} else { } else {
if (n->second == -1) assert(it->second.avgcount == -SPT_MAX);
n->second = -2; it->second.value = std::max(value, it->second.value);
assert(n->second == -2);
}
}
{
auto n = m_data.find(name);
if (n == m_data.end())
m_data[name] = value;
else if (value > n->second)
n->second = value;
} }
} }
void Profiler::avg(const std::string &name, float value) void Profiler::avg(const std::string &name, float value)
{ {
MutexAutoLock lock(m_mutex); MutexAutoLock lock(m_mutex);
int &count = m_avgcounts[name];
assert(count != -2); auto it = m_data.find(name);
count = MYMAX(count, 0) + 1; if (it == m_data.end()) {
m_data[name] += value; m_data.emplace(name, DataPair{value, 1});
} else {
assert(it->second.avgcount >= 1);
it->second.value += value;
it->second.avgcount++;
}
} }
void Profiler::clear() void Profiler::clear()
{ {
MutexAutoLock lock(m_mutex); MutexAutoLock lock(m_mutex);
for (auto &it : m_data) { for (auto &it : m_data)
it.second = 0; it.second = DataPair();
}
m_avgcounts.clear();
m_start_time = porting::getTimeMs(); m_start_time = porting::getTimeMs();
} }
float Profiler::getValue(const std::string &name) const float Profiler::getValue(const std::string &name) const
{ {
auto numerator = m_data.find(name); auto it = m_data.find(name);
if (numerator == m_data.end()) if (it == m_data.end())
return 0.f; return 0;
return it->second.getValue();
auto denominator = m_avgcounts.find(name);
if (denominator != m_avgcounts.end()) {
if (denominator->second >= 1)
return numerator->second / denominator->second;
}
return numerator->second;
} }
int Profiler::getAvgCount(const std::string &name) const int Profiler::getAvgCount(const std::string &name) const
{ {
auto n = m_avgcounts.find(name); auto it = m_data.find(name);
if (it == m_data.end())
if (n != m_avgcounts.end() && n->second >= 1) return 1;
return n->second; int denominator = it->second.avgcount;
return denominator >= 1 ? denominator : 1;
return 1;
} }
u64 Profiler::getElapsedMs() const u64 Profiler::getElapsedMs() const
@ -204,6 +177,6 @@ void Profiler::getPage(GraphValues &o, u32 page, u32 pagecount)
continue; continue;
} }
o[i.first] = i.second / getAvgCount(i.first); o[i.first] = i.second.getValue();
} }
} }

View File

@ -58,54 +58,71 @@ public:
void getPage(GraphValues &o, u32 page, u32 pagecount); void getPage(GraphValues &o, u32 page, u32 pagecount);
void graphSet(const std::string &id, float value)
{
MutexAutoLock lock(m_mutex);
m_graphvalues[id] = value;
}
void graphAdd(const std::string &id, float value) void graphAdd(const std::string &id, float value)
{ {
MutexAutoLock lock(m_mutex); MutexAutoLock lock(m_mutex);
std::map<std::string, float>::iterator i = auto it = m_graphvalues.find(id);
m_graphvalues.find(id); if (it == m_graphvalues.end())
if(i == m_graphvalues.end()) m_graphvalues.emplace(id, value);
m_graphvalues[id] = value;
else else
i->second += value; it->second += value;
} }
void graphGet(GraphValues &result) void graphPop(GraphValues &result)
{ {
MutexAutoLock lock(m_mutex); MutexAutoLock lock(m_mutex);
result = m_graphvalues; assert(result.empty());
m_graphvalues.clear(); std::swap(result, m_graphvalues);
} }
void remove(const std::string& name) void remove(const std::string& name)
{ {
MutexAutoLock lock(m_mutex); MutexAutoLock lock(m_mutex);
m_avgcounts.erase(name);
m_data.erase(name); m_data.erase(name);
} }
private: private:
struct DataPair {
float value = 0;
int avgcount = 0;
inline float getValue() const {
return avgcount >= 1 ? (value / avgcount) : value;
}
};
std::mutex m_mutex; std::mutex m_mutex;
std::map<std::string, float> m_data; std::map<std::string, DataPair> m_data;
std::map<std::string, int> m_avgcounts;
std::map<std::string, float> m_graphvalues; std::map<std::string, float> m_graphvalues;
u64 m_start_time; u64 m_start_time;
}; };
enum ScopeProfilerType{ enum ScopeProfilerType : u8
SPT_ADD, {
SPT_ADD = 1,
SPT_AVG, SPT_AVG,
SPT_GRAPH_ADD, SPT_GRAPH_ADD,
SPT_MAX SPT_MAX
}; };
// Note: this class should be kept lightweight.
class ScopeProfiler class ScopeProfiler
{ {
public: public:
ScopeProfiler(Profiler *profiler, const std::string &name, ScopeProfiler(Profiler *profiler, const std::string &name,
ScopeProfilerType type = SPT_ADD); ScopeProfilerType type = SPT_ADD,
TimePrecision precision = PRECISION_MILLI);
~ScopeProfiler(); ~ScopeProfiler();
private: private:
Profiler *m_profiler = nullptr; Profiler *m_profiler = nullptr;
std::string m_name; std::string m_name;
TimeTaker *m_timer = nullptr; u64 m_time1;
enum ScopeProfilerType m_type; ScopeProfilerType m_type;
TimePrecision m_precision;
}; };

View File

@ -4096,10 +4096,9 @@ void dedicated_server_loop(Server &server, bool &kill)
/* /*
Profiler Profiler
*/ */
if (profiler_print_interval != 0) { if (profiler_print_interval > 0) {
if(m_profiler_interval.step(steplen, profiler_print_interval)) if (m_profiler_interval.step(steplen, profiler_print_interval)) {
{ infostream << "Profiler:" << std::endl;
infostream<<"Profiler:"<<std::endl;
g_profiler->print(infostream); g_profiler->print(infostream);
g_profiler->clear(); g_profiler->clear();
} }
@ -4112,6 +4111,12 @@ void dedicated_server_loop(Server &server, bool &kill)
ServerList::sendAnnounce(ServerList::AA_DELETE, ServerList::sendAnnounce(ServerList::AA_DELETE,
server.m_bind_addr.getPort()); server.m_bind_addr.getPort());
#endif #endif
if (profiler_print_interval > 0) {
infostream << "Profiler:" << std::endl;
g_profiler->print(infostream);
g_profiler->clear();
}
} }
/* /*

View File

@ -115,7 +115,7 @@ static TestAuthDatabase g_test_instance;
void TestAuthDatabase::runTests(IGameDef *gamedef) void TestAuthDatabase::runTests(IGameDef *gamedef)
{ {
// fixed directory, for persistence // fixed directory, for persistence
thread_local const std::string test_dir = getTestTempDirectory(); const std::string test_dir = getTestTempDirectory();
// Each set of tests is run twice for each database type: // Each set of tests is run twice for each database type:
// one where we reuse the same AuthDatabase object (to test local caching), // one where we reuse the same AuthDatabase object (to test local caching),

View File

@ -36,7 +36,7 @@ public:
void testFlagDesc(); void testFlagDesc();
static const char *config_text_before; static const char *config_text_before;
static const std::string config_text_after; static const char *config_text_after;
}; };
static TestSettings g_test_instance; static TestSettings g_test_instance;
@ -76,7 +76,7 @@ const char *TestSettings::config_text_before =
"zoop = true\n" "zoop = true\n"
"[dummy_eof_end_tag]\n"; "[dummy_eof_end_tag]\n";
const std::string TestSettings::config_text_after = const char *TestSettings::config_text_after =
u8"leet = 1337\n" u8"leet = 1337\n"
"leetleet = 13371337\n" "leetleet = 13371337\n"
"leetleet_neg = -13371337\n" "leetleet_neg = -13371337\n"

View File

@ -31,6 +31,7 @@ std::string QuicktuneValue::getString()
} }
return "<invalid type>"; return "<invalid type>";
} }
void QuicktuneValue::relativeAdd(float amount) void QuicktuneValue::relativeAdd(float amount)
{ {
switch(type){ switch(type){
@ -48,24 +49,16 @@ void QuicktuneValue::relativeAdd(float amount)
static std::map<std::string, QuicktuneValue> g_values; static std::map<std::string, QuicktuneValue> g_values;
static std::vector<std::string> g_names; static std::vector<std::string> g_names;
std::mutex *g_mutex = NULL; static std::mutex g_mutex;
static void makeMutex() const std::vector<std::string> &getQuicktuneNames()
{
if(!g_mutex){
g_mutex = new std::mutex();
}
}
std::vector<std::string> getQuicktuneNames()
{ {
return g_names; return g_names;
} }
QuicktuneValue getQuicktuneValue(const std::string &name) QuicktuneValue getQuicktuneValue(const std::string &name)
{ {
makeMutex(); MutexAutoLock lock(g_mutex);
MutexAutoLock lock(*g_mutex);
std::map<std::string, QuicktuneValue>::iterator i = g_values.find(name); std::map<std::string, QuicktuneValue>::iterator i = g_values.find(name);
if(i == g_values.end()){ if(i == g_values.end()){
QuicktuneValue val; QuicktuneValue val;
@ -77,17 +70,15 @@ QuicktuneValue getQuicktuneValue(const std::string &name)
void setQuicktuneValue(const std::string &name, const QuicktuneValue &val) void setQuicktuneValue(const std::string &name, const QuicktuneValue &val)
{ {
makeMutex(); MutexAutoLock lock(g_mutex);
MutexAutoLock lock(*g_mutex);
g_values[name] = val; g_values[name] = val;
g_values[name].modified = true; g_values[name].modified = true;
} }
void updateQuicktuneValue(const std::string &name, QuicktuneValue &val) void updateQuicktuneValue(const std::string &name, QuicktuneValue &val)
{ {
makeMutex(); MutexAutoLock lock(g_mutex);
MutexAutoLock lock(*g_mutex); auto i = g_values.find(name);
std::map<std::string, QuicktuneValue>::iterator i = g_values.find(name);
if(i == g_values.end()){ if(i == g_values.end()){
g_values[name] = val; g_values[name] = val;
g_names.push_back(name); g_names.push_back(name);

View File

@ -74,7 +74,7 @@ struct QuicktuneValue
void relativeAdd(float amount); void relativeAdd(float amount);
}; };
std::vector<std::string> getQuicktuneNames(); const std::vector<std::string> &getQuicktuneNames();
QuicktuneValue getQuicktuneValue(const std::string &name); QuicktuneValue getQuicktuneValue(const std::string &name);
void setQuicktuneValue(const std::string &name, const QuicktuneValue &val); void setQuicktuneValue(const std::string &name, const QuicktuneValue &val);

View File

@ -291,7 +291,7 @@ inline v3f readV3F32(const u8 *data)
inline void writeU8(u8 *data, u8 i) inline void writeU8(u8 *data, u8 i)
{ {
data[0] = (i >> 0) & 0xFF; data[0] = i;
} }
inline void writeS8(u8 *data, s8 i) inline void writeS8(u8 *data, s8 i)

View File

@ -23,12 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h" #include "log.h"
#include <ostream> #include <ostream>
TimeTaker::TimeTaker(const std::string &name, u64 *result, TimePrecision prec) void TimeTaker::start()
{ {
m_name = name; m_time1 = porting::getTime(m_precision);
m_result = result;
m_precision = prec;
m_time1 = porting::getTime(prec);
} }
u64 TimeTaker::stop(bool quiet) u64 TimeTaker::stop(bool quiet)
@ -39,15 +36,8 @@ u64 TimeTaker::stop(bool quiet)
(*m_result) += dtime; (*m_result) += dtime;
} else { } else {
if (!quiet) { if (!quiet) {
static const char* const units[] = {
"s" /* PRECISION_SECONDS */,
"ms" /* PRECISION_MILLI */,
"us" /* PRECISION_MICRO */,
"ns" /* PRECISION_NANO */,
};
infostream << m_name << " took " infostream << m_name << " took "
<< dtime << units[m_precision] << dtime << TimePrecision_units[m_precision] << std::endl;
<< std::endl;
} }
} }
m_running = false; m_running = false;

View File

@ -19,18 +19,43 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once #pragma once
#include <string>
#include "irrlichttypes.h" #include "irrlichttypes.h"
#include "gettime.h"
enum TimePrecision : s8
{
PRECISION_SECONDS,
PRECISION_MILLI,
PRECISION_MICRO,
PRECISION_NANO,
};
constexpr const char *TimePrecision_units[] = {
"s" /* PRECISION_SECONDS */,
"ms" /* PRECISION_MILLI */,
"us" /* PRECISION_MICRO */,
"ns" /* PRECISION_NANO */,
};
/* /*
TimeTaker TimeTaker
*/ */
// Note: this class should be kept lightweight
class TimeTaker class TimeTaker
{ {
public: public:
TimeTaker(const std::string &name, u64 *result=nullptr, TimeTaker(const std::string &name, u64 *result = nullptr,
TimePrecision prec=PRECISION_MILLI); TimePrecision prec = PRECISION_MILLI)
{
if (result)
m_result = result;
else
m_name = name;
m_precision = prec;
start();
}
~TimeTaker() ~TimeTaker()
{ {
@ -42,9 +67,11 @@ public:
u64 getTimerTime(); u64 getTimerTime();
private: private:
void start();
std::string m_name; std::string m_name;
u64 *m_result = nullptr;
u64 m_time1; u64 m_time1;
bool m_running = true; bool m_running = true;
TimePrecision m_precision; TimePrecision m_precision;
u64 *m_result = nullptr;
}; };