LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Callbacks and event optimization

Hello all,
while I was impressed 15 years ago by the speed at which CVI could
manipulate complex user interfaces, I now have the impression it has lagged
behind in respect to Moore's law. That is, it's not as fast now as it ough
to, but I course I don't have hard data to back this claim up.

I discovered recently the EVENT_MOUSE_POINTER_MOVE event. Does this mean
that every time my mouse moves over a control, both panel and control
callbacks get called hundreds of times per second (depending on the mouse
refresh rate), even if I don't use this event ?

Or is there some kind of optimization so that callback functions which only
make use of EVENT_COMMIT only get called for this event ? In the past I
thought it was overkill to get calls for EVENT_LEFT_CLICK, EVENT_FOCUS, etc
when all you want is an EVENT_COMMIT. But now with
EVENT_MOUSE_POINTER_MOVE...

Any way to manually optimize things up ?
--
Guillaume Dargaud
http://www.gdargaud.net/


0 Kudos
Message 1 of 8
(3,905 Views)

i would first say that CVI has never been a fast compiler. i performed some speed testing between CVI 7.0 and visual studio 6, CVI was more than 100 times slower than visual studio. of course, visual studio is an optimizing compiler, whereas CVI is not.

 

second, the mouse move event is not CVI specific: Windows generates this event, and the system sends hundreds of WM_MOUSEMOVE event per second. now, (contrary to what everybody believes) microsoft developpers are smart, and they know this may harm the system performances: the event queue is optimized so that some events are not posted twice if they are not processed. this way you do not receive hundreds of mouse move events if you can't process them.

 

also, note that an event is not posted to all windows in the system: the event first goes to the top level window, and are sometimes passed to the parent window. that's why EVENT_FOCUS and EVENT_LEFT_CLICK will not kill your application. if you are concerned about these performance problems,  think about the clock: every millisecond, the system gets interrupted only to increment a counter, 1000 times per second. think also about the thread context switches, about 100 times per second, which involves saving the whole processor state to memory and loading a new processor state...

0 Kudos
Message 2 of 8
(3,893 Views)
> think about the clock: every millisecond, the system gets interrupted only
> to
> increment a counter, 1000 times per second. think also about the thread
> context

OK, but in a clock routine you don't have declarations that can take a lot
of time such as:
int CVICALLBACK cb_MonostableOff(int panel, int control, int event,
void *callbackData, int eventData1, int eventData2) {
char Str[1024]; // And other time consuming declarations
switch (event) {
case EVENT_COMMIT:
// Do something with Str
break;
}
return 0;
}

I know understand that I need to move those declarations inside a block
inside the case if I don't want them declared hundreds of times per second !
--
Guillaume Dargaud
http://www.gdargaud.net/


0 Kudos
Message 3 of 8
(3,856 Views)

Guillaume Dargaud wrote:

char Str[1024]; // And other time consuming declarations


Why do you think that this local declaration takes a lot of time? In C, a local array is assigned off the stack simply by setting pointers to the appropriate values. As local variables are not initialised (in the release version), it makes no difference in speed if 2 or 20000 array elements are reserved in this way.

 

JR

0 Kudos
Message 4 of 8
(3,851 Views)

when compiled in release mode, the compiler is not supposed to perform any initialization on the variables. thus, declaring a variable consist in moving the stack pointer to allow some space on the stack to store the variable. since the compiler knows how many variable you declared in the block and how much space they takes, allocations in a block are done in one step which takes almost no time at all. note that, when calling a function, the stack pointer is also moved for parameter passing and for some register state preservation, so the call should be no longer with 1000 variables than with no variable at all.

 

on the other hand, when compiled in debug mode, every variable are initialized (aie aie !) and many variable access are checked. this is what makes a debug build so slow compared to a release build. 

 

(edit: it seems i am a bit slow to reply. jr_2005 said that before me, thanx mate)

