Sterling API Developer Thread

Quote from bespoke:

Well, in C#.NET I can only receive up to about 700 quotes per second when using a counter in the QuoteUpdate event (and nothing but a counter in the event), whereas in VB6 I have received up to 5000 quotes per second and that also includes all the code I execute for my ATS, even including GUI changes.

My results:

Delphi: 1500 quotes/sec
VS6 C++ 2000 quotes/sec
VS6 VB 9000 quotes/sec

If someone has an explanation, please do post it, lol.
 
I've also tested with nothing but a counter in the event. 500-700 qps seems to be all it can handle. (The CPU that is) That is using C#.Net. This is the 1 and only reason I'm not using their quotes.

Worthless.
 
Quote from ers811:

I've also tested with nothing but a counter in the event. 500-700 qps seems to be all it can handle. (The CPU that is) That is using C#.Net. This is the 1 and only reason I'm not using their quotes.

Worthless.

Well, the thing is, that all other event handling is probably also way faster in VB (tradeupdates etc), so at the moment it sounds like VB is THE language of choice for the Sterling API (although that's not really fair to say, since it will really depend on the number of events to handle per second vs the rest of the code)
 
Quote from the_whistler:

My results:

Delphi: 1500 quotes/sec
VS6 C++ 2000 quotes/sec
VS6 VB 9000 quotes/sec

If someone has an explanation, please do post it, lol.
One thing to do is to use a profiler:

http://www.red-gate.com/Products/ants_profiler/index.htm

I would compare VB.NET and C++.NET or C#.NET. Then you can also look at the CIL generated for both and see if there is something obvious that makes one faster than another, and may give you a clue as to why you are seeing what you are seeing.

Otherwise, it is there are way to many variables and it would all be guessing.

nitro
 
Quote from nitro:

One thing to do is to use a profiler:

http://www.red-gate.com/Products/ants_profiler/index.htm

I would compare VB.NET and C++.NET or C#.NET. Then you can also look at the CIL generated for both and see if there is something obvious that makes one faster than another, and may give you a clue as to why you are seeing what you are seeing.

Otherwise, it is there are way to many variables and it would all be guessing.

nitro

I'm not using .NET, since it will use interop to translate COM messages which will result in a huge performance drop. If you have other idea's how to reverse engineer the COM stuff, please let me know (I'm good with ASM, but just don't know how to RE the COM events, since i don't know where to set breakpoints)
 
I ran some new tests, this time I timed setting a property of STIOrder: STIOrder.TIF.

When looping this 5000 times, I found on my setup:

Delphi takes 22 seconds
VB takes 14 seconds
C++ takes 10 seconds

I've reverse engineered the generated C++ code, I found that about all it does is call the windows "NdrClientCall2" API. From the MSDN:

The NdrClientCall2 function transmits all [in] data to the remote server, and upon receipt of the response packet, returns the [out] value to the client-side application
http://msdn.microsoft.com/en-us/library/aa374215(VS.85).aspx

Which makes sense of course, it's transmitting the TIF property into the base.exe process this way. Going to reverse engineer the Delphi stuff tomorrow and try to find out what the heck it's doing :) I wonder if it's using the same windows API ...
 
Did some initial reverse engineering of my Delphi code. I found that it's using the same windows API (NdrClientCall2), but it calls it twice ! Apart from that, there's a lot overhead. Anyway, not sure yet why it's calling that API twice. Below is the important part of the Delphi disassembly:

CODE:0045A758 loc_45A758: ; CODE XREF: ComObj::_16532+40j
CODE:0045A758 ; ComObj::_16532+51j
CODE:0045A758 lea eax, [ebp+dwMessageId]
CODE:0045A75E push eax ; dwMessageId
CODE:0045A75F xor ecx, ecx
CODE:0045A761 mov cl, [ebx+2]
CODE:0045A764 inc ecx
CODE:0045A765 xor eax, eax
CODE:0045A767 mov al, [ebx+1]
CODE:0045A76A lea edx, [ebx+eax+3]
CODE:0045A76E mov eax, [ebp+var_4]
CODE:0045A771 call unknown_libname_947 ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:0045A776 test esi, esi
CODE:0045A778 jz short loc_45A781
CODE:0045A77A mov eax, esi
CODE:0045A77C call @Variants@@VarClear$qqrr8TVarData ; Variants::__linkproc__ VarClear(TVarData &)
CODE:0045A781
CODE:0045A781 loc_45A781: ; CODE XREF: ComObj::_16532+78j
CODE:0045A781 mov eax, [ebp+arg_C]
CODE:0045A784 push eax
CODE:0045A785 push esi
CODE:0045A786 lea ecx, [ebp+dwMessageId]
CODE:0045A78C mov edx, ebx
CODE:0045A78E mov eax, [ebp+var_4]
CODE:0045A791 call @Comobj@DispatchInvoke$qqrx36System@_DelphiInterface$t9IDispatch_p16System@TCallDescpa65536$ipvp14System@Variant ; Comobj:: DispatchInvoke(System:: DelphiInterface<IDispatch>,System::TCallDesc *,int (*)[65536],void *,System::Variant *)
CODE:0045A796 pop esi
CODE:0045A797 pop ebx
CODE:0045A798 mov esp, ebp
CODE:0045A79A pop ebp
CODE:0045A79B retn
CODE:0045A79B @ComObj@_16532 endp
CODE:0045A79B

The calls to NdrClientCall2 are in the 2 routines printed in bold.

Anyway, as for now, it's obvious that Delphi just plain sucks at COM, and VB isn't doing that bad at all. Setting object properties is about 30-40% faster in C++, which makes sense. However, I'm still very confused why VB is beating the crap out of C++ when it comes to the COM event handling, going to try to find that out next, althought that most probably won't be very easy ...
 
very interesting.

I was poking around with my code today and I found something interesting that's undocumented but I have no idea what it does.

STIQuote.Destroy
and STIEvents.Destroy

Anyone know or have a guess of what they do?


- mnx
 
Back
Top