mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 16:29:55 +00:00
Report more stats from caches
This commit is contained in:
parent
ae41ebfc83
commit
215404e126
19 changed files with 267 additions and 108 deletions
|
@ -463,6 +463,6 @@ namespace MWRender
|
||||||
|
|
||||||
void Groundcover::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void Groundcover::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Groundcover Chunk", mCache->getCacheSize());
|
Resource::reportStats("Groundcover Chunk", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include "landmanager.hpp"
|
#include "landmanager.hpp"
|
||||||
|
|
||||||
#include <osg/Stats>
|
|
||||||
|
|
||||||
#include <components/esm4/loadwrld.hpp>
|
#include <components/esm4/loadwrld.hpp>
|
||||||
#include <components/resource/objectcache.hpp>
|
#include <components/resource/objectcache.hpp>
|
||||||
#include <components/settings/values.hpp>
|
#include <components/settings/values.hpp>
|
||||||
|
@ -53,7 +51,7 @@ namespace MWRender
|
||||||
|
|
||||||
void LandManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void LandManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Land", mCache->getCacheSize());
|
Resource::reportStats("Land", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1013,7 +1013,7 @@ namespace MWRender
|
||||||
|
|
||||||
void ObjectPaging::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void ObjectPaging::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Object Chunk", mCache->getCacheSize());
|
Resource::reportStats("Object Chunk", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,9 +114,11 @@ namespace Resource
|
||||||
|
|
||||||
cache->update(referenceTime, expiryDelay);
|
cache->update(referenceTime, expiryDelay);
|
||||||
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
ASSERT_THAT(cache->getRefFromObjectCacheOrNone(key), Optional(_));
|
||||||
|
ASSERT_EQ(cache->getStats().mExpired, 0);
|
||||||
|
|
||||||
cache->update(referenceTime + expiryDelay, expiryDelay);
|
cache->update(referenceTime + expiryDelay, expiryDelay);
|
||||||
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt);
|
EXPECT_EQ(cache->getRefFromObjectCacheOrNone(key), std::nullopt);
|
||||||
|
ASSERT_EQ(cache->getStats().mExpired, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ResourceGenericObjectCacheTest, updateShouldKeepExternallyReferencedItems)
|
TEST(ResourceGenericObjectCacheTest, updateShouldKeepExternallyReferencedItems)
|
||||||
|
@ -249,7 +251,7 @@ namespace Resource
|
||||||
EXPECT_THAT(actual, ElementsAre(Pair(1, value1.get()), Pair(2, value2.get()), Pair(3, value3.get())));
|
EXPECT_THAT(actual, ElementsAre(Pair(1, value1.get()), Pair(2, value2.get()), Pair(3, value3.get())));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ResourceGenericObjectCacheTest, getCacheSizeShouldReturnNumberOrAddedItems)
|
TEST(ResourceGenericObjectCacheTest, getStatsShouldReturnNumberOrAddedItems)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
@ -258,7 +260,33 @@ namespace Resource
|
||||||
cache->addEntryToObjectCache(13, value1);
|
cache->addEntryToObjectCache(13, value1);
|
||||||
cache->addEntryToObjectCache(42, value2);
|
cache->addEntryToObjectCache(42, value2);
|
||||||
|
|
||||||
EXPECT_EQ(cache->getCacheSize(), 2);
|
const CacheStats stats = cache->getStats();
|
||||||
|
|
||||||
|
EXPECT_EQ(stats.mSize, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ResourceGenericObjectCacheTest, getStatsShouldReturnNumberOrGetsAndHits)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<GenericObjectCache<int>> cache(new GenericObjectCache<int>);
|
||||||
|
|
||||||
|
{
|
||||||
|
const CacheStats stats = cache->getStats();
|
||||||
|
|
||||||
|
EXPECT_EQ(stats.mGet, 0);
|
||||||
|
EXPECT_EQ(stats.mHit, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<Object> value(new Object);
|
||||||
|
cache->addEntryToObjectCache(13, value);
|
||||||
|
cache->getRefFromObjectCache(13);
|
||||||
|
cache->getRefFromObjectCache(42);
|
||||||
|
|
||||||
|
{
|
||||||
|
const CacheStats stats = cache->getStats();
|
||||||
|
|
||||||
|
EXPECT_EQ(stats.mGet, 2);
|
||||||
|
EXPECT_EQ(stats.mHit, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ResourceGenericObjectCacheTest, lowerBoundShouldReturnFirstNotLessThatGivenKey)
|
TEST(ResourceGenericObjectCacheTest, lowerBoundShouldReturnFirstNotLessThatGivenKey)
|
||||||
|
|
|
@ -125,7 +125,7 @@ add_component_dir (vfs
|
||||||
|
|
||||||
add_component_dir (resource
|
add_component_dir (resource
|
||||||
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem
|
scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem
|
||||||
resourcemanager stats animation foreachbulletobject errormarker
|
resourcemanager stats animation foreachbulletobject errormarker cachestats
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (shader
|
add_component_dir (shader
|
||||||
|
|
|
@ -213,8 +213,8 @@ namespace Resource
|
||||||
|
|
||||||
void BulletShapeManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void BulletShapeManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Shape", mCache->getCacheSize());
|
Resource::reportStats("Shape", frameNumber, mCache->getStats(), *stats);
|
||||||
stats->setAttribute(frameNumber, "Shape Instance", mInstanceCache->getCacheSize());
|
Resource::reportStats("Shape Instance", frameNumber, mInstanceCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
40
components/resource/cachestats.cpp
Normal file
40
components/resource/cachestats.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include "cachestats.hpp"
|
||||||
|
|
||||||
|
#include <osg/Stats>
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::string makeAttribute(std::string_view prefix, std::string_view suffix)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
result.reserve(prefix.size() + 1 + suffix.size());
|
||||||
|
result += prefix;
|
||||||
|
result += ' ';
|
||||||
|
result += suffix;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCacheStatsAttibutes(std::string_view prefix, std::vector<std::string>& out)
|
||||||
|
{
|
||||||
|
constexpr std::string_view suffixes[] = {
|
||||||
|
"Count",
|
||||||
|
"Get",
|
||||||
|
"Hit",
|
||||||
|
"Expired",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (std::string_view suffix : suffixes)
|
||||||
|
out.push_back(makeAttribute(prefix, suffix));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reportStats(std::string_view prefix, unsigned frameNumber, const CacheStats& src, osg::Stats& dst)
|
||||||
|
{
|
||||||
|
dst.setAttribute(frameNumber, makeAttribute(prefix, "Count"), static_cast<double>(src.mSize));
|
||||||
|
dst.setAttribute(frameNumber, makeAttribute(prefix, "Get"), static_cast<double>(src.mGet));
|
||||||
|
dst.setAttribute(frameNumber, makeAttribute(prefix, "Hit"), static_cast<double>(src.mHit));
|
||||||
|
dst.setAttribute(frameNumber, makeAttribute(prefix, "Expired"), static_cast<double>(src.mExpired));
|
||||||
|
}
|
||||||
|
}
|
28
components/resource/cachestats.hpp
Normal file
28
components/resource/cachestats.hpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_RESOURCE_CACHESATS
|
||||||
|
#define OPENMW_COMPONENTS_RESOURCE_CACHESATS
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
struct CacheStats
|
||||||
|
{
|
||||||
|
std::size_t mSize = 0;
|
||||||
|
std::size_t mGet = 0;
|
||||||
|
std::size_t mHit = 0;
|
||||||
|
std::size_t mExpired = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void addCacheStatsAttibutes(std::string_view prefix, std::vector<std::string>& out);
|
||||||
|
|
||||||
|
void reportStats(std::string_view prefix, unsigned frameNumber, const CacheStats& src, osg::Stats& dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -202,7 +202,7 @@ namespace Resource
|
||||||
|
|
||||||
void ImageManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void ImageManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Image", mCache->getCacheSize());
|
Resource::reportStats("Image", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
#include <osg/Stats>
|
|
||||||
#include <osgAnimation/Animation>
|
#include <osgAnimation/Animation>
|
||||||
#include <osgAnimation/BasicAnimationManager>
|
#include <osgAnimation/BasicAnimationManager>
|
||||||
#include <osgAnimation/Channel>
|
#include <osgAnimation/Channel>
|
||||||
|
@ -250,7 +249,7 @@ namespace Resource
|
||||||
|
|
||||||
void KeyframeManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void KeyframeManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Keyframe", mCache->getCacheSize());
|
Resource::reportStats("Keyframe", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace Resource
|
||||||
{
|
{
|
||||||
objectsToRemove.push_back(oitr->second);
|
objectsToRemove.push_back(oitr->second);
|
||||||
_objectCache.erase(oitr++);
|
_objectCache.erase(oitr++);
|
||||||
|
++mExpired;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -57,13 +58,15 @@ namespace Resource
|
||||||
osg::ref_ptr<osg::Object> MultiObjectCache::takeFromObjectCache(const std::string& fileName)
|
osg::ref_ptr<osg::Object> MultiObjectCache::takeFromObjectCache(const std::string& fileName)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
||||||
|
++mGet;
|
||||||
ObjectCacheMap::iterator found = _objectCache.find(fileName);
|
ObjectCacheMap::iterator found = _objectCache.find(fileName);
|
||||||
if (found == _objectCache.end())
|
if (found == _objectCache.end())
|
||||||
return osg::ref_ptr<osg::Object>();
|
return osg::ref_ptr<osg::Object>();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Object> object = found->second;
|
osg::ref_ptr<osg::Object> object = std::move(found->second);
|
||||||
_objectCache.erase(found);
|
_objectCache.erase(found);
|
||||||
|
++mHit;
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,10 +82,15 @@ namespace Resource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int MultiObjectCache::getCacheSize() const
|
CacheStats MultiObjectCache::getStats() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
std::lock_guard<std::mutex> lock(_objectCacheMutex);
|
||||||
return _objectCache.size();
|
return CacheStats{
|
||||||
|
.mSize = _objectCache.size(),
|
||||||
|
.mGet = mGet,
|
||||||
|
.mHit = mHit,
|
||||||
|
.mExpired = mExpired,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <osg/Referenced>
|
#include <osg/Referenced>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include "cachestats.hpp"
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Object;
|
class Object;
|
||||||
|
@ -37,13 +39,16 @@ namespace Resource
|
||||||
/** call releaseGLObjects on all objects attached to the object cache.*/
|
/** call releaseGLObjects on all objects attached to the object cache.*/
|
||||||
void releaseGLObjects(osg::State* state);
|
void releaseGLObjects(osg::State* state);
|
||||||
|
|
||||||
unsigned int getCacheSize() const;
|
CacheStats getStats() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef std::multimap<std::string, osg::ref_ptr<osg::Object>> ObjectCacheMap;
|
typedef std::multimap<std::string, osg::ref_ptr<osg::Object>> ObjectCacheMap;
|
||||||
|
|
||||||
ObjectCacheMap _objectCache;
|
ObjectCacheMap _objectCache;
|
||||||
mutable std::mutex _objectCacheMutex;
|
mutable std::mutex _objectCacheMutex;
|
||||||
|
std::size_t mGet = 0;
|
||||||
|
std::size_t mHit = 0;
|
||||||
|
std::size_t mExpired = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <osg/Object>
|
#include <osg/Object>
|
||||||
#include <osg/Stats>
|
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
|
@ -59,7 +58,7 @@ namespace Resource
|
||||||
|
|
||||||
void NifFileManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void NifFileManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Nif", mCache->getCacheSize());
|
Resource::reportStats("Nif", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#ifndef OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE
|
#ifndef OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE
|
||||||
#define OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE
|
#define OPENMW_COMPONENTS_RESOURCE_OBJECTCACHE
|
||||||
|
|
||||||
|
#include "cachestats.hpp"
|
||||||
|
|
||||||
#include <osg/Node>
|
#include <osg/Node>
|
||||||
#include <osg/Referenced>
|
#include <osg/Referenced>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
@ -29,26 +31,28 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace osg
|
namespace osg
|
||||||
{
|
{
|
||||||
class Object;
|
class Object;
|
||||||
class State;
|
class State;
|
||||||
class NodeVisitor;
|
class NodeVisitor;
|
||||||
|
class Stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
|
struct GenericObjectCacheItem
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Object> mValue;
|
||||||
|
double mLastUsage;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename KeyType>
|
template <typename KeyType>
|
||||||
class GenericObjectCache : public osg::Referenced
|
class GenericObjectCache : public osg::Referenced
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GenericObjectCache()
|
|
||||||
: osg::Referenced(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update last usage timestamp using referenceTime for each cache time if they are not nullptr and referenced
|
// Update last usage timestamp using referenceTime for each cache time if they are not nullptr and referenced
|
||||||
// from somewhere else. Remove items with last usage > expiryTime. Note: last usage might be updated from other
|
// from somewhere else. Remove items with last usage > expiryTime. Note: last usage might be updated from other
|
||||||
// places so nullptr or not references elsewhere items are not always removed.
|
// places so nullptr or not references elsewhere items are not always removed.
|
||||||
|
@ -64,6 +68,7 @@ namespace Resource
|
||||||
item.mLastUsage = referenceTime;
|
item.mLastUsage = referenceTime;
|
||||||
if (item.mLastUsage > expiryTime)
|
if (item.mLastUsage > expiryTime)
|
||||||
return false;
|
return false;
|
||||||
|
++mExpired;
|
||||||
if (item.mValue != nullptr)
|
if (item.mValue != nullptr)
|
||||||
objectsToRemove.push_back(std::move(item.mValue));
|
objectsToRemove.push_back(std::move(item.mValue));
|
||||||
return true;
|
return true;
|
||||||
|
@ -105,33 +110,28 @@ namespace Resource
|
||||||
osg::ref_ptr<osg::Object> getRefFromObjectCache(const auto& key)
|
osg::ref_ptr<osg::Object> getRefFromObjectCache(const auto& key)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
const auto itr = mItems.find(key);
|
if (Item* const item = find(key))
|
||||||
if (itr != mItems.end())
|
return item->mValue;
|
||||||
return itr->second.mValue;
|
|
||||||
else
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<osg::ref_ptr<osg::Object>> getRefFromObjectCacheOrNone(const auto& key)
|
std::optional<osg::ref_ptr<osg::Object>> getRefFromObjectCacheOrNone(const auto& key)
|
||||||
{
|
{
|
||||||
const std::lock_guard<std::mutex> lock(mMutex);
|
const std::lock_guard<std::mutex> lock(mMutex);
|
||||||
const auto it = mItems.find(key);
|
if (Item* const item = find(key))
|
||||||
if (it == mItems.end())
|
return item->mValue;
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
return it->second.mValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check if an object is in the cache, and if it is, update its usage time stamp. */
|
/** Check if an object is in the cache, and if it is, update its usage time stamp. */
|
||||||
bool checkInObjectCache(const auto& key, double timeStamp)
|
bool checkInObjectCache(const auto& key, double timeStamp)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
const auto itr = mItems.find(key);
|
if (Item* const item = find(key))
|
||||||
if (itr != mItems.end())
|
|
||||||
{
|
{
|
||||||
itr->second.mLastUsage = timeStamp;
|
item->mLastUsage = timeStamp;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,13 +162,6 @@ namespace Resource
|
||||||
f(k, v.mValue.get());
|
f(k, v.mValue.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the number of objects in the cache. */
|
|
||||||
unsigned int getCacheSize() const
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
|
||||||
return mItems.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class K>
|
template <class K>
|
||||||
std::optional<std::pair<KeyType, osg::ref_ptr<osg::Object>>> lowerBound(K&& key)
|
std::optional<std::pair<KeyType, osg::ref_ptr<osg::Object>>> lowerBound(K&& key)
|
||||||
{
|
{
|
||||||
|
@ -179,21 +172,36 @@ namespace Resource
|
||||||
return std::pair(it->first, it->second.mValue);
|
return std::pair(it->first, it->second.mValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
CacheStats getStats() const
|
||||||
struct Item
|
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Object> mValue;
|
const std::lock_guard<std::mutex> lock(mMutex);
|
||||||
double mLastUsage;
|
return CacheStats{
|
||||||
|
.mSize = mItems.size(),
|
||||||
|
.mGet = mGet,
|
||||||
|
.mHit = mHit,
|
||||||
|
.mExpired = mExpired,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using Item = GenericObjectCacheItem;
|
||||||
|
|
||||||
std::map<KeyType, Item, std::less<>> mItems;
|
std::map<KeyType, Item, std::less<>> mItems;
|
||||||
mutable std::mutex mMutex;
|
mutable std::mutex mMutex;
|
||||||
};
|
std::size_t mGet = 0;
|
||||||
|
std::size_t mHit = 0;
|
||||||
|
std::size_t mExpired = 0;
|
||||||
|
|
||||||
class ObjectCache : public GenericObjectCache<std::string>
|
Item* find(const auto& key)
|
||||||
{
|
{
|
||||||
|
++mGet;
|
||||||
|
const auto it = mItems.find(key);
|
||||||
|
if (it == mItems.end())
|
||||||
|
return nullptr;
|
||||||
|
++mHit;
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1125,7 +1125,7 @@ namespace Resource
|
||||||
stats->setAttribute(frameNumber, "StateSet", mSharedStateManager->getNumSharedStateSets());
|
stats->setAttribute(frameNumber, "StateSet", mSharedStateManager->getNumSharedStateSets());
|
||||||
}
|
}
|
||||||
|
|
||||||
stats->setAttribute(frameNumber, "Node", mCache->getCacheSize());
|
Resource::reportStats("Node", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<Shader::ShaderVisitor> SceneManager::createShaderVisitor(const std::string& shaderPrefix)
|
osg::ref_ptr<Shader::ShaderVisitor> SceneManager::createShaderVisitor(const std::string& shaderPrefix)
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
|
|
||||||
|
#include "cachestats.hpp"
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
|
@ -45,14 +47,36 @@ namespace Resource
|
||||||
bool collectStatUpdate = false;
|
bool collectStatUpdate = false;
|
||||||
bool collectStatEngine = false;
|
bool collectStatEngine = false;
|
||||||
|
|
||||||
const std::vector<std::string> allStatNames = {
|
std::vector<std::string> generateAllStatNames()
|
||||||
|
{
|
||||||
|
constexpr std::string_view firstPage[] = {
|
||||||
"FrameNumber",
|
"FrameNumber",
|
||||||
|
"",
|
||||||
"Compiling",
|
"Compiling",
|
||||||
"WorkQueue",
|
"WorkQueue",
|
||||||
"WorkThread",
|
"WorkThread",
|
||||||
"UnrefQueue",
|
"UnrefQueue",
|
||||||
|
"",
|
||||||
"Texture",
|
"Texture",
|
||||||
"StateSet",
|
"StateSet",
|
||||||
|
"Composite",
|
||||||
|
"",
|
||||||
|
"Mechanics Actors",
|
||||||
|
"Mechanics Objects",
|
||||||
|
"",
|
||||||
|
"Physics Actors",
|
||||||
|
"Physics Objects",
|
||||||
|
"Physics Projectiles",
|
||||||
|
"Physics HeightFields",
|
||||||
|
"",
|
||||||
|
"Lua UsedMemory",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::string_view caches[] = {
|
||||||
"Node",
|
"Node",
|
||||||
"Shape",
|
"Shape",
|
||||||
"Shape Instance",
|
"Shape Instance",
|
||||||
|
@ -64,19 +88,17 @@ namespace Resource
|
||||||
"Terrain Chunk",
|
"Terrain Chunk",
|
||||||
"Terrain Texture",
|
"Terrain Texture",
|
||||||
"Land",
|
"Land",
|
||||||
"Composite",
|
};
|
||||||
"Mechanics Actors",
|
|
||||||
"Mechanics Objects",
|
constexpr std::string_view cellPreloader[] = {
|
||||||
"Physics Actors",
|
|
||||||
"Physics Objects",
|
|
||||||
"Physics Projectiles",
|
|
||||||
"Physics HeightFields",
|
|
||||||
"Lua UsedMemory",
|
|
||||||
"CellPreloader Count",
|
"CellPreloader Count",
|
||||||
"CellPreloader Added",
|
"CellPreloader Added",
|
||||||
"CellPreloader Evicted",
|
"CellPreloader Evicted",
|
||||||
"CellPreloader Loaded",
|
"CellPreloader Loaded",
|
||||||
"CellPreloader Expired",
|
"CellPreloader Expired",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::string_view navMesh[] = {
|
||||||
"NavMesh Jobs",
|
"NavMesh Jobs",
|
||||||
"NavMesh Waiting",
|
"NavMesh Waiting",
|
||||||
"NavMesh Pushed",
|
"NavMesh Pushed",
|
||||||
|
@ -92,6 +114,29 @@ namespace Resource
|
||||||
"NavMesh Cache Hit",
|
"NavMesh Cache Hit",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::vector<std::string> statNames;
|
||||||
|
|
||||||
|
for (std::string_view name : firstPage)
|
||||||
|
statNames.emplace_back(name);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < std::size(caches); ++i)
|
||||||
|
{
|
||||||
|
Resource::addCacheStatsAttibutes(caches[i], statNames);
|
||||||
|
if ((i + 1) % 5 != 0)
|
||||||
|
statNames.emplace_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::string_view name : cellPreloader)
|
||||||
|
statNames.emplace_back(name);
|
||||||
|
|
||||||
|
statNames.emplace_back();
|
||||||
|
|
||||||
|
for (std::string_view name : navMesh)
|
||||||
|
statNames.emplace_back(name);
|
||||||
|
|
||||||
|
return statNames;
|
||||||
|
}
|
||||||
|
|
||||||
void setupStatCollection()
|
void setupStatCollection()
|
||||||
{
|
{
|
||||||
const char* envList = getenv("OPENMW_OSG_STATS_LIST");
|
const char* envList = getenv("OPENMW_OSG_STATS_LIST");
|
||||||
|
@ -258,6 +303,7 @@ namespace Resource
|
||||||
, mSwitch(new osg::Switch)
|
, mSwitch(new osg::Switch)
|
||||||
, mCamera(new osg::Camera)
|
, mCamera(new osg::Camera)
|
||||||
, mTextFont(getMonoFont(vfs))
|
, mTextFont(getMonoFont(vfs))
|
||||||
|
, mStatNames(generateAllStatNames())
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::StateSet> stateset = mSwitch->getOrCreateStateSet();
|
osg::ref_ptr<osg::StateSet> stateset = mSwitch->getOrCreateStateSet();
|
||||||
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
@ -465,7 +511,7 @@ namespace Resource
|
||||||
const osg::Vec4 staticTextColor(1.0, 1.0, 0.0f, 1.0);
|
const osg::Vec4 staticTextColor(1.0, 1.0, 0.0f, 1.0);
|
||||||
const osg::Vec4 dynamicTextColor(1.0, 1.0, 1.0f, 1.0);
|
const osg::Vec4 dynamicTextColor(1.0, 1.0, 1.0f, 1.0);
|
||||||
|
|
||||||
const auto longest = std::max_element(allStatNames.begin(), allStatNames.end(),
|
const auto longest = std::max_element(mStatNames.begin(), mStatNames.end(),
|
||||||
[](const std::string& lhs, const std::string& rhs) { return lhs.size() < rhs.size(); });
|
[](const std::string& lhs, const std::string& rhs) { return lhs.size() < rhs.size(); });
|
||||||
const std::size_t longestSize = longest->size();
|
const std::size_t longestSize = longest->size();
|
||||||
const float statNamesWidth = longestSize * characterSize * 0.6 + 2 * backgroundMargin;
|
const float statNamesWidth = longestSize * characterSize * 0.6 + 2 * backgroundMargin;
|
||||||
|
@ -473,14 +519,14 @@ namespace Resource
|
||||||
const float statHeight = pageSize * characterSize + 2 * backgroundMargin;
|
const float statHeight = pageSize * characterSize + 2 * backgroundMargin;
|
||||||
const float width = statNamesWidth + backgroundSpacing + statTextWidth;
|
const float width = statNamesWidth + backgroundSpacing + statTextWidth;
|
||||||
|
|
||||||
for (std::size_t offset = 0; offset < allStatNames.size(); offset += pageSize)
|
for (std::size_t offset = 0; offset < mStatNames.size(); offset += pageSize)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Group> group = new osg::Group;
|
osg::ref_ptr<osg::Group> group = new osg::Group;
|
||||||
|
|
||||||
group->setCullingActive(false);
|
group->setCullingActive(false);
|
||||||
|
|
||||||
const std::size_t count = std::min(allStatNames.size() - offset, pageSize);
|
const std::size_t count = std::min(mStatNames.size() - offset, pageSize);
|
||||||
std::span<const std::string> currentStatNames(allStatNames.data() + offset, count);
|
std::span<const std::string> currentStatNames(mStatNames.data() + offset, count);
|
||||||
osg::Vec3 pos(statsWidth - width, statHeight - characterSize, 0.0f);
|
osg::Vec3 pos(statsWidth - width, statHeight - characterSize, 0.0f);
|
||||||
|
|
||||||
group->addChild(
|
group->addChild(
|
||||||
|
|
|
@ -57,6 +57,7 @@ namespace Resource
|
||||||
osg::ref_ptr<osg::Switch> mSwitch;
|
osg::ref_ptr<osg::Switch> mSwitch;
|
||||||
osg::ref_ptr<osg::Camera> mCamera;
|
osg::ref_ptr<osg::Camera> mCamera;
|
||||||
osg::ref_ptr<osgText::Font> mTextFont;
|
osg::ref_ptr<osgText::Font> mTextFont;
|
||||||
|
std::vector<std::string> mStatNames;
|
||||||
|
|
||||||
void setWindowSize(int w, int h);
|
void setWindowSize(int w, int h);
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace Terrain
|
||||||
|
|
||||||
void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Terrain Chunk", mCache->getCacheSize());
|
Resource::reportStats("Terrain Chunk", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChunkManager::clearCache()
|
void ChunkManager::clearCache()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "texturemanager.hpp"
|
#include "texturemanager.hpp"
|
||||||
|
|
||||||
#include <osg/Stats>
|
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
|
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
|
@ -56,7 +55,7 @@ namespace Terrain
|
||||||
|
|
||||||
void TextureManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
void TextureManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const
|
||||||
{
|
{
|
||||||
stats->setAttribute(frameNumber, "Terrain Texture", mCache->getCacheSize());
|
Resource::reportStats("Terrain Texture", frameNumber, mCache->getStats(), *stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue