Я долго сидел над этой идеей и хотел бы услышать, что вы, ребята, думаете об этом.
Стандартная идиома написания синглтона примерно такова:
public class A {
...
private static A _instance;
public static A Instance() {
if(_instance == null) {
_instance = new A();
}
return _instance;
}
...
}
Здесь я предлагаю другое решение:
public class A {
...
private static A _instance;
public static A Instance() {
try {
return _instance.Self();
} catch(NullReferenceExceptio) {
_instance = new A();
}
return _instance.Self();
}
public A Self() {
return this;
}
...
}
Основная идея заключается в том, что затраты времени выполнения 1 разыменования и неисключенного исключения меньше, чем стоимость одной нулевой проверки. Я попытался измерить потенциальный прирост производительности и вот мои цифры:
Сон 1сек (пробовать / ловить) : 188788мс
Сон 1сек (проверка нуля) : 207485мс
И тестовый код:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
public class A
{
private static A _instance;
public static A Instance() {
try {
return _instance.Self();
} catch(NullReferenceException) {
_instance = new A();
}
return _instance.Self();
}
public A Self() {
return this;
}
public void DoSomething()
{
Thread.Sleep(1);
}
}
public class B
{
private static B _instance;
public static B Instance() {
if(_instance == null) {
_instance = new B();
}
return _instance;
}
public void DoSomething()
{
Thread.Sleep(1);
}
}
public class MyClass
{
public static void Main()
{
Stopwatch sw = new Stopwatch();
sw.Reset();
sw.Start();
for(int i = 0; i < 100000; ++i) {
A.Instance().DoSomething();
}
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for(int i = 0; i < 100000; ++i) {
B.Instance().DoSomething();
}
Console.WriteLine(sw.ElapsedMilliseconds);
RL();
}
#region Helper methods
private static void WL(object text, params object[] args)
{
Console.WriteLine(text.ToString(), args);
}
private static void RL()
{
Console.ReadLine();
}
private static void Break()
{
System.Diagnostics.Debugger.Break();
}
#endregion
}
Результирующий прирост производительности составляет почти 10%, вопрос в том, является ли это микрооперацией, или она может предложить значительное повышение производительности для одноэлементных приложений (или для промежуточного программного обеспечения, например, журналирование)?