Merge branch 'navigator_stats' into 'master'

Show stats for writing and reading navmesh db queue jobs

See merge request OpenMW/openmw!2346
crashfix_debugdraw
psi29a 2 years ago
commit 58d08d402a

@ -1,6 +1,7 @@
#include <benchmark/benchmark.h>
#include <components/detournavigator/navmeshtilescache.hpp>
#include <components/detournavigator/stats.hpp>
#include <components/esm3/loadland.hpp>
#include <algorithm>

@ -35,6 +35,7 @@
#include <components/detournavigator/navigator.hpp>
#include <components/detournavigator/settings.hpp>
#include <components/detournavigator/agentbounds.hpp>
#include <components/detournavigator/stats.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
@ -3992,7 +3993,7 @@ namespace MWWorld
void World::reportStats(unsigned int frameNumber, osg::Stats& stats) const
{
mNavigator->reportStats(frameNumber, stats);
DetourNavigator::reportStats(mNavigator->getStats(), frameNumber, stats);
mPhysics->reportStats(frameNumber, stats);
}

@ -316,6 +316,7 @@ add_component_dir(detournavigator
recast
gettilespositions
collisionshapetype
stats
)
add_component_dir(loadinglistener

@ -15,7 +15,6 @@
#include <DetourNavMesh.h>
#include <osg/Stats>
#include <osg/io_utils>
#include <algorithm>
@ -111,6 +110,11 @@ namespace DetourNavigator
static std::atomic_size_t nextJobId {1};
return nextJobId.fetch_add(1);
}
bool isWritingDbJob(const Job& job)
{
return job.mGeneratedNavMeshData != nullptr;
}
}
std::ostream& operator<<(std::ostream& stream, JobStatus value)
@ -302,9 +306,9 @@ namespace DetourNavigator
mProcessingTiles.wait(mProcessed, [] (const auto& v) { return v.empty(); });
}
AsyncNavMeshUpdater::Stats AsyncNavMeshUpdater::getStats() const
AsyncNavMeshUpdaterStats AsyncNavMeshUpdater::getStats() const
{
Stats result;
AsyncNavMeshUpdaterStats result;
{
const std::lock_guard<std::mutex> lock(mMutex);
result.mJobs = mJobs.size();
@ -319,25 +323,6 @@ namespace DetourNavigator
return result;
}
void reportStats(const AsyncNavMeshUpdater::Stats& stats, unsigned int frameNumber, osg::Stats& out)
{
out.setAttribute(frameNumber, "NavMesh Jobs", static_cast<double>(stats.mJobs));
out.setAttribute(frameNumber, "NavMesh Waiting", static_cast<double>(stats.mWaiting));
out.setAttribute(frameNumber, "NavMesh Pushed", static_cast<double>(stats.mPushed));
out.setAttribute(frameNumber, "NavMesh Processing", static_cast<double>(stats.mProcessing));
if (stats.mDb.has_value())
{
out.setAttribute(frameNumber, "NavMesh DbJobs", static_cast<double>(stats.mDb->mJobs));
if (stats.mDb->mGetTileCount > 0)
out.setAttribute(frameNumber, "NavMesh DbCacheHitRate", static_cast<double>(stats.mDbGetTileHits)
/ static_cast<double>(stats.mDb->mGetTileCount) * 100.0);
}
reportStats(stats.mCache, frameNumber, out);
}
void AsyncNavMeshUpdater::process() noexcept
{
Log(Debug::Debug) << "Start process navigator jobs by thread=" << std::this_thread::get_id();
@ -690,6 +675,10 @@ namespace DetourNavigator
{
const std::lock_guard lock(mMutex);
insertPrioritizedDbJob(job, mJobs);
if (isWritingDbJob(*job))
++mWritingJobs;
else
++mReadingJobs;
mHasJob.notify_all();
}
@ -701,6 +690,10 @@ namespace DetourNavigator
return std::nullopt;
const JobIt job = mJobs.front();
mJobs.pop_front();
if (isWritingDbJob(*job))
--mWritingJobs;
else
--mReadingJobs;
return job;
}
@ -719,10 +712,10 @@ namespace DetourNavigator
mHasJob.notify_all();
}
std::size_t DbJobQueue::size() const
DbJobQueueStats DbJobQueue::getStats() const
{
const std::lock_guard lock(mMutex);
return mJobs.size();
return DbJobQueueStats {.mWritingJobs = mWritingJobs, .mReadingJobs = mReadingJobs};
}
DbWorker::DbWorker(AsyncNavMeshUpdater& updater, std::unique_ptr<NavMeshDb>&& db,
@ -749,12 +742,12 @@ namespace DetourNavigator
mQueue.push(job);
}
DbWorker::Stats DbWorker::getStats() const
DbWorkerStats DbWorker::getStats() const
{
Stats result;
result.mJobs = mQueue.size();
result.mGetTileCount = mGetTileCount.load(std::memory_order_relaxed);
return result;
return DbWorkerStats {
.mJobs = mQueue.getStats(),
.mGetTileCount = mGetTileCount.load(std::memory_order_relaxed)
};
}
void DbWorker::stop()
@ -809,7 +802,7 @@ namespace DetourNavigator
}
};
if (job->mGeneratedNavMeshData != nullptr)
if (isWritingDbJob(*job))
{
process([&] (JobIt job) { processWritingJob(job); });
mUpdater.removeJob(job);

@ -12,6 +12,7 @@
#include "agentbounds.hpp"
#include "guardednavmeshcacheitem.hpp"
#include "sharednavmeshcacheitem.hpp"
#include "stats.hpp"
#include <osg/Vec3f>
@ -88,13 +89,15 @@ namespace DetourNavigator
void stop();
std::size_t size() const;
DbJobQueueStats getStats() const;
private:
mutable std::mutex mMutex;
std::condition_variable mHasJob;
std::deque<JobIt> mJobs;
bool mShouldStop = false;
std::size_t mWritingJobs = 0;
std::size_t mReadingJobs = 0;
};
class AsyncNavMeshUpdater;
@ -102,18 +105,12 @@ namespace DetourNavigator
class DbWorker
{
public:
struct Stats
{
std::size_t mJobs = 0;
std::size_t mGetTileCount = 0;
};
DbWorker(AsyncNavMeshUpdater& updater, std::unique_ptr<NavMeshDb>&& db,
TileVersion version, const RecastSettings& recastSettings, bool writeToDb);
~DbWorker();
Stats getStats() const;
DbWorkerStats getStats() const;
void enqueueJob(JobIt job);
@ -146,17 +143,6 @@ namespace DetourNavigator
class AsyncNavMeshUpdater
{
public:
struct Stats
{
std::size_t mJobs = 0;
std::size_t mWaiting = 0;
std::size_t mPushed = 0;
std::size_t mProcessing = 0;
std::size_t mDbGetTileHits = 0;
std::optional<DbWorker::Stats> mDb;
NavMeshTilesCache::Stats mCache;
};
AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager,
OffMeshConnectionsManager& offMeshConnectionsManager, std::unique_ptr<NavMeshDb>&& db);
~AsyncNavMeshUpdater();
@ -169,7 +155,7 @@ namespace DetourNavigator
void stop();
Stats getStats() const;
AsyncNavMeshUpdaterStats getStats() const;
void enqueueJob(JobIt job);
@ -227,8 +213,6 @@ namespace DetourNavigator
inline void waitUntilAllJobsDone();
};
void reportStats(const AsyncNavMeshUpdater::Stats& stats, unsigned int frameNumber, osg::Stats& out);
}
#endif

