mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-03 13:13:23 +00:00
Lua Profiler
This commit is contained in:
parent
6fa65e4729
commit
02a9069a0e
@ -100,6 +100,8 @@ namespace MWBase
|
|||||||
virtual void handleConsoleCommand(
|
virtual void handleConsoleCommand(
|
||||||
const std::string& consoleMode, const std::string& command, const MWWorld::Ptr& selectedPtr)
|
const std::string& consoleMode, const std::string& command, const MWWorld::Ptr& selectedPtr)
|
||||||
= 0;
|
= 0;
|
||||||
|
|
||||||
|
virtual std::string formatResourceUsageStats() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,7 @@ namespace MWBase
|
|||||||
virtual void updateSpellWindow() = 0;
|
virtual void updateSpellWindow() = 0;
|
||||||
|
|
||||||
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0;
|
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0;
|
||||||
|
virtual MWWorld::Ptr getConsoleSelectedObject() const = 0;
|
||||||
virtual void setConsoleMode(const std::string& mode) = 0;
|
virtual void setConsoleMode(const std::string& mode) = 0;
|
||||||
|
|
||||||
static constexpr std::string_view sConsoleColor_Default = "#FFFFFF";
|
static constexpr std::string_view sConsoleColor_Default = "#FFFFFF";
|
||||||
|
@ -23,6 +23,7 @@ namespace MWGui
|
|||||||
public:
|
public:
|
||||||
/// Set the implicit object for script execution
|
/// Set the implicit object for script execution
|
||||||
void setSelectedObject(const MWWorld::Ptr& object);
|
void setSelectedObject(const MWWorld::Ptr& object);
|
||||||
|
MWWorld::Ptr getSelectedObject() const { return mPtr; }
|
||||||
|
|
||||||
MyGUI::EditBox* mCommandLine;
|
MyGUI::EditBox* mCommandLine;
|
||||||
MyGUI::EditBox* mHistory;
|
MyGUI::EditBox* mHistory;
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
#include <components/debug/debugging.hpp>
|
#include <components/debug/debugging.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/luamanager.hpp"
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#ifndef BT_NO_PROFILE
|
#ifndef BT_NO_PROFILE
|
||||||
@ -106,6 +109,12 @@ namespace MWGui
|
|||||||
= itemLV->createWidgetReal<MyGUI::EditBox>("LogEdit", MyGUI::FloatCoord(0, 0, 1, 1), MyGUI::Align::Stretch);
|
= itemLV->createWidgetReal<MyGUI::EditBox>("LogEdit", MyGUI::FloatCoord(0, 0, 1, 1), MyGUI::Align::Stretch);
|
||||||
mLogView->setEditReadOnly(true);
|
mLogView->setEditReadOnly(true);
|
||||||
|
|
||||||
|
MyGUI::TabItem* itemLuaProfiler = mTabControl->addItem("Lua Profiler");
|
||||||
|
itemLuaProfiler->setCaptionWithReplacing(" #{DebugMenu:LuaProfiler} ");
|
||||||
|
mLuaProfiler = itemLuaProfiler->createWidgetReal<MyGUI::EditBox>(
|
||||||
|
"LogEdit", MyGUI::FloatCoord(0, 0, 1, 1), MyGUI::Align::Stretch);
|
||||||
|
mLuaProfiler->setEditReadOnly(true);
|
||||||
|
|
||||||
#ifndef BT_NO_PROFILE
|
#ifndef BT_NO_PROFILE
|
||||||
MyGUI::TabItem* item = mTabControl->addItem("Physics Profiler");
|
MyGUI::TabItem* item = mTabControl->addItem("Physics Profiler");
|
||||||
item->setCaptionWithReplacing(" #{DebugMenu:PhysicsProfiler} ");
|
item->setCaptionWithReplacing(" #{DebugMenu:PhysicsProfiler} ");
|
||||||
@ -206,6 +215,16 @@ namespace MWGui
|
|||||||
mLogView->setVScrollPosition(scrollPos);
|
mLogView->setVScrollPosition(scrollPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugWindow::updateLuaProfile()
|
||||||
|
{
|
||||||
|
if (mLuaProfiler->isTextSelection())
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t previousPos = mLuaProfiler->getVScrollPosition();
|
||||||
|
mLuaProfiler->setCaption(MWBase::Environment::get().getLuaManager()->formatResourceUsageStats());
|
||||||
|
mLuaProfiler->setVScrollPosition(std::min(previousPos, mLuaProfiler->getVScrollRange() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
void DebugWindow::updateBulletProfile()
|
void DebugWindow::updateBulletProfile()
|
||||||
{
|
{
|
||||||
#ifndef BT_NO_PROFILE
|
#ifndef BT_NO_PROFILE
|
||||||
@ -229,9 +248,18 @@ namespace MWGui
|
|||||||
return;
|
return;
|
||||||
timer = 0.25;
|
timer = 0.25;
|
||||||
|
|
||||||
if (mTabControl->getIndexSelected() == 0)
|
switch (mTabControl->getIndexSelected())
|
||||||
updateLogView();
|
{
|
||||||
else
|
case 0:
|
||||||
updateBulletProfile();
|
updateLogView();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
updateLuaProfile();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
updateBulletProfile();
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,12 @@ namespace MWGui
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void updateLogView();
|
void updateLogView();
|
||||||
|
void updateLuaProfile();
|
||||||
void updateBulletProfile();
|
void updateBulletProfile();
|
||||||
|
|
||||||
MyGUI::TabControl* mTabControl;
|
MyGUI::TabControl* mTabControl;
|
||||||
MyGUI::EditBox* mLogView;
|
MyGUI::EditBox* mLogView;
|
||||||
|
MyGUI::EditBox* mLuaProfiler;
|
||||||
MyGUI::EditBox* mBulletProfilerEdit;
|
MyGUI::EditBox* mBulletProfilerEdit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2158,6 +2158,11 @@ namespace MWGui
|
|||||||
mConsole->setSelectedObject(object);
|
mConsole->setSelectedObject(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MWWorld::Ptr WindowManager::getConsoleSelectedObject() const
|
||||||
|
{
|
||||||
|
return mConsole->getSelectedObject();
|
||||||
|
}
|
||||||
|
|
||||||
void WindowManager::printToConsole(const std::string& msg, std::string_view color)
|
void WindowManager::printToConsole(const std::string& msg, std::string_view color)
|
||||||
{
|
{
|
||||||
mConsole->print(msg, color);
|
mConsole->print(msg, color);
|
||||||
|
@ -188,6 +188,7 @@ namespace MWGui
|
|||||||
void updateSpellWindow() override;
|
void updateSpellWindow() override;
|
||||||
|
|
||||||
void setConsoleSelectedObject(const MWWorld::Ptr& object) override;
|
void setConsoleSelectedObject(const MWWorld::Ptr& object) override;
|
||||||
|
MWWorld::Ptr getConsoleSelectedObject() const override;
|
||||||
void printToConsole(const std::string& msg, std::string_view color) override;
|
void printToConsole(const std::string& msg, std::string_view color) override;
|
||||||
void setConsoleMode(const std::string& mode) override;
|
void setConsoleMode(const std::string& mode) override;
|
||||||
|
|
||||||
|
@ -37,8 +37,16 @@
|
|||||||
namespace MWLua
|
namespace MWLua
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static LuaUtil::LuaStateSettings createLuaStateSettings()
|
||||||
|
{
|
||||||
|
return { .mInstructionLimit = Settings::Manager::getUInt64("instruction limit per call", "Lua"),
|
||||||
|
.mMemoryLimit = Settings::Manager::getUInt64("memory limit", "Lua"),
|
||||||
|
.mSmallAllocMaxSize = Settings::Manager::getUInt64("small alloc max size", "Lua"),
|
||||||
|
.mLogMemoryUsage = Settings::Manager::getBool("log memory usage", "Lua") };
|
||||||
|
}
|
||||||
|
|
||||||
LuaManager::LuaManager(const VFS::Manager* vfs, const std::filesystem::path& libsDir)
|
LuaManager::LuaManager(const VFS::Manager* vfs, const std::filesystem::path& libsDir)
|
||||||
: mLua(vfs, &mConfiguration)
|
: mLua(vfs, &mConfiguration, createLuaStateSettings())
|
||||||
, mUiResourceManager(vfs)
|
, mUiResourceManager(vfs)
|
||||||
{
|
{
|
||||||
Log(Debug::Info) << "Lua version: " << LuaUtil::getLuaVersion();
|
Log(Debug::Info) << "Lua version: " << LuaUtil::getLuaVersion();
|
||||||
@ -605,9 +613,90 @@ namespace MWLua
|
|||||||
mActionQueue.push_back(std::make_unique<FunctionAction>(&mLua, std::move(action), name));
|
mActionQueue.push_back(std::make_unique<FunctionAction>(&mLua, std::move(action), name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaManager::reportStats(unsigned int frameNumber, osg::Stats& stats)
|
void LuaManager::reportStats(unsigned int frameNumber, osg::Stats& stats) const
|
||||||
{
|
{
|
||||||
const sol::state_view state(mLua.sol());
|
stats.setAttribute(frameNumber, "Lua UsedMemory", mLua.getTotalMemoryUsage());
|
||||||
stats.setAttribute(frameNumber, "Lua UsedMemory", state.memory_used());
|
}
|
||||||
|
|
||||||
|
std::string LuaManager::formatResourceUsageStats() const
|
||||||
|
{
|
||||||
|
std::stringstream out;
|
||||||
|
|
||||||
|
static const uint64_t smallAllocSize = Settings::Manager::getUInt64("small alloc max size", "Lua");
|
||||||
|
out << "Total memory usage: " << mLua.getTotalMemoryUsage() << "\n";
|
||||||
|
out << "small alloc max size = " << smallAllocSize << " (section [Lua] in settings.cfg)\n";
|
||||||
|
out << "Smaller values give more information for the profiler, but increase performance overhead.\n";
|
||||||
|
out << " Memory allocations <= " << smallAllocSize << " bytes: " << mLua.getSmallAllocMemoryUsage()
|
||||||
|
<< " (not tracked)\n";
|
||||||
|
out << " Memory allocations > " << smallAllocSize
|
||||||
|
<< " bytes: " << mLua.getTotalMemoryUsage() - mLua.getSmallAllocMemoryUsage() << " (see the table below)\n";
|
||||||
|
out << "\n";
|
||||||
|
|
||||||
|
using Stats = LuaUtil::ScriptsContainer::ScriptStats;
|
||||||
|
|
||||||
|
std::vector<Stats> activeStats;
|
||||||
|
mGlobalScripts.collectStats(activeStats);
|
||||||
|
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||||
|
scripts->collectStats(activeStats);
|
||||||
|
|
||||||
|
std::vector<Stats> selectedStats;
|
||||||
|
MWWorld::Ptr selectedPtr = MWBase::Environment::get().getWindowManager()->getConsoleSelectedObject();
|
||||||
|
LocalScripts* selectedScripts = nullptr;
|
||||||
|
if (!selectedPtr.isEmpty())
|
||||||
|
{
|
||||||
|
selectedScripts = selectedPtr.getRefData().getLuaScripts();
|
||||||
|
if (selectedScripts)
|
||||||
|
selectedScripts->collectStats(selectedStats);
|
||||||
|
out << "Profiled object (selected in the in-game console): " << ptrToString(selectedPtr) << "\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out << "No selected object. Use the in-game console to select an object for detailed profile.\n";
|
||||||
|
out << "\n";
|
||||||
|
|
||||||
|
constexpr int nameW = 50;
|
||||||
|
constexpr int valueW = 12;
|
||||||
|
|
||||||
|
out << std::left;
|
||||||
|
out << " " << std::setw(nameW + 2) << "*** Resource usage per script";
|
||||||
|
out << std::right;
|
||||||
|
out << std::setw(valueW) << "CPU";
|
||||||
|
out << std::setw(valueW) << "memory";
|
||||||
|
out << std::setw(valueW) << "memory";
|
||||||
|
out << std::setw(valueW) << "CPU";
|
||||||
|
out << std::setw(valueW) << "memory";
|
||||||
|
out << "\n";
|
||||||
|
out << std::left << " " << std::setw(nameW + 2) << "[name]" << std::right;
|
||||||
|
out << std::setw(valueW) << "[all]";
|
||||||
|
out << std::setw(valueW) << "[active]";
|
||||||
|
out << std::setw(valueW) << "[inactive]";
|
||||||
|
out << std::setw(valueW * 2) << "[for selected object]";
|
||||||
|
out << "\n";
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mConfiguration.size(); ++i)
|
||||||
|
{
|
||||||
|
bool isGlobal = mConfiguration[i].mFlags & ESM::LuaScriptCfg::sGlobal;
|
||||||
|
|
||||||
|
out << std::left;
|
||||||
|
out << " " << std::setw(nameW) << mConfiguration[i].mScriptPath;
|
||||||
|
if (mConfiguration[i].mScriptPath.size() > nameW)
|
||||||
|
out << "\n " << std::setw(nameW) << ""; // if path is too long, break line
|
||||||
|
out << std::right;
|
||||||
|
out << std::setw(valueW) << static_cast<int64_t>(activeStats[i].mCPUusage);
|
||||||
|
out << std::setw(valueW) << activeStats[i].mMemoryUsage;
|
||||||
|
out << std::setw(valueW) << mLua.getMemoryUsageByScriptIndex(i) - activeStats[i].mMemoryUsage;
|
||||||
|
|
||||||
|
if (isGlobal)
|
||||||
|
out << std::setw(valueW * 2) << "NA (global script)";
|
||||||
|
else if (selectedPtr.isEmpty())
|
||||||
|
out << std::setw(valueW * 2) << "NA (not selected) ";
|
||||||
|
else if (!selectedScripts || !selectedScripts->hasScript(i))
|
||||||
|
out << std::setw(valueW) << "-" << std::setw(valueW) << selectedStats[i].mMemoryUsage;
|
||||||
|
else
|
||||||
|
out << std::setw(valueW) << static_cast<int64_t>(selectedStats[i].mCPUusage) << std::setw(valueW)
|
||||||
|
<< selectedStats[i].mMemoryUsage;
|
||||||
|
out << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,8 @@ namespace MWLua
|
|||||||
|
|
||||||
bool isProcessingInputEvents() const { return mProcessingInputEvents; }
|
bool isProcessingInputEvents() const { return mProcessingInputEvents; }
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats& stats);
|
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||||
|
std::string formatResourceUsageStats() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initConfiguration();
|
void initConfiguration();
|
||||||
|
@ -26,3 +26,64 @@ If one, a separate thread is used.
|
|||||||
Values >1 are not yet supported.
|
Values >1 are not yet supported.
|
||||||
|
|
||||||
This setting can only be configured by editing the settings configuration file.
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
lua profiler
|
||||||
|
------------
|
||||||
|
|
||||||
|
:Type: boolean
|
||||||
|
:Range: True/False
|
||||||
|
:Default: True
|
||||||
|
|
||||||
|
Enables Lua profiler.
|
||||||
|
|
||||||
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
small alloc max size
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
:Type: integer
|
||||||
|
:Range: >= 0
|
||||||
|
:Default: 1024
|
||||||
|
|
||||||
|
No ownership tracking for memory allocations below or equal this size (in bytes).
|
||||||
|
This setting is used only if ``lua profiler = true``.
|
||||||
|
With the default value (1024) the lua profiler will show almost no memory usage because allocation more than 1KB are rare.
|
||||||
|
Decrease the value of this setting (e.g. set it to 64) to have better memory tracking by the cost of higher overhead.
|
||||||
|
|
||||||
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
memory limit
|
||||||
|
------------
|
||||||
|
|
||||||
|
:Type: integer
|
||||||
|
:Range: > 0
|
||||||
|
:Default: 2147483648 (2GB)
|
||||||
|
|
||||||
|
Memory limit for Lua runtime (only if ``lua profiler = true``). If exceeded then only small allocations are allowed.
|
||||||
|
Small allocations are always allowed, so e.g. Lua console can function.
|
||||||
|
|
||||||
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
log memory usage
|
||||||
|
----------------
|
||||||
|
|
||||||
|
:Type: boolean
|
||||||
|
:Range: True/False
|
||||||
|
:Default: False
|
||||||
|
|
||||||
|
Print debug info about memory usage (only if ``lua profiler = true``).
|
||||||
|
|
||||||
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
instruction limit per call
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
:Type: integer
|
||||||
|
:Range: > 1000
|
||||||
|
:Default: 100000000
|
||||||
|
|
||||||
|
The maximal number of Lua instructions per function call (only if ``lua profiler = true``).
|
||||||
|
If exceeded (e.g. because of an infinite loop) the function will be terminated.
|
||||||
|
|
||||||
|
This setting can only be configured by editing the settings configuration file.
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
DebugWindow: "Debug"
|
DebugWindow: "Debug"
|
||||||
LogViewer: "Protokollansicht"
|
LogViewer: "Protokollansicht"
|
||||||
|
LuaProfiler: "Lua-Profiler"
|
||||||
PhysicsProfiler: "Physik-Profiler"
|
PhysicsProfiler: "Physik-Profiler"
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
DebugWindow: "Debug"
|
DebugWindow: "Debug"
|
||||||
LogViewer: "Log Viewer"
|
LogViewer: "Log Viewer"
|
||||||
|
LuaProfiler: "Lua Profiler"
|
||||||
PhysicsProfiler: "Physics Profiler"
|
PhysicsProfiler: "Physics Profiler"
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
DebugWindow: "Меню отладки"
|
DebugWindow: "Меню отладки"
|
||||||
LogViewer: "Журнал логов"
|
LogViewer: "Журнал логов"
|
||||||
|
LuaProfiler: "Профилировщик Луа"
|
||||||
PhysicsProfiler: "Профилировщик физики"
|
PhysicsProfiler: "Профилировщик физики"
|
||||||
|
@ -1141,6 +1141,19 @@ lua debug = false
|
|||||||
# If zero, Lua scripts are processed in the main thread.
|
# If zero, Lua scripts are processed in the main thread.
|
||||||
lua num threads = 1
|
lua num threads = 1
|
||||||
|
|
||||||
|
# No ownership tracking for allocations below or equal this size.
|
||||||
|
small alloc max size = 1024
|
||||||
|
|
||||||
|
# Memory limit for Lua runtime. If exceeded then only small allocations are allowed. Small allocations are always allowed, so e.g. Lua console can function.
|
||||||
|
# Default value is 2GB.
|
||||||
|
memory limit = 2147483648
|
||||||
|
|
||||||
|
# Print debug info about memory usage.
|
||||||
|
log memory usage = false
|
||||||
|
|
||||||
|
# The maximal number of Lua instructions per function call. If exceeded (e.g. because of an infinite loop) the function will be terminated.
|
||||||
|
instruction limit per call = 100000000
|
||||||
|
|
||||||
[Stereo]
|
[Stereo]
|
||||||
# Enable/disable stereo view. This setting is ignored in VR.
|
# Enable/disable stereo view. This setting is ignored in VR.
|
||||||
stereo enabled = false
|
stereo enabled = false
|
||||||
|
Loading…
x
Reference in New Issue
Block a user