Categories
Delphi Programming

RTTI in Delphi 2010, nice but a little bit too slow

First of all RTTI is a very nice feature I think. You can do a lot of funny things especially when you combine this technique with Generics. But there is a problem I’m not very glad about: the speed is not that good, so I had to change some things in my O/R mapping class. I do not want to explain what I’m working on because my intention of this post is to write down some words about my experiences with this RTTI feature and the speed.

At the moment I have a test application which does the following: it has one class TTest which has two properties, PropA: String and PropB: Integer. I create one instance of this class and set the property in a loop which starts at 100000. The setter call on the one side is the direct setter method and on the other the SetValue() method of the RTTI class TRttiProperty. These are my results; the last two columns are denoted in milliseconds:

loop count simple setter RTTI SetValue()
100000 0 359
600000 15 2169
1100000 15 4025
1600000 31 5772
2100000 16 7566
2600000 31 9360
3100000 47 11201
3600000 47 13041
4100000 47 14852
4600000 62 16567
5100000 63 18345

As you can see this shows that a call of the SetValue() method is really slow against directly setting a property. So it is not advising that you are using too much of SetValue() like I did ;) I know that there is a lot of magic behind this method and TValue is very powerful but i haven’t believed that there is such a huge difference. In my case now I’m using a mixture of direct setting and getting properties and the usage of the RTTI SetValue/GetValue.

Some further tests…

Before some minutes I had a beautiful idea how to improve the speed of setting values via RTTI. Imagine you have an index over the properties (e.g. THashedStringList in unit IniFiles) so that you can find very fast a pointer of the property setter method (okay, you could do this every time via a loop… but that’s stupid). When you want to set a value to a property you only have to get the associated pointer to the setter method (look-up in index), “create” a TMethod instance, set method and object pointer in the TMethod instance and call it. Yeah, it could be so easy, but it is not so easy. Think about properties which doesn’t have a setter method or are not writeable. What about the data type!? TMethod does only support pointers, and so on…

Because there are some traps there are already implementations of this functionality. Look through the code of TypInfo.pas, there you can find methods for nearly all data types which already implements my idea ;) Some examples are SetStrProp(), SetOrdProp() (for integers), SetObjectProp() (for classes), and so on. Here some new Results comparing the three told possibilities (now I used TStopWatch in Diagnostics.pas instead of GetTickCount() method for measure time):

loop count simple setter RTTI SetValue() TypInfo methods
100000 1 349 52
600000 6 2088 313
1100000 12 3813 571
1600000 18 5594 834
2100000 24 7281 1096
2600000 30 9047 1357
3100000 36 10787 1617
3600000 42 12549 1888
4100000 48 14303 2146
4600000 53 15980 2436
5100000 60 17783 2659

How you can see the usage of the setter methods in TypInfo.pas is much better than the SetValue() method of the TRttiProperty class. But when you want to use this solution you have to set the properties you want to set via RTTI published and enable the RTTI feature via {$M+} (set this before the corresponding class). You can easily do this with you own classes but what about others?

Fast, Faster, Fastest (at the moment ;)

I have found a way combining the old (TypInfo.pas) and the new (Rtti.pas) version of RTTI to improve speed about 90% comparing the normal setter method usage told above (i mean using the methods which expects a string as property name and not a pointer to PPropInfo). Here some code:

// get references to properties
p1 := T.GetProperty('PropA');
p2 := T.GetProperty('PropB');

// get pointers to PPropInfo of properties
pi1 := TRttiInstanceProperty(p1).PropInfo;
pi2 := TRttiInstanceProperty(p2).PropInfo;

// run benchmark...
for i := 0 to counter do
begin
  SetStrProp(obj, pi1, 'User');
  SetOrdProp(obj, pi2, 100000);
end;

The trick is not to use the propertyname in SetStrProp() or SetOrdProp() because these methods has an internal loop searching for the PPropInfo of the given property (yes, there als also some other stuff…). So i came to this results:

loop count simple setter RTTI SetValue() TypInfo methods Combined methods (code above)
100000 1 349 52 4
600000 6 2088 313 26
1100000 12 3813 571 48
1600000 18 5594 834 70
2100000 24 7281 1096 92
2600000 30 9047 1357 114
3100000 36 10787 1617 136
3600000 42 12549 1888 159
4100000 48 14303 2146 181
4600000 53 15980 2436 203
5100000 60 17783 2659 224

Now i will use RTTI setter methods again but in my way :)

Here you can download the RTTI Speed Demo (152.4 KiB, 348 hits) with which i created these results. I think that it will compile only in Delphi 2010 because if the usage of Rtti.pas and Diagnostics.pas.

2 replies on “RTTI in Delphi 2010, nice but a little bit too slow”

Thanks for the posting! I ‘ve had the same problem (for my own ORM implementation by the way ;-) ) and thought about performance, too. Your comparison made my life a bit easier …

Leave a Reply

Your email address will not be published. Required fields are marked *

Captcha * Time limit is exhausted. Please reload CAPTCHA.