Message Edited by dummy_decoy on 04-06-2009 11:03 AM
0 Kudos
Message 5 of 8
(3,848 Views)
> when compiled in debug mode, every variable are initialized (aie aie !)

I like that !
When you learn to swim with a lifebuoy, why would you want to take it off
when you head across the Atlantic ?!?

Can I force var inits in release mode ?
--
Guillaume Dargaud
http://www.gdargaud.net/


0 Kudos
Message 6 of 8
(3,821 Views)

> When you learn to swim with a lifebuoy, why would you want to take it off when you head across the Atlantic ?!?

 

because you don't need to swim anymore, since you took a boat. if you cannot cross the atlantic alone on your own, you do not even try it. same for software: for example, you do not use a software for handling 10 database queries per seconds to drive an application which runs 1000 database queries per seconds on average. use the right tool for the right job.

 

debug mode is only for debugging: variables are initialized (generally with obvious values like 0xCCCCCCCC or 0xDEADBEEF) because it allows for an easy catching of common errors, memory accesses are checked because it allows for an easy catching of pointer mismatche... your standard production software should be written in a way that do not need those safety barriers: you must not use uninitialized variables, you must not perform dangerous and unchecked pointer arithmetics. of course, this is a matter of compromise: some software abolutely needs to follow these rules (an airplane or an automated passenger train, for obvious reasons), others do not need at all (the fast-thrown test case you wrote to check the return value a function bleurk()), the vast majority lying between those 2 extremes.

 

to answer your question: yes, of course you can force var init in release mode. it involves writing an initializer for every variable (and good luck for initializing arrays). C has not been designed for this kind of software quality, so the solution is cumbersome and places all the burdden over the developper's shoulders, as always.

0 Kudos
Message 7 of 8
(3,816 Views)

Easy boys.

 

The CVI native compiler is based on the Princeton LCC compiler, which is an open source compiler that NI's had great fun fixing up with their debug capability which we have all grown to know and love over the years.

 

In release mode, the CVI/LCC compiler does a little better but it's still quite slow.  LCC does support some optimization, but it's not much.

 

The Microsoft VC++ compiler is much better if you use it as the release mode compiler.  VC++ does a better job of optimizing .

 

but, the gold standard of C/C++ compilers is the Intel C++ compiler for Windows (or linux, or unix or MacOS), called icl.

 

icl does a phenomenal job - it not only compiles way faster, the code produced is very much faster than LCC on either x86 CPU's or even AMD CPU's and it produces faster code than VC++ too.

 

I made a very large (millions of elements as I recall)  int array and  incremented each element in a loop and the Intel code was a full 75% faster than the CVI LCC code in release mode.  You can find metrics on this stuff on the Internet, LCC Vs. icl Vs VC++, Vs gcc etc etc.

 

icl will detect errors you never suspected were there - it does a very thorough job of checking your code - and it can do static analysis, auto-parallelization (splits loops into parts and schedules threads to do each part and merges the results), profiling, stack and buffer overflow analysis, CPU-specific optimization, etc. etc. etc. all for $600 for the pro version AND CVI has a built-in template for using it.

 

icl supports C99 too 😉  It runs on top of VC++ so you really need three compilers to make it work (!) - CVI, VC++, and the icl.  Well, for release mode you may not need the CVI compiler, but you need it for debug.

 

NI knows all of this quite well - that's why they offer the ability to use an optimizing compiler with CVI -  they've never claimed that the native compiler is fast or particularly efficient I don't think.  CVI refers to the Intel compiler in the documentation on optimizing compilers.

 

icl is well worth the money IMHO - the current release is 11.0 and they've bundled in several other tools with it.

 

It can't always overcome design issues by itself, but by using the profiler you can find "hot spots" in your code so that if you are bottle necked processing events or anything else you can detect it and fix it.

 

It may be that you don't care and can swim with the life buoy, but if you need the speed the icl can give it.

 

 

 

Menchar

Message Edited by menchar on 04-07-2009 06:51 PM
0 Kudos
Message 8 of 8
(3,788 Views)