@ -23,15 +23,11 @@ namespace Loading
class Listener;
}
namespace osg
{
class Stats;
}
namespace DetourNavigator
{
struct Settings;
struct AgentBounds;
struct Stats;
struct ObjectShapes
{
@ -181,7 +177,7 @@ namespace DetourNavigator
virtual const Settings& getSettings() const = 0;
virtual void reportStats(unsigned int frameNumber, osg::Stats& stats) const = 0;
virtual Stats getStats() const = 0;
virtual RecastMeshTiles getRecastMeshTiles() const = 0;

@ -1,5 +1,6 @@
#include "navigatorimpl.hpp"
#include "settingsutils.hpp"
#include "stats.hpp"
#include <components/debug/debuglog.hpp>
#include <components/esm3/loadpgrd.hpp>
@ -173,9 +174,9 @@ namespace DetourNavigator
return mSettings;
}
void NavigatorImpl::reportStats(unsigned int frameNumber, osg::Stats& stats) const
Stats NavigatorImpl::getStats() const
{
mNavMeshManager.reportStats(frameNumber, stats);
return mNavMeshManager.getStats();
}
RecastMeshTiles NavigatorImpl::getRecastMeshTiles() const

@ -58,7 +58,7 @@ namespace DetourNavigator
const Settings& getSettings() const override;
void reportStats(unsigned int frameNumber, osg::Stats& stats) const override;
Stats getStats() const override;
RecastMeshTiles getRecastMeshTiles() const override;

@ -3,6 +3,7 @@
#include "navigator.hpp"
#include "settings.hpp"
#include "stats.hpp"
namespace Loading
{
@ -66,7 +67,7 @@ namespace DetourNavigator
return mDefaultSettings;
}
void reportStats(unsigned int /*frameNumber*/, osg::Stats& /*stats*/) const override {}
Stats getStats() const override { return Stats {}; }
RecastMeshTiles getRecastMeshTiles() const override
{

@ -268,9 +268,9 @@ namespace DetourNavigator
return mCache;
}
void NavMeshManager::reportStats(unsigned int frameNumber, osg::Stats& stats) const
Stats NavMeshManager::getStats() const
{
DetourNavigator::reportStats(mAsyncNavMeshUpdater.getStats(), frameNumber, stats);
return Stats {.mUpdater = mAsyncNavMeshUpdater.getStats()};
}
RecastMeshTiles NavMeshManager::getRecastMeshTiles() const

@ -58,7 +58,7 @@ namespace DetourNavigator
std::map<AgentBounds, SharedNavMeshCacheItem> getNavMeshes() const;
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
Stats getStats() const;
RecastMeshTiles getRecastMeshTiles() const;

@ -1,6 +1,5 @@
#include "navmeshtilescache.hpp"
#include <osg/Stats>
#include "stats.hpp"
#include <cstring>
@ -65,9 +64,9 @@ namespace DetourNavigator
return Value(*this, iterator);
}
NavMeshTilesCache::Stats NavMeshTilesCache::getStats() const
NavMeshTilesCacheStats NavMeshTilesCache::getStats() const
{
Stats result;
NavMeshTilesCacheStats result;
{
const std::lock_guard<std::mutex> lock(mMutex);
result.mNavMeshCacheSize = mUsedNavMeshDataSize;
@ -79,15 +78,6 @@ namespace DetourNavigator
return result;
}
void reportStats(const NavMeshTilesCache::Stats& stats, unsigned int frameNumber, osg::Stats& out)
{
out.setAttribute(frameNumber, "NavMesh CacheSize", static_cast<double>(stats.mNavMeshCacheSize));
out.setAttribute(frameNumber, "NavMesh UsedTiles", static_cast<double>(stats.mUsedNavMeshTiles));
out.setAttribute(frameNumber, "NavMesh CachedTiles", static_cast<double>(stats.mCachedNavMeshTiles));
if (stats.mGetCount > 0)
out.setAttribute(frameNumber, "NavMesh CacheHitRate", static_cast<double>(stats.mHitCount) / stats.mGetCount * 100.0);
}
void NavMeshTilesCache::removeLeastRecentlyUsed()
{
const auto& item = mFreeItems.back();

@ -14,11 +14,6 @@
#include <cstring>
#include <vector>
namespace osg
{
class Stats;
}
namespace DetourNavigator
{
struct RecastMeshData
@ -47,6 +42,8 @@ namespace DetourNavigator
< std::tie(rhs.mMesh, rhs.mWater, rhs.mHeightfields, rhs.mFlatHeightfields);
}
struct NavMeshTilesCacheStats;
class NavMeshTilesCache
{
public:
@ -126,15 +123,6 @@ namespace DetourNavigator
ItemIterator mIterator;
};
struct Stats
{
std::size_t mNavMeshCacheSize;
std::size_t mUsedNavMeshTiles;
std::size_t mCachedNavMeshTiles;
std::size_t mHitCount;
std::size_t mGetCount;
};
NavMeshTilesCache(const std::size_t maxNavMeshDataSize);
Value get(const AgentBounds& agentBounds, const TilePosition& changedTile,
@ -143,7 +131,7 @@ namespace DetourNavigator
Value set(const AgentBounds& agentBounds, const TilePosition& changedTile,
const RecastMesh& recastMesh, std::unique_ptr<PreparedNavMeshData>&& value);
Stats getStats() const;
NavMeshTilesCacheStats getStats() const;
private:
mutable std::mutex mMutex;
@ -162,8 +150,6 @@ namespace DetourNavigator
void releaseItem(ItemIterator iterator);
};
void reportStats(const NavMeshTilesCache::Stats& stats, unsigned int frameNumber, osg::Stats& out);
}
#endif

@ -0,0 +1,40 @@
#include "stats.hpp"
#include <osg/Stats>
namespace DetourNavigator
{
namespace
{
void reportStats(const AsyncNavMeshUpdaterStats& stats, unsigned int frameNumber, osg::Stats& out)
{
out.setAttribute(frameNumber, "NavMesh Jobs", static_cast<double>(stats.mJobs));
out.setAttribute(frameNumber, "NavMesh Waiting", static_cast<double>(stats.mWaiting));
out.setAttribute(frameNumber, "NavMesh Pushed", static_cast<double>(stats.mPushed));
out.setAttribute(frameNumber, "NavMesh Processing", static_cast<double>(stats.mProcessing));
if (stats.mDb.has_value())
{
out.setAttribute(frameNumber, "NavMesh DbJobs Write", static_cast<double>(stats.mDb->mJobs.mWritingJobs));
out.setAttribute(frameNumber, "NavMesh DbJobs Read", static_cast<double>(stats.mDb->mJobs.mReadingJobs));
if (stats.mDb->mGetTileCount > 0)
out.setAttribute(frameNumber, "NavMesh DbCacheHitRate", static_cast<double>(stats.mDbGetTileHits)
/ static_cast<double>(stats.mDb->mGetTileCount) * 100.0);
}
out.setAttribute(frameNumber, "NavMesh CacheSize", static_cast<double>(stats.mCache.mNavMeshCacheSize));
out.setAttribute(frameNumber, "NavMesh UsedTiles", static_cast<double>(stats.mCache.mUsedNavMeshTiles));
out.setAttribute(frameNumber, "NavMesh CachedTiles", static_cast<double>(stats.mCache.mCachedNavMeshTiles));
if (stats.mCache.mGetCount > 0)
out.setAttribute(frameNumber, "NavMesh CacheHitRate", static_cast<double>(stats.mCache.mHitCount)
/ stats.mCache.mGetCount * 100.0);
}
}
void reportStats(const Stats& stats, unsigned int frameNumber, osg::Stats& out)
{
if (stats.mUpdater.has_value())
reportStats(*stats.mUpdater, frameNumber, out);
}
}

@ -0,0 +1,54 @@
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_STATS_H
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_STATS_H
#include <cstddef>
#include <optional>
namespace osg
{
class Stats;
}
namespace DetourNavigator
{
struct DbJobQueueStats
{
std::size_t mWritingJobs = 0;
std::size_t mReadingJobs = 0;
};
struct DbWorkerStats
{
DbJobQueueStats mJobs;
std::size_t mGetTileCount = 0;
};
struct NavMeshTilesCacheStats
{
std::size_t mNavMeshCacheSize = 0;
std::size_t mUsedNavMeshTiles = 0;
std::size_t mCachedNavMeshTiles = 0;
std::size_t mHitCount = 0;
std::size_t mGetCount = 0;
};
struct AsyncNavMeshUpdaterStats
{
std::size_t mJobs = 0;
std::size_t mWaiting = 0;
std::size_t mPushed = 0;
std::size_t mProcessing = 0;
std::size_t mDbGetTileHits = 0;
std::optional<DbWorkerStats> mDb;
NavMeshTilesCacheStats mCache;
};
struct Stats
{
std::optional<AsyncNavMeshUpdaterStats> mUpdater;
};
void reportStats(const Stats& stats, unsigned int frameNumber, osg::Stats& out);
}
#endif

@ -439,7 +439,8 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer)
"NavMesh Waiting",
"NavMesh Pushed",
"NavMesh Processing",
"NavMesh DbJobs",
"NavMesh DbJobs Write",
"NavMesh DbJobs Read",
"NavMesh DbCacheHitRate",
"NavMesh CacheSize",
"NavMesh UsedTiles",

Loading…
Cancel
Save