Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to get this really fast?
    primarykey
    data
    text
    <p>I have a framework that allows users to do queries to a specific datasource (the Football Manager 2010 ingame database, for those of you interested).</p> <p>In this framework, I have two different modes wherein my framework can run: realtime and cached mode. I want users who use this framework to be able to switch by just calling a different constructor (e.g. <code>new Context(Mode.Cached)</code>). That should be the only switch a user should make, so he can still have all the same Linq calls, but just use Cached mode when his application fits better. Clear.</p> <p>I had decided that using PostSharp should be my best choice because:</p> <ul> <li>Create an aspect on every property (that's already been decorated by an attribute)</li> <li>In that aspect, check whether we are in <code>Cached</code> or <code>Realtime</code> mode</li> <li>Return the value either from memory or from cache</li> </ul> <p>Well that works. BUT! Speed is not good enough. When doing the following on 90.000 objects:</p> <pre><code>foreach (Player p in fm.Players) { int ca = (short)ProcessManager.ReadFromBuffer(p.OriginalBytes, PlayerOffsets.Ca, typeof(Int16)); } </code></pre> <p>It takes only 63 ms. (ReadFromBuffer is a highly optimized function which takes <code>byte[], int, Type</code> and returns <code>object</code>), 63 ms is very reasonable considering the large amounts of objects.</p> <p><strong>But!</strong> In PostSharp, I implemented quite the same using this:</p> <pre><code> 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); } </code></pre> <p>Now I call this using</p> <pre><code>foreach (Player p in fm.Players) { int ca = p.CA; } </code></pre> <p>And it takes <em>782 ms</em>, more than 10 times as much!</p> <p>I created the aspect as:</p> <pre><code>[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 } </code></pre> <p>And the property is decorated like</p> <pre><code> [FMEntityAttribute(PlayerOffsets.Ca)] public Int16 CA { get; set; } </code></pre> <p>How can I get this to perform well?!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload