mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 03:29:55 +00:00
Lua Profiler
This commit is contained in:
parent
6fa65e4729
commit
02a9069a0e
14 changed files with 216 additions and 9 deletions
|
@ -100,6 +100,8 @@ namespace MWBase
|
|||
virtual void handleConsoleCommand(
|
||||
const std::string& consoleMode, const std::string& command, const MWWorld::Ptr& selectedPtr)
|
||||
= 0;
|
||||
|
||||
virtual std::string formatResourceUsageStats() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ namespace MWBase
|
|||
virtual void updateSpellWindow() = 0;
|
||||
|
||||
virtual void setConsoleSelectedObject(const MWWorld::Ptr& object) = 0;
|
||||
virtual MWWorld::Ptr getConsoleSelectedObject() const = 0;
|
||||
virtual void setConsoleMode(const std::string& mode) = 0;
|
||||
|
||||
static constexpr std::string_view sConsoleColor_Default = "#FFFFFF";
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace MWGui
|
|||
public:
|
||||
/// Set the implicit object for script execution
|
||||
void setSelectedObject(const MWWorld::Ptr& object);
|
||||
MWWorld::Ptr getSelectedObject() const { return mPtr; }
|
||||
|
||||
MyGUI::EditBox* mCommandLine;
|
||||
MyGUI::EditBox* mHistory;
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#include <components/debug/debugging.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#ifndef BT_NO_PROFILE
|
||||
|
@ -106,6 +109,12 @@ namespace MWGui
|
|||
= itemLV->createWidgetReal<MyGUI::EditBox>("LogEdit", MyGUI::FloatCoord(0, 0, 1, 1), MyGUI::Align::Stretch);
|
||||
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
|
||||
MyGUI::TabItem* item = mTabControl->addItem("Physics Profiler");
|
||||
item->setCaptionWithReplacing(" #{DebugMenu:PhysicsProfiler} ");
|
||||
|
@ -206,6 +215,16 @@ namespace MWGui
|
|||
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()
|
||||
{
|
||||
#ifndef BT_NO_PROFILE
|
||||
|
@ -229,9 +248,18 @@ namespace MWGui
|
|||
return;
|
||||
timer = 0.25;
|
||||
|
||||
if (mTabControl->getIndexSelected() == 0)
|
||||
updateLogView();
|
||||
else
|
||||
updateBulletProfile();
|
||||
switch (mTabControl->getIndexSelected())
|
||||
{
|
||||
case 0:
|
||||
updateLogView();
|
||||
break;
|
||||
case 1:
|
||||
updateLuaProfile();
|
||||
break;
|
||||
case 2:
|
||||
updateBulletProfile();
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,12 @@ namespace MWGui
|
|||
|
||||
private:
|
||||
void updateLogView();
|
||||
void updateLuaProfile();
|
||||
void updateBulletProfile();
|
||||
|
||||
MyGUI::TabControl* mTabControl;
|
||||
MyGUI::EditBox* mLogView;
|
||||
MyGUI::EditBox* mLuaProfiler;
|
||||
MyGUI::EditBox* mBulletProfilerEdit;
|
||||
};
|
||||
|
||||
|
|
|
@ -2158,6 +2158,11 @@ namespace MWGui
|
|||
mConsole->setSelectedObject(object);
|
||||
}
|
||||
|
||||
MWWorld::Ptr WindowManager::getConsoleSelectedObject() const
|
||||
{
|
||||
return mConsole->getSelectedObject();
|
||||
}
|
||||
|
||||
void WindowManager::printToConsole(const std::string& msg, std::string_view color)
|
||||
{
|
||||
mConsole->print(msg, color);
|
||||
|
|
|
@ -188,6 +188,7 @@ namespace MWGui
|
|||
void updateSpellWindow() 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 setConsoleMode(const std::string& mode) override;
|
||||
|
||||
|
|
|
@ -37,8 +37,16 @@
|
|||
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)
|
||||
: mLua(vfs, &mConfiguration)
|
||||
: mLua(vfs, &mConfiguration, createLuaStateSettings())
|
||||
, mUiResourceManager(vfs)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
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", state.memory_used());
|
||||
stats.setAttribute(frameNumber, "Lua UsedMemory", mLua.getTotalMemoryUsage());
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats& stats);
|
||||
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||
std::string formatResourceUsageStats() const override;
|
||||
|
||||
private:
|
||||
void initConfiguration();
|
||||
|
|
|
@ -26,3 +26,64 @@ If one, a separate thread is used.
|
|||
Values >1 are not yet supported.
|
||||
|
||||
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"
|
||||
LogViewer: "Protokollansicht"
|
||||
LuaProfiler: "Lua-Profiler"
|
||||
PhysicsProfiler: "Physik-Profiler"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
DebugWindow: "Debug"
|
||||
LogViewer: "Log Viewer"
|
||||
LuaProfiler: "Lua Profiler"
|
||||
PhysicsProfiler: "Physics Profiler"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
DebugWindow: "Меню отладки"
|
||||
LogViewer: "Журнал логов"
|
||||
LuaProfiler: "Профилировщик Луа"
|
||||
PhysicsProfiler: "Профилировщик физики"
|
||||
|
|
|
@ -1141,6 +1141,19 @@ lua debug = false
|
|||
# If zero, Lua scripts are processed in the main thread.
|
||||
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]
|
||||
# Enable/disable stereo view. This setting is ignored in VR.
|
||||
stereo enabled = false
|
||||
|
|
Loading…
Reference in a new issue