Is there a way to prevent a cache miss when using singleton objects? Here’s my current singleton implementation:
SingletonObject.h
#pragma once
class SingletonObject
{
public:
static SingletonObject* SingletonObject();
static void SingletonObject();
private:
static SingletonObject* sSingletonObject;
SingletonObject();
~SingletonObject();
};
SingletonObject.cpp
#include "SingletonObject.h"
SingletonObject* SingletonObject::sSingletonObject = NULL;
SingletonObject:: SingletonObject()
{
}
SingletonObject::~ SingletonObject()
{
}
SingletonObject* SingletonObject::GetSingleton()
{
if (sSingletonObject == NULL) // cache miss
{
sSingletonObject = new SingletonObject();
}
return sSingletonObject;
}
void SingletonObject::DestroySingleton()
{
delete sSingletonObject;
sSingletonObject = NULL;
}
Is there a better way to do this that prevents a cache miss? Is this just another reason to not use singletons?
Update: Turns out it really was nothing to do with cache as much as the code generated for stack unwinding and the conditional check in the GetSingleton() call. By explicitly creating and destroying the singleton (instead of demand-creating it), and creating an accessor for the static instance, I was able to avoid much of the overhead and noted a significant speedup in profiling.
SingletonObject.h
#pragma once
class SingletonObject {
public:
static void CreateSingleton();
static void DestroySingleton();
static inline SingletonObject* GetSingleton() { return sInstance; }
private:
static SingletonObject* sInstance;
SingletonObject();
}
SingletonObject.cpp
#include "SingletonObject.h"
void SingletonObject::CreateSingleton() {
if (sInstance == NULL)
sInstance = new SingletonObject();`
}
void SingletonObject::DestroySingleton() {
delete(sInstance);
sInstance = NULL;
}
This is a very specific question people arrive to way down the performance optimization road. Are you sure you’re all the way there? Reason I’m asking is if you access your Singleton frequently enough, the pointer to the object will stay in cache. If it’s not in cache, then you’re not accessing the object frequently enough, which means you don’t really need it, so prefetching the pointer (or the object) to cache will just steal precious cache space from something that you’re using more often in reality – this might even hurt the performance in a long run.
In my understanding arriving the question you’re at currently you’d have to go through the following steps:
static SingletonObject* SingletonObject();function really is a hot spot (>10% of the overall time is spend executing this one function)static SingletonObject* SingletonObject();and inspect if all those accesses are necessary. If they are, then it’s a justified cache miss and you can’t do anything about it. If they’re not, then reduce your working set by as much as you can and re-run the profiler (step 2)._mm_prefetch()calls in your code prior to accessing the Singleton object.