Slow Performance On Different Objects

Oct 8, 2012 at 8:33 PM
Edited Oct 8, 2012 at 8:38 PM

I'm seeing very slow performance when using FasterFlect on different objects to retrieve fields from 2 classes and 1 structure.  FasterFlect takes 1.7 sec per object set, whereas Reflection only takes 212 ms.  If I use the same objects for the FasterFlect DelegetForGetFieldValue calls, then its lightening fast, can't even measure it.  The purpose of my code is to workaround a limitation of the XmlSerializer by getting the name of the current node from the XmlTextWriter in my IXmlSerializable.WriteXml implementation.  Is there any way to fix this so a FasterFlect DelegateForGetFieldValue will run the same speed no matter what object it is passed?

Here's the slow code (1.7 sec)

Fasterflect.MemberGetter xmlWriterNodeStackGetter;
Fasterflect.MemberGetter xmlWriterNodeStackTopElementNumberGetter;
Fasterflect.MemberGetter xmlWriterStackElementNameGetter;
object          elementStack;
int             stackTopElementNo;
System.Array    tagInfoArray;
object          stackTopTag;
string          currXmlSerializerElementName;

Type writerType     = typeof(System.Xml.XmlTextWriter);
Type tagInfoType    = writerType.GetField("stack", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).FieldType.GetElementType();
xmlWriterNodeStackGetter = Fasterflect.FieldExtensions.DelegateForGetFieldValue(writerType, "stack", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
xmlWriterNodeStackTopElementNumberGetter = Fasterflect.FieldExtensions.DelegateForGetFieldValue(writerType, "top", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
xmlWriterStackElementNameGetter = Fasterflect.FieldExtensions.DelegateForGetFieldValue(tagInfoType, "name", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

elementStack = xmlWriterNodeStackGetter(writer);
stackTopElementNo = (int) xmlWriterNodeStackTopElementNumberGetter(writer);
tagInfoArray = (System.Array) elementStack;
stackTopTag = tagInfoArray.GetValue(new int[1] {stackTopElementNo});
currXmlSerializerElementName = (string) xmlWriterStackElementNameGetter(Fasterflect.ValueTypeExtensions.WrapIfValueType(stackTopTag));

For reference, this is the original Reflection code before I converted it (212 ms)

System.Reflection.FieldInfo elementStackField = writer.GetType().GetField("stack", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
System.Reflection.FieldInfo stackTopField = writer.GetType().GetField("top", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
object elementStack = elementStackField.GetValue(writer);
int stackTopElementNo = (int) stackTopField.GetValue(writer);
System.Array tagInfoArray;
tagInfoArray = (System.Array) elementStack;
object stackTopTag = tagInfoArray.GetValue(new int[1] {stackTopElementNo});
System.Reflection.FieldInfo stackTopElementNameField = stackTopTag.GetType().GetField("name", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
var currXmlSerializerElementName = stackTopElementNameField.GetValue(stackTopTag);

Coordinator
Oct 8, 2012 at 10:49 PM

That sounds odd, but I can't spot anything you seem to be doing wrong.. which would indicate a problem with Fasterflect.

Do you have a small ready-to-run test project that you could zip up and share somehow? (e.g. public DropBox link)

Oct 9, 2012 at 12:59 PM

Interesting – I’ve just found that this bug only repros with a certain type of call stack. Very unexpected. I’m building a sample project for you and should have it done soon.

David L-

From: mertner [email removed]
Sent: Monday, October 08, 2012 6:50 PM
To: David Luxford
Subject: Re: Slow Performance On Different Objects [fasterflect:398563]

From: mertner

That sounds odd, but I can't spot anything you seem to be doing wrong.. which would indicate a problem with Fasterflect.

Do you have a small ready-to-run test project that you could zip up and share somehow? (e.g. public DropBox link)

Oct 9, 2012 at 1:08 PM

Never mind - my bad!  I forgot the static statement on my class static constructor, causing the FasterFlect delegates to be recompiled with every object instance instead of only once.

Wheew!

Coordinator
Oct 9, 2012 at 1:14 PM

Sounds good, glad you got up to speed again :-)