У меня есть структура, которая позволяет пользователям делать запросы к определенному источнику данных (игровая база данных Football Manager 2010 для тех, кто вас интересует).Как это сделать быстро?
В этом контексте у меня есть два разных режима, в которых может работать мой фрейм: режим реального времени и режим кэширования. Я хочу, чтобы пользователи, которые используют эту инфраструктуру, могли переключаться, просто вызвав другой конструктор (например, new Context(Mode.Cached)
). Это должен быть единственный переключатель, который должен сделать пользователь, поэтому он все равно может иметь все те же вызовы Linq, но просто использует режим кэширования, когда его приложение подходит лучше. Очистить.
я решил, что использование PostSharp должно быть моим лучшим выбором, потому что:
- Создание аспекта на каждой собственности (который уже был украшен атрибутом)
- В этом аспекте, проверьте ли мы в
Cached
илиRealtime
режим - Возвращает значение либо из памяти или из кэша
Ну что работает. НО! Скорость не достаточно хороша. При выполнении следующих условий на 90 000 объектов:
foreach (Player p in fm.Players)
{
int ca = (short)ProcessManager.ReadFromBuffer(p.OriginalBytes, PlayerOffsets.Ca, typeof(Int16));
}
Это занимает всего 63 мс. (ReadFromBuffer - это высоко оптимизированная функция, которая принимает byte[], int, Type
и возвращает object
), 63 мс очень разумно, учитывая большое количество объектов.
Но! В PostSharp, я реализовал совсем то же самое, используя это:
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
if (eventArgs.Method.Name.StartsWith("~get_"))
{
if (Global.DatabaseMode == DatabaseModeEnum.Cached)
{
byte[] buffer = ((BaseObject)eventArgs.Instance).OriginalBytes;
eventArgs.ReturnValue =
ProcessManager.ReadFromBuffer(buffer, this.Offset, eventArgs.Method.ReturnType);
}
Теперь я называю это с помощью
foreach (Player p in fm.Players)
{
int ca = p.CA;
}
И он принимает 782 мс, более чем в 10 раз больше!
Я создал аспект, как:
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, PersistMetaData = true)]
internal class FMEntityAttribute : OnMethodInvocationAspect
{
public FMEntityAttribute(int offset, int additionalStringOffset)
{
this.Offset = offset;
this.AdditionalStringOffset = additionalStringOffset;
}
//blah blah AOP code
}
И свойство оформлен как
[FMEntityAttribute(PlayerOffsets.Ca)]
public Int16 CA { get; set; }
Как я могу получить это хорошо выступить ?!
Что означал ваш прогон профилирования, было дорогое горячее пятно? –
То, что больше всего времени проводилось в моей собственности getter, не очень полезная информация. –