mirror of
https://github.com/minetest/minetest.git
synced 2024-12-21 21:52:25 +01:00
Add support for Tracy profiler (#15113)
This commit is contained in:
parent
6f23de41fb
commit
4aec4fbe6f
@ -56,6 +56,11 @@ if((WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR APPLE)
|
||||
endif()
|
||||
set(ENABLE_LTO ${DEFAULT_ENABLE_LTO} CACHE BOOL "Use Link Time Optimization")
|
||||
|
||||
set(BUILD_WITH_TRACY FALSE CACHE BOOL
|
||||
"Fetch and build with the Tracy profiler client")
|
||||
set(FETCH_TRACY_GIT_TAG "master" CACHE STRING
|
||||
"Git tag for fetching Tracy client. Match with your server (gui) version")
|
||||
|
||||
set(DEFAULT_RUN_IN_PLACE FALSE)
|
||||
if(WIN32)
|
||||
set(DEFAULT_RUN_IN_PLACE TRUE)
|
||||
@ -370,3 +375,19 @@ if(BUILD_DOCUMENTATION)
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Fetch Tracy
|
||||
if(BUILD_WITH_TRACY)
|
||||
include(FetchContent)
|
||||
|
||||
message(STATUS "Fetching Tracy (${FETCH_TRACY_GIT_TAG})...")
|
||||
FetchContent_Declare(
|
||||
tracy
|
||||
GIT_REPOSITORY https://github.com/wolfpld/tracy.git
|
||||
GIT_TAG ${FETCH_TRACY_GIT_TAG}
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(tracy)
|
||||
message(STATUS "Fetching Tracy - done")
|
||||
endif()
|
||||
|
@ -40,6 +40,8 @@ General options and their default values:
|
||||
ENABLE_UPDATE_CHECKER=TRUE - Whether to enable update checks by default
|
||||
INSTALL_DEVTEST=FALSE - Whether the Development Test game should be installed alongside Minetest
|
||||
USE_GPROF=FALSE - Enable profiling using GProf
|
||||
BUILD_WITH_TRACY=FALSE - Fetch and build with the Tracy profiler client
|
||||
FETCH_TRACY_GIT_TAG=master - Git tag for fetching Tracy client. Match with your server (gui) version
|
||||
VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
|
||||
|
||||
Library specific options:
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Miscellaneous
|
||||
|
||||
## Profiling Minetest on Linux
|
||||
## Profiling Minetest on Linux with perf
|
||||
|
||||
We will be using a tool called "perf", which you can get by installing `perf` or `linux-perf` or `linux-tools-common`.
|
||||
|
||||
@ -36,3 +36,54 @@ Give both files to the developer and also provide:
|
||||
* commit the source was built from and/or modified source code (if applicable)
|
||||
|
||||
Hotspot will resolve symbols correctly when pointing the sysroot option at the collected libs.
|
||||
|
||||
|
||||
## Profiling with Tracy
|
||||
|
||||
[Tracy](https://github.com/wolfpld/tracy) is
|
||||
> A real time, nanosecond resolution, remote telemetry, hybrid frame and sampling
|
||||
> profiler for games and other applications.
|
||||
|
||||
It allows one to annotate important functions and generate traces, where one can
|
||||
see when each individual function call happened, and how long it took.
|
||||
|
||||
Tracy can also record when frames, e.g. server step, start and end, and inspect
|
||||
frames that took longer than usual. Minetest already contains annotations for
|
||||
its frames.
|
||||
|
||||
See also [Tracy's official documentation](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf).
|
||||
|
||||
### Installing
|
||||
|
||||
Tracy consists of a client (Minetest) and a server (the gui).
|
||||
|
||||
Install the server, e.g. using your package manager.
|
||||
|
||||
### Building
|
||||
|
||||
Build Minetest with `-DDBUILD_WITH_TRACY=1`, this will fetch Tracy for building
|
||||
the Tracy client. And use `FETCH_TRACY_GIT_TAG` to get a version matching your
|
||||
Tracy server, e.g. `-DFETCH_TRACY_GIT_TAG=v0.11.0` if it's `0.11.0`.
|
||||
|
||||
To actually use Tracy, you also have to enable it with Tracy's build options:
|
||||
```
|
||||
-DTRACY_ENABLE=1 -DTRACY_ONLY_LOCALHOST=1
|
||||
```
|
||||
|
||||
See Tracy's documentation for more build options.
|
||||
|
||||
### Using in C++
|
||||
|
||||
Start the Tracy server and Minetest. You should see Minetest in the menu.
|
||||
|
||||
To actually get useful traces, you have to annotate functions with `ZoneScoped`
|
||||
macros and recompile. Please refer to Tracy's official documentation.
|
||||
|
||||
### Using in Lua
|
||||
|
||||
Tracy also supports Lua.
|
||||
If built with Tracy, Minetest loads its API in the global `tracy` table.
|
||||
See Tracy's official documentation for more information.
|
||||
|
||||
Note: The whole Tracy Lua API is accessible to all mods. And we don't check if it
|
||||
is or becomes insecure. Run untrusted mods at your own risk.
|
||||
|
@ -11394,6 +11394,16 @@ Functions: bit.tobit, bit.tohex, bit.bnot, bit.band, bit.bor, bit.bxor, bit.lshi
|
||||
|
||||
See http://bitop.luajit.org/ for advanced information.
|
||||
|
||||
Tracy Profiler
|
||||
--------------
|
||||
|
||||
Minetest can be built with support for the Tracy profiler, which can also be
|
||||
useful for profiling mods and is exposed to Lua as the global `tracy`.
|
||||
|
||||
See doc/developing/misc.md for details.
|
||||
|
||||
Note: This is a development feature and not covered by compatibility promises.
|
||||
|
||||
Error Handling
|
||||
--------------
|
||||
|
||||
|
@ -468,6 +468,10 @@ foreach(object_lib
|
||||
target_include_directories(${object_lib} PRIVATE ${link_includes})
|
||||
# Add objects from object library to main library
|
||||
target_sources(IrrlichtMt PRIVATE $<TARGET_OBJECTS:${object_lib}>)
|
||||
|
||||
if(BUILD_WITH_TRACY)
|
||||
target_link_libraries(${object_lib} PRIVATE Tracy::TracyClient)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Alias target provides add_submodule compatibility
|
||||
|
@ -648,6 +648,9 @@ if(BUILD_CLIENT)
|
||||
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
|
||||
target_link_libraries(${PROJECT_NAME} Catch2::Catch2)
|
||||
endif()
|
||||
if(BUILD_WITH_TRACY)
|
||||
target_link_libraries(${PROJECT_NAME} Tracy::TracyClient)
|
||||
endif()
|
||||
|
||||
if(PRECOMPILE_HEADERS)
|
||||
target_precompile_headers(${PROJECT_NAME} PRIVATE ${PRECOMPILED_HEADERS_LIST})
|
||||
@ -715,6 +718,9 @@ if(BUILD_SERVER)
|
||||
if(BUILD_UNITTESTS OR BUILD_BENCHMARKS)
|
||||
target_link_libraries(${PROJECT_NAME}server Catch2::Catch2)
|
||||
endif()
|
||||
if(BUILD_WITH_TRACY)
|
||||
target_link_libraries(${PROJECT_NAME}server Tracy::TracyClient)
|
||||
endif()
|
||||
|
||||
if(PRECOMPILE_HEADERS)
|
||||
target_precompile_headers(${PROJECT_NAME}server PRIVATE ${PRECOMPILED_HEADERS_LIST})
|
||||
|
@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "version.h"
|
||||
#include "renderingengine.h"
|
||||
#include "network/networkexceptions.h"
|
||||
#include "util/tracy_wrapper.h"
|
||||
#include <IGUISpriteBank.h>
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <unordered_map>
|
||||
@ -544,15 +545,19 @@ void ClientLauncher::main_menu(MainMenuData *menudata)
|
||||
video::IVideoDriver *driver = m_rendering_engine->get_video_driver();
|
||||
|
||||
infostream << "Waiting for other menus" << std::endl;
|
||||
auto framemarker = FrameMarker("ClientLauncher::main_menu()-wait-frame").started();
|
||||
while (m_rendering_engine->run() && !*kill) {
|
||||
if (!isMenuActive())
|
||||
break;
|
||||
driver->beginScene(true, true, video::SColor(255, 128, 128, 128));
|
||||
m_rendering_engine->get_gui_env()->drawAll();
|
||||
driver->endScene();
|
||||
framemarker.end();
|
||||
// On some computers framerate doesn't seem to be automatically limited
|
||||
sleep_ms(25);
|
||||
framemarker.start();
|
||||
}
|
||||
framemarker.end();
|
||||
infostream << "Waited for other menus" << std::endl;
|
||||
|
||||
auto *cur_control = m_rendering_engine->get_raw_device()->getCursorControl();
|
||||
|
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "settings.h"
|
||||
#include "camera.h" // CameraModes
|
||||
#include "util/basic_macros.h"
|
||||
#include "util/tracy_wrapper.h"
|
||||
#include "client/renderingengine.h"
|
||||
|
||||
#include <queue>
|
||||
@ -714,6 +715,8 @@ void ClientMap::touchMapBlocks()
|
||||
|
||||
void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
bool is_transparent_pass = pass == scene::ESNRP_TRANSPARENT;
|
||||
|
||||
std::string prefix;
|
||||
|
@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "util/basic_macros.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/directiontables.h"
|
||||
#include "util/tracy_wrapper.h"
|
||||
#include "mapblock_mesh.h"
|
||||
#include "settings.h"
|
||||
#include "nodedef.h"
|
||||
@ -1750,6 +1751,8 @@ void MapblockMeshGenerator::drawNode()
|
||||
|
||||
void MapblockMeshGenerator::generate()
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
for (cur_node.p.Z = 0; cur_node.p.Z < data->side_length; cur_node.p.Z++)
|
||||
for (cur_node.p.Y = 0; cur_node.p.Y < data->side_length; cur_node.p.Y++)
|
||||
for (cur_node.p.X = 0; cur_node.p.X < data->side_length; cur_node.p.X++) {
|
||||
|
@ -79,6 +79,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "hud.h"
|
||||
#include "clientdynamicinfo.h"
|
||||
#include <IAnimatedMeshSceneNode.h>
|
||||
#include "util/tracy_wrapper.h"
|
||||
|
||||
#if USE_SOUND
|
||||
#include "client/sound/sound_openal.h"
|
||||
@ -1140,6 +1141,8 @@ bool Game::startup(bool *kill,
|
||||
|
||||
void Game::run()
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
ProfilerGraph graph;
|
||||
RunStats stats = {};
|
||||
CameraOrientation cam_view_target = {};
|
||||
@ -1167,15 +1170,21 @@ void Game::run()
|
||||
const bool initial_window_maximized = !g_settings->getBool("fullscreen") &&
|
||||
g_settings->getBool("window_maximized");
|
||||
|
||||
auto framemarker = FrameMarker("Game::run()-frame").started();
|
||||
|
||||
while (m_rendering_engine->run()
|
||||
&& !(*kill || g_gamecallback->shutdown_requested
|
||||
|| (server && server->isShutdownRequested()))) {
|
||||
|
||||
framemarker.end();
|
||||
|
||||
// Calculate dtime =
|
||||
// m_rendering_engine->run() from this iteration
|
||||
// + Sleep time until the wanted FPS are reached
|
||||
draw_times.limit(device, &dtime, g_menumgr.pausesGame());
|
||||
|
||||
framemarker.start();
|
||||
|
||||
const auto current_dynamic_info = ClientDynamicInfo::getCurrent();
|
||||
if (!current_dynamic_info.equal(client_display_info)) {
|
||||
client_display_info = current_dynamic_info;
|
||||
@ -1232,6 +1241,8 @@ void Game::run()
|
||||
}
|
||||
}
|
||||
|
||||
framemarker.end();
|
||||
|
||||
RenderingEngine::autosaveScreensizeAndCo(initial_screen_size, initial_window_maximized);
|
||||
}
|
||||
|
||||
@ -1671,9 +1682,13 @@ bool Game::connectToServer(const GameStartData &start_data,
|
||||
|
||||
fps_control.reset();
|
||||
|
||||
auto framemarker = FrameMarker("Game::connectToServer()-frame").started();
|
||||
|
||||
while (m_rendering_engine->run()) {
|
||||
|
||||
framemarker.end();
|
||||
fps_control.limit(device, &dtime);
|
||||
framemarker.start();
|
||||
|
||||
// Update client and server
|
||||
step(dtime);
|
||||
@ -1719,6 +1734,7 @@ bool Game::connectToServer(const GameStartData &start_data,
|
||||
// Update status
|
||||
showOverlayMessage(N_("Connecting to server..."), dtime, 20);
|
||||
}
|
||||
framemarker.end();
|
||||
} catch (con::PeerNotFoundException &e) {
|
||||
warningstream << "This should not happen. Please report a bug." << std::endl;
|
||||
return false;
|
||||
@ -1736,9 +1752,11 @@ bool Game::getServerContent(bool *aborted)
|
||||
|
||||
fps_control.reset();
|
||||
|
||||
auto framemarker = FrameMarker("Game::getServerContent()-frame").started();
|
||||
while (m_rendering_engine->run()) {
|
||||
|
||||
framemarker.end();
|
||||
fps_control.limit(device, &dtime);
|
||||
framemarker.start();
|
||||
|
||||
// Update client and server
|
||||
step(dtime);
|
||||
@ -1804,6 +1822,7 @@ bool Game::getServerContent(bool *aborted)
|
||||
texture_src, dtime, progress);
|
||||
}
|
||||
}
|
||||
framemarker.end();
|
||||
|
||||
*aborted = true;
|
||||
infostream << "Connect aborted [device]" << std::endl;
|
||||
@ -2773,6 +2792,8 @@ void Game::updatePauseState()
|
||||
|
||||
inline void Game::step(f32 dtime)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
if (server) {
|
||||
float fps_max = (!device->isWindowFocused() || g_menumgr.pausesGame()) ?
|
||||
g_settings->getFloat("fps_max_unfocused") :
|
||||
@ -4052,6 +4073,7 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
|
||||
void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
|
||||
const CameraOrientation &cam)
|
||||
{
|
||||
ZoneScoped;
|
||||
TimeTaker tt_update("Game::updateFrame()");
|
||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||
|
||||
@ -4311,6 +4333,8 @@ void Game::updateShadows()
|
||||
|
||||
void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
const video::SColor fog_color = this->sky->getFogColor();
|
||||
const video::SColor sky_color = this->sky->getSkyColor();
|
||||
|
||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "minimap.h"
|
||||
#include "content_mapblock.h"
|
||||
#include "util/directiontables.h"
|
||||
#include "util/tracy_wrapper.h"
|
||||
#include "client/meshgen/collector.h"
|
||||
#include "client/renderingengine.h"
|
||||
#include <array>
|
||||
@ -611,6 +612,8 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data, v3s16 camera_offs
|
||||
m_last_crack(-1),
|
||||
m_last_daynight_ratio((u32) -1)
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
for (auto &m : m_mesh)
|
||||
m = new scene::SMesh();
|
||||
m_enable_shaders = data->m_use_shaders;
|
||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#include "sound_singleton.h"
|
||||
#include "util/numeric.h" // myrand()
|
||||
#include "util/tracy_wrapper.h"
|
||||
#include "filesys.h"
|
||||
#include "porting.h"
|
||||
|
||||
@ -501,6 +502,8 @@ void *OpenALSoundManager::run()
|
||||
|
||||
u64 t_step_start = porting::getTimeMs();
|
||||
while (true) {
|
||||
auto framemarker = FrameMarker("OpenALSoundManager::run()-frame").started();
|
||||
|
||||
auto get_time_since_last_step = [&] {
|
||||
return (f32)(porting::getTimeMs() - t_step_start);
|
||||
};
|
||||
|
@ -41,3 +41,4 @@
|
||||
#cmakedefine01 BUILD_UNITTESTS
|
||||
#cmakedefine01 BUILD_BENCHMARKS
|
||||
#cmakedefine01 USE_SDL2
|
||||
#cmakedefine01 BUILD_WITH_TRACY
|
||||
|
@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include <ICameraSceneNode.h>
|
||||
#include <IGUIStaticText.h>
|
||||
#include "client/imagefilters.h"
|
||||
#include "util/tracy_wrapper.h"
|
||||
|
||||
#if USE_SOUND
|
||||
#include "client/sound/sound_openal.h"
|
||||
@ -329,9 +330,12 @@ void GUIEngine::run()
|
||||
|
||||
fps_control.reset();
|
||||
|
||||
while (m_rendering_engine->run() && !m_startgame && !m_kill) {
|
||||
auto framemarker = FrameMarker("GUIEngine::run()-frame").started();
|
||||
|
||||
while (m_rendering_engine->run() && !m_startgame && !m_kill) {
|
||||
framemarker.end();
|
||||
fps_control.limit(device, &dtime);
|
||||
framemarker.start();
|
||||
|
||||
if (device->isWindowVisible()) {
|
||||
// check if we need to update the "upper left corner"-text
|
||||
@ -371,6 +375,7 @@ void GUIEngine::run()
|
||||
m_menu->getAndroidUIInput();
|
||||
#endif
|
||||
}
|
||||
framemarker.end();
|
||||
|
||||
m_script->beforeClose();
|
||||
|
||||
|
@ -73,6 +73,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "filesys.h"
|
||||
#include "log.h"
|
||||
#include "util/string.h"
|
||||
#include "util/tracy_wrapper.h"
|
||||
#include <vector>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
@ -960,6 +961,8 @@ void TrackFreedMemory(size_t amount)
|
||||
|
||||
void TriggerMemoryTrim()
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
constexpr auto MO = std::memory_order_relaxed;
|
||||
if (memory_freed.load(MO) >= MEMORY_TRIM_THRESHOLD) {
|
||||
// Synchronize call
|
||||
|
@ -32,6 +32,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "client/client.h"
|
||||
#endif
|
||||
|
||||
#if BUILD_WITH_TRACY
|
||||
#include "tracy/TracyLua.hpp"
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "lualib.h"
|
||||
@ -95,6 +98,11 @@ ScriptApiBase::ScriptApiBase(ScriptingType type):
|
||||
lua_pushstring(m_luastack, LUA_BITLIBNAME);
|
||||
lua_call(m_luastack, 1, 0);
|
||||
|
||||
#if BUILD_WITH_TRACY
|
||||
// Load tracy lua bindings
|
||||
tracy::LuaRegister(m_luastack);
|
||||
#endif
|
||||
|
||||
// Make the ScriptApiBase* accessible to ModApiBase
|
||||
#if INDIRECT_SCRIPTAPI_RIDX
|
||||
*(void **)(lua_newuserdata(m_luastack, sizeof(void *))) = this;
|
||||
|
@ -109,7 +109,12 @@ void ScriptApiSecurity::initializeSecurity()
|
||||
"string",
|
||||
"table",
|
||||
"math",
|
||||
"bit"
|
||||
"bit",
|
||||
// Not sure if completely safe. But if someone enables tracy, they'll
|
||||
// know what they do.
|
||||
#if BUILD_WITH_TRACY
|
||||
"tracy",
|
||||
#endif
|
||||
};
|
||||
static const char *io_whitelist[] = {
|
||||
"close",
|
||||
@ -303,6 +308,11 @@ void ScriptApiSecurity::initializeSecurityClient()
|
||||
"table",
|
||||
"math",
|
||||
"bit",
|
||||
// Not sure if completely safe. But if someone enables tracy, they'll
|
||||
// know what they do.
|
||||
#if BUILD_WITH_TRACY
|
||||
"tracy",
|
||||
#endif
|
||||
};
|
||||
static const char *os_whitelist[] = {
|
||||
"clock",
|
||||
|
@ -75,6 +75,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "gameparams.h"
|
||||
#include "particles.h"
|
||||
#include "gettext.h"
|
||||
#include "util/tracy_wrapper.h"
|
||||
|
||||
class ClientNotFoundException : public BaseException
|
||||
{
|
||||
@ -101,6 +102,8 @@ private:
|
||||
|
||||
void *ServerThread::run()
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
/*
|
||||
@ -110,6 +113,7 @@ void *ServerThread::run()
|
||||
* server-step frequency. Receive() is used for waiting between the steps.
|
||||
*/
|
||||
|
||||
auto framemarker = FrameMarker("ServerThread::run()-frame").started();
|
||||
try {
|
||||
m_server->AsyncRunStep(0.0f, true);
|
||||
} catch (con::ConnectionBindFailed &e) {
|
||||
@ -119,10 +123,12 @@ void *ServerThread::run()
|
||||
} catch (ModError &e) {
|
||||
m_server->setAsyncFatalError(e.what());
|
||||
}
|
||||
framemarker.end();
|
||||
|
||||
float dtime = 0.0f;
|
||||
|
||||
while (!stopRequested()) {
|
||||
framemarker.start();
|
||||
ScopeProfiler spm(g_profiler, "Server::RunStep() (max)", SPT_MAX);
|
||||
|
||||
u64 t0 = porting::getTimeUs();
|
||||
@ -149,6 +155,7 @@ void *ServerThread::run()
|
||||
}
|
||||
|
||||
dtime = 1e-6f * (porting::getTimeUs() - t0);
|
||||
framemarker.end();
|
||||
}
|
||||
|
||||
END_DEBUG_EXCEPTION_HANDLER
|
||||
@ -607,6 +614,9 @@ void Server::step()
|
||||
|
||||
void Server::AsyncRunStep(float dtime, bool initial_step)
|
||||
{
|
||||
ZoneScoped;
|
||||
auto framemarker = FrameMarker("Server::AsyncRunStep()-frame").started();
|
||||
|
||||
{
|
||||
// Send blocks to clients
|
||||
SendBlocks(dtime);
|
||||
@ -1055,6 +1065,9 @@ void Server::AsyncRunStep(float dtime, bool initial_step)
|
||||
|
||||
void Server::Receive(float timeout)
|
||||
{
|
||||
ZoneScoped;
|
||||
auto framemarker = FrameMarker("Server::Receive()-frame").started();
|
||||
|
||||
const u64 t0 = porting::getTimeUs();
|
||||
const float timeout_us = timeout * 1e6f;
|
||||
auto remaining_time_us = [&]() -> float {
|
||||
|
200
src/util/tracy_wrapper.h
Normal file
200
src/util/tracy_wrapper.h
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2024 DS
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Wrapper for <tracy/Tracy.hpp>, so that we can use Tracy's macros without
|
||||
* having it as mandatory dependency.
|
||||
*
|
||||
* For annotations that you don't intend to upstream, you can also include
|
||||
* <tracy/Tracy.hpp> directly (which also works in irr/).
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
#include "util/basic_macros.h"
|
||||
|
||||
#if BUILD_WITH_TRACY
|
||||
|
||||
#include <tracy/Tracy.hpp> // IWYU pragma: export
|
||||
|
||||
#else
|
||||
|
||||
// Copied from Tracy.hpp
|
||||
|
||||
#define TracyNoop
|
||||
|
||||
#define ZoneNamed(x,y)
|
||||
#define ZoneNamedN(x,y,z)
|
||||
#define ZoneNamedC(x,y,z)
|
||||
#define ZoneNamedNC(x,y,z,w)
|
||||
|
||||
#define ZoneTransient(x,y)
|
||||
#define ZoneTransientN(x,y,z)
|
||||
|
||||
#define ZoneScoped
|
||||
#define ZoneScopedN(x)
|
||||
#define ZoneScopedC(x)
|
||||
#define ZoneScopedNC(x,y)
|
||||
|
||||
#define ZoneText(x,y)
|
||||
#define ZoneTextV(x,y,z)
|
||||
#define ZoneTextF(x,...)
|
||||
#define ZoneTextVF(x,y,...)
|
||||
#define ZoneName(x,y)
|
||||
#define ZoneNameV(x,y,z)
|
||||
#define ZoneNameF(x,...)
|
||||
#define ZoneNameVF(x,y,...)
|
||||
#define ZoneColor(x)
|
||||
#define ZoneColorV(x,y)
|
||||
#define ZoneValue(x)
|
||||
#define ZoneValueV(x,y)
|
||||
#define ZoneIsActive false
|
||||
#define ZoneIsActiveV(x) false
|
||||
|
||||
#define FrameMark
|
||||
#define FrameMarkNamed(x)
|
||||
#define FrameMarkStart(x)
|
||||
#define FrameMarkEnd(x)
|
||||
|
||||
#define FrameImage(x,y,z,w,a)
|
||||
|
||||
#define TracyLockable( type, varname ) type varname
|
||||
#define TracyLockableN( type, varname, desc ) type varname
|
||||
#define TracySharedLockable( type, varname ) type varname
|
||||
#define TracySharedLockableN( type, varname, desc ) type varname
|
||||
#define LockableBase( type ) type
|
||||
#define SharedLockableBase( type ) type
|
||||
#define LockMark(x) (void)x
|
||||
#define LockableName(x,y,z)
|
||||
|
||||
#define TracyPlot(x,y)
|
||||
#define TracyPlotConfig(x,y,z,w,a)
|
||||
|
||||
#define TracyMessage(x,y)
|
||||
#define TracyMessageL(x)
|
||||
#define TracyMessageC(x,y,z)
|
||||
#define TracyMessageLC(x,y)
|
||||
#define TracyAppInfo(x,y)
|
||||
|
||||
#define TracyAlloc(x,y)
|
||||
#define TracyFree(x)
|
||||
#define TracySecureAlloc(x,y)
|
||||
#define TracySecureFree(x)
|
||||
|
||||
#define TracyAllocN(x,y,z)
|
||||
#define TracyFreeN(x,y)
|
||||
#define TracySecureAllocN(x,y,z)
|
||||
#define TracySecureFreeN(x,y)
|
||||
|
||||
#define ZoneNamedS(x,y,z)
|
||||
#define ZoneNamedNS(x,y,z,w)
|
||||
#define ZoneNamedCS(x,y,z,w)
|
||||
#define ZoneNamedNCS(x,y,z,w,a)
|
||||
|
||||
#define ZoneTransientS(x,y,z)
|
||||
#define ZoneTransientNS(x,y,z,w)
|
||||
|
||||
#define ZoneScopedS(x)
|
||||
#define ZoneScopedNS(x,y)
|
||||
#define ZoneScopedCS(x,y)
|
||||
#define ZoneScopedNCS(x,y,z)
|
||||
|
||||
#define TracyAllocS(x,y,z)
|
||||
#define TracyFreeS(x,y)
|
||||
#define TracySecureAllocS(x,y,z)
|
||||
#define TracySecureFreeS(x,y)
|
||||
|
||||
#define TracyAllocNS(x,y,z,w)
|
||||
#define TracyFreeNS(x,y,z)
|
||||
#define TracySecureAllocNS(x,y,z,w)
|
||||
#define TracySecureFreeNS(x,y,z)
|
||||
|
||||
#define TracyMessageS(x,y,z)
|
||||
#define TracyMessageLS(x,y)
|
||||
#define TracyMessageCS(x,y,z,w)
|
||||
#define TracyMessageLCS(x,y,z)
|
||||
|
||||
#define TracySourceCallbackRegister(x,y)
|
||||
#define TracyParameterRegister(x,y)
|
||||
#define TracyParameterSetup(x,y,z,w)
|
||||
#define TracyIsConnected false
|
||||
#define TracyIsStarted false
|
||||
#define TracySetProgramName(x)
|
||||
|
||||
#define TracyFiberEnter(x)
|
||||
#define TracyFiberEnterHint(x,y)
|
||||
#define TracyFiberLeave
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Helper for making sure frames end in all possible control flow path
|
||||
class FrameMarker
|
||||
{
|
||||
const char *m_name;
|
||||
bool m_started = false;
|
||||
|
||||
public:
|
||||
FrameMarker(const char *name) : m_name(name) {}
|
||||
|
||||
~FrameMarker() { end(); }
|
||||
|
||||
DISABLE_CLASS_COPY(FrameMarker)
|
||||
|
||||
FrameMarker(FrameMarker &&other) noexcept :
|
||||
m_name(other.m_name), m_started(other.m_started)
|
||||
{
|
||||
other.m_started = false;
|
||||
}
|
||||
|
||||
FrameMarker &operator=(FrameMarker &&other) noexcept
|
||||
{
|
||||
if (&other != this) {
|
||||
end();
|
||||
m_name = other.m_name;
|
||||
m_started = other.m_started;
|
||||
other.m_started = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
FrameMarker &&started() &&
|
||||
{
|
||||
if (!m_started) {
|
||||
FrameMarkStart(m_name);
|
||||
m_started = true;
|
||||
}
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
// no move happens, because we drop the reference
|
||||
(void)std::move(*this).started();
|
||||
}
|
||||
|
||||
void end()
|
||||
{
|
||||
if (m_started) {
|
||||
m_started = false;
|
||||
FrameMarkEnd(m_name);
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user