Hi, at 1 minute in the video there's this piece of code: if (_instance is not null) { return _instance; } return _instance ??= new Manager(); Why the if statement? Doesn't the null-coalescing already cover it thus make it redundant? I'm kind of new to C# programming and I'm asking maybe I'm missing something.
Valid point I missed it when I moved it to Rider because originally I had implemented locking to make it thread safe but I removed it last minute to have more accurate benchmarks. It shouldn’t affect the benchmarks in any meaningful way (I will have to check if the JIT will optimise one of the checks out) and the point of the video isn’t just about the performance difference but the use-case differences
The singleton you come up with is a special type of singleton: a _lazy_ singleton. A non-thread-safe in particular, because .Instance can be called from multiple threads. If the ctor takes time (which it probably does, because that's often why you are using a singleton), then _instance will be null if a second thread calls .Instance, resulting in two invocations of the ctor. You should Lazy for lazy singleton init.
It's a unity example. You could remove the nullcheck and create that thing once at game-init where it's guaranteed to be called from the main thread before anything concurrent ever happens.
Chiming in from someone who works in gaming: the difference is small but I think it's definitely something we'd care about (in context). Because: 1. A single call might not make much of a difference, but singleton managers like this are often accessed many times from all over the place. The cost can stack up. 2. The cost to implementing this optimization is minimal (trivial basically) and the cost to readability and maintainability is also almost nil. That makes this kind of premature optimization more worth doing all the time. 3. (Context based) If you're building a general purpose library or system that's intended for use by others, the more performance you eke out the more variability you allow your end users (they can be sloppier with their code). But ultimately, this is all in gaming, where you have 16ms to do your frame (60fps) and many individual subsystems have budgets in the 2-5ms range.
If your Singleton is a static readonly field instead of a getter, then you should have close-to-zero overhead, because at runtime it's just going to be an extra pointer dereference. Also you can have some overhead if the JIT is unable to inline the Singleton getter. To avoid that, the bulk of the initialization work should be in a separate method, and the getter should have only the null check + method call. But static readonly is usually the best approach. You're effectively delegating the "is initialized" check to the JIT itself.
We always used Autofac and their singleton pattern, which worked well for us. We had a method that did all the instantiation necessary to compose all the application components. These were business applications where wringing every last bit of performance out of the code generally wasn't necessary. But it made for a nice clean pattern and of course we had all the other DI goodness (and pain).
I've been a professional unity dev for almost 10 years and have seen all kinds of code bases and optimizations. Singletons are extremely common where an instance lives on a static field. The only time I've seen caching that instance makes a difference (and even then extremely uncommon) is in highly complex functions that do many many calculations. And even then, you might squeeze 2ms out of something that only happens once every 5 minutes on an extremely old mobile phone. Like the redit comment said. There's other stuff to invest your time in, and this is something to forget about. To understand the problem then unity calls "benchmarking" "profiling".
There are multiple other important common problems to avoid with either singletons or statics on web servers: Thread safety is a must, especially if any kind of writes occur against your singleton obj. If you use a DI container with lifetimes, you may have a potential captive scope dependency problem to worry about. Outside of gaming or latency sensitive applications, i think the perf penalty is less important compared to the above 2 issues. An honorable 3rd place mention would be for me 'is the dependency you're referencing supposed to also be a singleton' as some objects carry properties that inherently imply multiples of them should exist. Other fun to cover material is inappropriate use of SDKs that are not necessarily designed to be transient lifetime, like the azure storage sdk.
It would be better initializing the singleton in the static constructor. Just keep in mind that static constructor messes up with the debugger when it throws an exception. Also you dont need a if before return _instance ?== new Manager() as this line aleready tests if _instance is null.
@maushax i don't say that you should avoid that solution, just that constructors must be kept fucking simple unless you want to fight against the debugger.
Instead of having a getter with a null-check, initialize a readonly field either with a static constructor or a field expression, and expose that field as public.
Question at the end: I usually use locks at initialization, out of habit. Probably not necessary in a lot of situations. But the performance hit is so minor, I just play it safe.
Hi! I think I didn't hear it in the video so I will write about it here. If it was said then I must have missed it and I will remove this comment :) The example shows using this caching inside of a loop and not as a single-time thing. Properties are functions calls and they will always be slower than accessing a variable. This is negligible when this does not accumulate, but it is accumulating inside of loops like the one showed in this post. I have a professional experience in Unity and there were times when I had to do this type of caching to optimize. Mostly as a variable before the loop instead of a field but it doesn't change much. Thanks! :)
I would advise against holding state in a static class, not because it wouldn't work, but because it can get ugly fast. I worked on a codebase where dozens of "global variables" were aggregated as public static in a static class.... debugging was a nightmare.
Funny thing you should mention DI frameworks. I do not use one, because I feel like they obfuscate code more than they help. Where did my instance come from? Where was my instance created? Tracking that through a DI framework whose internals you don't know, is a pain. I love DI, but I always do pure manual DI all the way. Regarding singletons, I really think it's an anti-pattern. There is no reason for it to exist in my opinion. If you need an instance and only one instance of a class, instantiate it once then inject it where it's needed. You control where it's created, you control the lifetime. No performance overhead, no "multi-second" surprises.
Yeah nothing new here, but this is one reason why never ever put heavy load/code into any constructor! I don't expect that constructing a class instance or even a struct takes longer than some nanoseconds. But when i call something like Process(), Load(), Compute(), Initialize(), then i expect that i may take longer. Also nowadays in the C# world, heavy load activities should be async anyway, so when stuff happens inside the ctor you have to wrap it around a Task.Run() or something.
Your singleton is not thread safe. Usually, you wrap initialization inside a lock statement, or you would use Lazy class to initialize the singleton in a thread-safe manner. I think that would result in even more performance impact (maybe).
I suppose one "pro" of storing it as a variable rather than accessing .Instance could be that *that* specific consumer doesn't need to "worry" about it actually being a singleton or not, though of course that knowledge just gets pushed elsewhere. So if for whatever reason it changes to not be a singleton and as such loses its static .Instance method, then this particular consumer's code doesn't need to be modified. Extremely niche scenario but one minor, minor thing nevertheless.
By the way, I think it's important to note that current version of Unity use Mono platform, and for benchmarking results to be completely valid for the Unity, it would be fair to run benchmarks on Mono. Though, I don't think for this specific case results would be drastically different anyways. More like an advice for those, who would want to benchmark other Unity stuff.
I think you should have run the benchmark a second time but using Mono. Mono is leagues behind .NET 9 and is notorious for producing _compliant_ code rather than _fast_ code. For example, Mono definitely would not inline the getter like many comments suggest, and it also wouldn't remove the second null check that was added by mistake. Both of those would probably add up to more than a single microsecond difference.
I'm curious, if you would use the static property instantiation(public static Manager Instance = new ()), would you have the same result? Since it does only initiatlize the static property on the first code, and then does not this "if" check?
Depends on. If a cycle update is necessary, I will inject a system to Unity LowLevel PlayerLoop. If it's a library, kindly create a static class. MonoBehaviour components are almost use to control game objects, renderable objects, or audios in my unity projects. So if there is a MonoBehaviour component which is really necessary and should be alive in the whole game (or application), I will make it as a Singleton.
I thought you going to talk about state and locking in singleton from the title. It remind me of inline function in C you can reduce function call overhead at least
Note You should not use the static field on Unity because of the MonoBehaviour lifecycle you can end up with weird initialization order dependent behavior since you cannot new up MonoBehaviors the static field always need to start off as null
The singleton implementation is not only slower than it needs to be but also not thread safe. It's much better to use a static readonly field initialised and a static constructor. Then the property Instance simply returns the field, no need to check for null and it will likely be inlined.
I think this is also where Nick is going, but this seems like such a pointless question. By definition, singletons and static classes will (at most) be instaniated once, so any performance difference would be negligible in the grand scheme of things.
This is nonsense. Benchmarking something that has a result in nanoseconds but in the real world contains reading a value from RAM has no value. Both benchmarks read from CPU cache, so it is only the method call overhead. And just to be sure i googled memory latency, and it is still around 13ns for modern RAM.
Singletons are only used by junior developers because they lack the fundamental knowledge to do dependency injection which would negate the need to have a singleton. For me they are considered anti-pattern since they can create the following issues: 1. Anti-testing issue (Can't test code that uses singletons) 2. Global states (bad cache utilization for video games since the memory location is laid out everywhere) 3. Increased complexity which can lead to spaghetti 4. Cross dependency-initialization issues (Singleton accessing another singleton which i've seen it happen many times) Most of these issues if not all are usually just applicable to game code and you don't need to bother if you're just writing some small app that does something simple. Either way you can just do DI and avoid this anti-pattern pattern.
Singletons have nothing to do with Dependency Injection, DI does not negate the need for Singletons. There is an Extension Method on the Service Collection called "AddSingleton". This way, it is just handled by the DI-Framework. But yes, Singletons can be problematic, especially when used extensively...
Don't agree with you. What if you need to have some state that is the same across whole application lifetime. Read from a file once for example That singleton from the video is barely used. Class is usually registered as singleton during DI and you can easy do testing where it is used.
i use this for singletons in case i need it old way: public sealed class Singleton { // Static members are lazily initialized. // .NET guarantees thread safety for static initialization private static readonly Singleton _instance = new(); private Singleton() {}
public static Singleton Instance() => _instance;
public int DoSomething() { return System.Random.Shared.Next(); } } no need for double checking nor locking
Hi, at 1 minute in the video there's this piece of code:
if (_instance is not null)
{
return _instance;
}
return _instance ??= new Manager();
Why the if statement? Doesn't the null-coalescing already cover it thus make it redundant? I'm kind of new to C# programming and I'm asking maybe I'm missing something.
You are correct
lol, true, I think he missed it
and maybe that's also part of his benchmark results hah
Valid point I missed it when I moved it to Rider because originally I had implemented locking to make it thread safe but I removed it last minute to have more accurate benchmarks. It shouldn’t affect the benchmarks in any meaningful way (I will have to check if the JIT will optimise one of the checks out) and the point of the video isn’t just about the performance difference but the use-case differences
@@nickchapsas guess you could call this "Nick-picking"
The singleton you come up with is a special type of singleton: a _lazy_ singleton. A non-thread-safe in particular, because .Instance can be called from multiple threads. If the ctor takes time (which it probably does, because that's often why you are using a singleton), then _instance will be null if a second thread calls .Instance, resulting in two invocations of the ctor.
You should Lazy for lazy singleton init.
Watch until the end
It's a unity example. You could remove the nullcheck and create that thing once at game-init where it's guaranteed to be called from the main thread before anything concurrent ever happens.
Chiming in from someone who works in gaming: the difference is small but I think it's definitely something we'd care about (in context). Because:
1. A single call might not make much of a difference, but singleton managers like this are often accessed many times from all over the place. The cost can stack up.
2. The cost to implementing this optimization is minimal (trivial basically) and the cost to readability and maintainability is also almost nil. That makes this kind of premature optimization more worth doing all the time.
3. (Context based) If you're building a general purpose library or system that's intended for use by others, the more performance you eke out the more variability you allow your end users (they can be sloppier with their code).
But ultimately, this is all in gaming, where you have 16ms to do your frame (60fps) and many individual subsystems have budgets in the 2-5ms range.
If your Singleton is a static readonly field instead of a getter, then you should have close-to-zero overhead, because at runtime it's just going to be an extra pointer dereference.
Also you can have some overhead if the JIT is unable to inline the Singleton getter. To avoid that, the bulk of the initialization work should be in a separate method, and the getter should have only the null check + method call.
But static readonly is usually the best approach. You're effectively delegating the "is initialized" check to the JIT itself.
totally agree )
1:00 btw this operator checks for null as well, basically you do not need if check before it and it would work the same
We always used Autofac and their singleton pattern, which worked well for us. We had a method that did all the instantiation necessary to compose all the application components. These were business applications where wringing every last bit of performance out of the code generally wasn't necessary. But it made for a nice clean pattern and of course we had all the other DI goodness (and pain).
I've been a professional unity dev for almost 10 years and have seen all kinds of code bases and optimizations.
Singletons are extremely common where an instance lives on a static field.
The only time I've seen caching that instance makes a difference (and even then extremely uncommon) is in highly complex functions that do many many calculations. And even then, you might squeeze 2ms out of something that only happens once every 5 minutes on an extremely old mobile phone.
Like the redit comment said.
There's other stuff to invest your time in, and this is something to forget about.
To understand the problem then unity calls "benchmarking" "profiling".
There are multiple other important common problems to avoid with either singletons or statics on web servers:
Thread safety is a must, especially if any kind of writes occur against your singleton obj.
If you use a DI container with lifetimes, you may have a potential captive scope dependency problem to worry about.
Outside of gaming or latency sensitive applications, i think the perf penalty is less important compared to the above 2 issues.
An honorable 3rd place mention would be for me 'is the dependency you're referencing supposed to also be a singleton' as some objects carry properties that inherently imply multiples of them should exist.
Other fun to cover material is inappropriate use of SDKs that are not necessarily designed to be transient lifetime, like the azure storage sdk.
Just to mention, the shown singleton pattern is not thread-save!
Watch until the end
It would be better initializing the singleton in the static constructor. Just keep in mind that static constructor messes up with the debugger when it throws an exception.
Also you dont need a if before return _instance ?== new Manager() as this line aleready tests if _instance is null.
>Mentions a possible "solution" for singleton initialization.
>Also states why should be avoided that "solution".
LMAO
@maushax i don't say that you should avoid that solution, just that constructors must be kept fucking simple unless you want to fight against the debugger.
You should check the "standard" singleton pattern which is static readonly.
Instead of having a getter with a null-check, initialize a readonly field either with a static constructor or a field expression, and expose that field as public.
Question at the end: I usually use locks at initialization, out of habit. Probably not necessary in a lot of situations. But the performance hit is so minor, I just play it safe.
Here at statischvssingleton
Me too, never do that again please.
Hi!
I think I didn't hear it in the video so I will write about it here. If it was said then I must have missed it and I will remove this comment :)
The example shows using this caching inside of a loop and not as a single-time thing. Properties are functions calls and they will always be slower than accessing a variable. This is negligible when this does not accumulate, but it is accumulating inside of loops like the one showed in this post. I have a professional experience in Unity and there were times when I had to do this type of caching to optimize. Mostly as a variable before the loop instead of a field but it doesn't change much.
Thanks! :)
I would advise against holding state in a static class, not because it wouldn't work, but because it can get ugly fast.
I worked on a codebase where dozens of "global variables" were aggregated as public static in a static class.... debugging was a nightmare.
Funny thing you should mention DI frameworks. I do not use one, because I feel like they obfuscate code more than they help. Where did my instance come from? Where was my instance created? Tracking that through a DI framework whose internals you don't know, is a pain. I love DI, but I always do pure manual DI all the way.
Regarding singletons, I really think it's an anti-pattern. There is no reason for it to exist in my opinion. If you need an instance and only one instance of a class, instantiate it once then inject it where it's needed. You control where it's created, you control the lifetime. No performance overhead, no "multi-second" surprises.
Yeah nothing new here, but this is one reason why never ever put heavy load/code into any constructor! I don't expect that constructing a class instance or even a struct takes longer than some nanoseconds. But when i call something like Process(), Load(), Compute(), Initialize(), then i expect that i may take longer. Also nowadays in the C# world, heavy load activities should be async anyway, so when stuff happens inside the ctor you have to wrap it around a Task.Run() or something.
Your singleton is not thread safe. Usually, you wrap initialization inside a lock statement, or you would use Lazy class to initialize the singleton in a thread-safe manner. I think that would result in even more performance impact (maybe).
I suppose one "pro" of storing it as a variable rather than accessing .Instance could be that *that* specific consumer doesn't need to "worry" about it actually being a singleton or not, though of course that knowledge just gets pushed elsewhere. So if for whatever reason it changes to not be a singleton and as such loses its static .Instance method, then this particular consumer's code doesn't need to be modified. Extremely niche scenario but one minor, minor thing nevertheless.
wtf - yt translates the title and description automatically now? How can i disable that?
The question is where do I disable that. It looks like it was auto activated for every channel on TH-cam
I think for now, the only way is to change your youtube language
By the way, I think it's important to note that current version of Unity use Mono platform, and for benchmarking results to be completely valid for the Unity, it would be fair to run benchmarks on Mono. Though, I don't think for this specific case results would be drastically different anyways. More like an advice for those, who would want to benchmark other Unity stuff.
I think you should have run the benchmark a second time but using Mono. Mono is leagues behind .NET 9 and is notorious for producing _compliant_ code rather than _fast_ code.
For example, Mono definitely would not inline the getter like many comments suggest, and it also wouldn't remove the second null check that was added by mistake. Both of those would probably add up to more than a single microsecond difference.
I'm curious, if you would use the static property instantiation(public static Manager Instance = new ()), would you have the same result? Since it does only initiatlize the static property on the first code, and then does not this "if" check?
Depends on. If a cycle update is necessary, I will inject a system to Unity LowLevel PlayerLoop. If it's a library, kindly create a static class. MonoBehaviour components are almost use to control game objects, renderable objects, or audios in my unity projects.
So if there is a MonoBehaviour component which is really necessary and should be alive in the whole game (or application), I will make it as a Singleton.
Your mention of the source generated DI is very interesting, can you make a video on it, with a library that you recommend?
The problem I have with caching a singleton like that is that the code 'knows' something that it shouldn't, that the other class is a singleton.
Why does it has 2 null checks? It has the "if is not null" and then nullish assignment?
Yeah I missed it when I moved it to the IDE. Shouldn’t affect the benchmarks in any meaningful way and the point of the video still stands
@nickchapsas will the first check get ignored?
It sure how the compiler or the JIT will optimise them. I would have to check the ASM
I thought you going to talk about state and locking in singleton from the title. It remind me of inline function in C you can reduce function call overhead at least
Note You should not use the static field on Unity because of the MonoBehaviour lifecycle you can end up with weird initialization order dependent behavior since you cannot new up MonoBehaviors the static field always need to start off as null
If your Monobehaviour gets destroyed then you did something wrong with your singleton setup. It should not be destroyed at all.
LOL, I clicked download and the video started with you speaking german! 🤣🤣🤣 Had to delete the video and download again
doesn't unity use really old dotnet?
my guy nick started with conquer online servers like me
The singleton implementation is not only slower than it needs to be but also not thread safe. It's much better to use a static readonly field initialised and a static constructor. Then the property Instance simply returns the field, no need to check for null and it will likely be inlined.
Why not expose the field as public? Why do you need a property at all?
"Benchmark it" he says, then proceeds to benchmark the wrong language 😂
I first read this as "you simpletons need to" sleepy
Same example but with record??
if or not to if, that is the question:)
I think this is also where Nick is going, but this seems like such a pointless question.
By definition, singletons and static classes will (at most) be instaniated once, so any performance difference would be negligible in the grand scheme of things.
Not thread-safe.
Please remove automatic translation.
This is nonsense.
Benchmarking something that has a result in nanoseconds but in the real world contains reading a value from RAM has no value.
Both benchmarks read from CPU cache, so it is only the method call overhead. And just to be sure i googled memory latency, and it is still around 13ns for modern RAM.
Singletons are only used by junior developers because they lack the fundamental knowledge to do dependency injection which would negate the need to have a singleton.
For me they are considered anti-pattern since they can create the following issues:
1. Anti-testing issue (Can't test code that uses singletons)
2. Global states (bad cache utilization for video games since the memory location is laid out everywhere)
3. Increased complexity which can lead to spaghetti
4. Cross dependency-initialization issues (Singleton accessing another singleton which i've seen it happen many times)
Most of these issues if not all are usually just applicable to game code and you don't need to bother if you're just writing some small app that does something simple.
Either way you can just do DI and avoid this anti-pattern pattern.
Singletons have nothing to do with Dependency Injection, DI does not negate the need for Singletons. There is an Extension Method on the Service Collection called "AddSingleton".
This way, it is just handled by the DI-Framework.
But yes, Singletons can be problematic, especially when used extensively...
Don't agree with you. What if you need to have some state that is the same across whole application lifetime. Read from a file once for example
That singleton from the video is barely used. Class is usually registered as singleton during DI and you can easy do testing where it is used.
i use this for singletons in case i need it old way:
public sealed class Singleton
{
// Static members are lazily initialized.
// .NET guarantees thread safety for static initialization
private static readonly Singleton _instance = new();
private Singleton() {}
public static Singleton Instance() => _instance;
public int DoSomething()
{
return System.Random.Shared.Next();
}
}
no need for double checking nor locking
return _instance ??= new Manager(); is all you need.