Moving to C++ presents opportunities for higher programmer productivity. The requirements of embedded systems, however, demand that the adoption of C++ be carefully measured for the performance impact of run-time costs present in C++, but not in C. This talk suggests strategies for developers who are starting their acquaintance with C++.
Using C++ Efficiently
In
Embedded Applications
César A QuirozMentor Graphics, Embedded Software Division
Abstract. Moving to C++ presents opportunities for higher programmerproductivity. The requirements of embedded systems, however,demand that the adoption of C++ be carefully measured for theperformance impact of run-time costs present in C++, but not in C.This talk suggests strategies for developers who are starting theiracquaintance with C++.
This talk is aimed at embedded systems developers who are considering the adoption of C++[BS97] intheir projects. The material assumes professional acquaintance with embedded development, and with alanguage in the general class of ANSI/ISO C[C90]. On the other hand, not much knowledge of C++ ispresumed. This talk is meant, therefore, for engineers tackling their first embedded system developmentprojects in C++.There are good reasons for using C++ to implement an embedded system, for instance:. C++ compares favorably with C (the leading alternative) in matters of syntactic convenience, compile-time type-checking, memory allocation and initialization, and code reuse through derivation,. The newly approved Draft Standard for C++ ends a long period of uncertainty about the ultimate shapeof the language. Conforming implementations are gradually turning up. Within a couple of years, weshould find that most implementations are fully conforming.On the other hand, there are corresponding reasons for caution, too:. C++ (plus its libraries) is a larger, more complex, language than C (its libraries included). A developerwho has a good understanding of the consequences of employing this or that C feature may be misledwhen evaluating outwardly similar features in C++,. The long gestation period of the C++ standard has promoted a drift in implementation. The meaningof a C++ program (never mind its performance) does depend on what compiler it was meant for.I assume here that the decision of adopting C++ has been made already, and that the development team isevaluating which C++ features will be appropriate for the project at hand.
Feature Cost EvaluationIf we could give for sure advice of the form "Embedded developers should never use feature XYZ" thenthis talk would not be needed. Such generalities are normally obvious (obviously right or obviouslywrong), but unlikely to be correct enough to use in real situations.1Evaluating a "feature", whatever we mean by that , has to be always a qualified proposition. Using afeature may be a clear win for some projects, but not for others; it will depend on the cost of the featurerelative to the project's needs and constraints.This sort of evaluation is uncertain because it depends on how much the feature buys us, how much it takesaway from our budget, and (not the least) because different implementations cost differently.For instance, consider the implementation of potentially unaligned accesses on processors (like most RISCcpus) where unaligned access triggers an exception[PPC].An example could be this function:int fetch_from( void *p ){ return *(int *)p; // what if 'p' points to an odd address?}
where we may be requested to obtain an integer from a non-int-aligned address. This could be needed, forone case, if we had to extract information from a message format that had been designed withoutconsideration for this problem.The implementation could deal with this sort of access in a number of ways; two extreme ones are worthcomparing. One is pessimistic (and normally inefficient), the other optimistic (and sometimes fast).The implementation may decide that such accesses need to be performed by fetching bytes one at a time toensure correct alignment. In effect, the return statement would mutate into something like:{ int tmp;char *dst = (char *)&tmp;char *src = (char *)p;while (dst < (char *)&tmp + sizeof(int)) *dst++ = *src++;return tmp;}
This, although legal, is likely to be inefficient always, as it dooms aligned accesses to the same treatment.On the other hand, the implementation could be optimistic, in whose case the fetch through the argumentpointer would be implemented directly as a word load, betting that the pointer points to a well-alignedinteger. Because this implementation would trigger exceptions whenever it loses its bet, it would be part ofits duty to supply an exception handler to correct the trapped accesses transparently.Deciding between these two decisions isn't t... [download for more]