Wednesday, October 26, 2005

With a little help from your compiler

GCC offers a plethora of extensions to the C language. Many of these extensions allow the programmer to communicate information--knowledge about the behavior or usage of functions, variables, and expressions--to the compiler, in hopes of the compiler generating more optimized code.

Many Linux programmers are unaware of GCC's bountiful extensions, but other barriers prevent their more wide-spread use: They are ugly and they generate non-portable (GCC-specific) code. With a single header file, however, the extensions can be beautified and made portable in one swoop. If only all relationships were that easy.

#if __GNUC__ >= 3
# define inline		inline __attribute__ ((always_inline))
# define __pure		__attribute__ ((pure))
# define __const	__attribute__ ((const))
# define __noreturn	__attribute__ ((noreturn))
# define __malloc	__attribute__ ((malloc))
# define __must_check	__attribute__ ((warn_unused_result))
# define __deprecated	__attribute__ ((deprecated))
# define __used		__attribute__ ((used))
# define __unused	__attribute__ ((unused))
# define __packed	__attribute__ ((packed))
# define likely(x)	__builtin_expect (!!(x), 1)
# define unlikely(x)	__builtin_expect (!!(x), 0)
#else
# define inline		/* no inline */
# define __pure		/* no pure */
# define __const	/* no const */
# define __noreturn	/* no noreturn */
# define __malloc	/* no malloc */
# define __must_check	/* no warn_unused_result */
# define __deprecated	/* no deprecated */
# define __used		/* no used */
# define __unused	/* no unused */
# define __packed	/* no packed */
# define likely(x)	(x)
# define unlikely(x)	(x)
#endif

With this header in hand, programmers may use simple, cute macros to harness the power of the GCC extensions. When compiling with a compiler other than GCC, or too old a version thereof, the symbols define away. Note that GLIB has many of these GCC extensions wrapped in its own convenience macros. GNOME developers may prefer to use those, but the discussion that follows is relevant no matter which macros one uses.

static inline void f (void) { ... }

The inline keyword specifies that the function body be copied into each call site. Such optimization saves function call overhead and allows for potential optimizations at the call site, as the compiler can remove unused code and optimize for constant values. If the function is also marked static and the function's address is never used, GCC will not output the actual function and thus the result is the same as a macro. Consequently, there is little reason to use macros in GCC--inline functions provide the same speed benefit, plus type checking. Despite what Gentoo users preach, function inlining should be used sparingly. The size of the function, number of call sites, and criticality of speed must all be taken into account. Function call overhead on the x86 architecture is very, very low.

__pure int f (void) { ... }

A "pure" function is one that has no effects except its return value and its return value is a function of only the function's parameters or non-volatile global variables. Any parameter or global variable access must be read-only. Loop optimization and subexpression elimination can be applied to such functions. A common example is strlen(): Given identical inputs, the function's return value (its only effect) is invariant across multiple invocations and thus can be pulled out of a loop and called but once.

__const int f (int x) { ... }

A "const" function is a stricter variant of a pure function: Such functions cannot access global variables and no parameters may be pointers. Thus their return value is a function of nothing but their passed-by-value parameters. Additional optimizations are possible for such functions. Math functions, such as abs(), are examples of const functions (presuming they don't save state or otherwise pull tricks in the name of optimization). It makes no sense for a const or pure function to return void.

__noreturn void f (void) { ... }

If a function never returns (perhaps because it calls exit()), it can be marked as such and GCC can optimize the call site without regard to the potentiality of the function actually returning. It makes no sense for such a function to have a return value other than void.

__malloc void * f (void) { ... }

If a function returns pointers that can never alias any other data (almost assuredly because it just allocated memory), the function can be marked as such and GCC can improve optimizations.

__must_check int f (void) { ... }

This attribute instructs GCC to generate a warning whenever the return value from the function is not stored or used in an expression during invocation. This allows functions whose return value is crucial to ensure that the value is always used.

__deprecated void f (void) { ... }

This attribute instructs GCC to generate a warning, at the call site, whenever the function is used. This helps developers wean off of deprecated interfaces.

static __used void f (void) { ... }

This attribute tells GCC that, despite apparent reality, a function really is used and to always output the assembly for the function. This is useful if the function is only invoked from assembly and GCC is unaware. It also disables warnings due to lack of use.

void f (int x __unused) { ... }

This attribute tells GCC that the programmer is aware that a given parameter is unused and not to emit warnings to that end. This is useful if compiling with -W or -Wunused but forced to have unused parameters, as is common in event-driven GUI programming.

struct __packed s { ... }

This attribute tells GCC that a type or variable should be packed into memory, using the minimum amount of space possible, potentially disregarding alignment requirements. If specified on a struct or union, all variables therein are so packed. If specified on just a specific variable, only that type is packed. As an example, a structure with a char followed by an int would most likely find the integer aligned to a memory address not immediately following the char (say, three bytes later). The compiler does this by inserting three bytes of unused packing between the two variables. A packed structure lacks this packing, potentially consuming less memory but failing to meet architecture alignment requirements.

if (unlikely (foo) && likely (bar)) { ... }

The likely() and unlikely() directives instruct GCC that the results of the expression contained within are likely true or unlikely true. GCC can then perform block reordering and other optimizations to improve the performance of conditional branches taken based on the results of these expressions. They should only be used if the result is overwhelmingly in one direction; for example, marking error conditions as unlikely().

Tuesday, October 25, 2005

ber-NANK-ee

I am not alone in my approval of President Bush's selection of Mr Bernanke as Federal Reserve Chairman. The news media, OpEd pieces, and the markets (stocks closed up, with the Dow showing a record six-month gain, although bonds were down) all support Mr Bernanke.

Mr Bernanke is surely qualified, with a long academic pedigree, a stint at The Fed, and chairmanship of the President's Council of Economic Advisors--a post where he gained both experience and the President's nod, without the partisan label that the Fed Chairman does not want. Indeed, President Bush decided well and confirmation will be easy.

I wrote yesterday that my only reservation with Mr Bernanke is his strong positive opinions on inflation-targeting. To be sure, transparency in the Fed is generally good and we should strive for such--to this end, Mr Greenspan has accomplished much, publicizing the Fed Funds Target Rate and distributing Fed Governor's meeting minutes earlier. Mr Bernanke will surely continue this trend; but inflation-targeting is much more than a simple matter of greater transparency.

The question is not whether or not the Fed should make public an inflation target, but whether they should have one at all. Locked into an explicit target, the Fed may find itself with less room to maneuver in a crisis. Certainly, Greenspan-style monetary policy decisions will be out and a more deterministic--dare I say that inflation-targeting makes monetary policy algorithmic?--and less instinctual application of policy shall ensue. One of Mr Greenspan's strongest attributes is his flexibility, his wide-angle lens view of the economy, and his deep understanding of markets. I do not know how much an explicit inflation target would have shackled him or made his knowledge inapplicable, but it could not have helped, and Mr Greenspan himself is against explicit targets. There is also the benefit of preemptive monetary policy, lacking the chance to hedge against and plan for, that sends the markets a strong message. Nonetheless, everything I have read from confidants deems Mr Bernanke a reasonable and accomodating man. Thus, combined with a clear need to continue Mr Greenspan's legacy, the new Fed Chairman will not be making unilateral policy decisions. In his own words, "my first priority will be to maintain continuity with the policies and policy strategies established during the Greenspan years."

President Bush additionally has two Fed Governor posts to fill. Choose wisely, and here's to a speedy confirmation.

Monday, October 24, 2005

Hard Act to Follow

As predicted, President Bush nominated Ben Bernanke to replace outgoing Fed Chief Greenspan.

Thus far, the Dow is up 121 points, NASDAQ 21 points, and the S&P 500 Index 14 points.

A New Maestro

Rumors just now surfacing suggest that President Bush is going to nominate Ben Bernanke to succeed Alan Greenspan as Federal Reserve Chairman.

With the exception of inflation-targeting, Mr Bernanke would get my vote.

We should know one way or the other later today.

Wednesday, October 12, 2005

Title of Post

I find my shoe laces untied more often than not these days and I am without explanation as to why.

Coming off the tail of summer, sandal weather, sun tanning my feet, the whole shoe and shoe lace thing is a tad bit annoying in its own right; give the laces a propensity for moving toward an untied state and the situation is downright unnerving.

Careful investigation--I called Mom, to make sure she correctly taught me how to tie shoe laces in the first place--and I suspect that the problem lies not in the tie, but in the lacing itself: I believe all of my shoes are mislaced.

They look fine, to be sure, but I don't think they are. Why else do they keep coming untied?

Anyhow, here I am, this is odd but this is me. I now find myself prepared to make the following offer: I need someone of the utmost shoe lacing experience to come into my home and lace and/or relace (as appropriate) all of my shoes (and possibly other items that require lacing). For some reason, I own a lot of shoes, so this job requires a lot of lacing--by nothing less than a bonafide shoe lacing expert.

Your shoe lacing experience must be documented and accompanied by several references. Serious inquiries only. Female applicants strongly preferred.

Sunday, October 9, 2005

Anarcho-syndicalism

At the GNOME Summit. Yesterday, Federico offered an interesting talk on performance, which spurred this thought: As processor speed increases, the time spent in I/O approaches 100% of total execution time, until all processes are fully I/O bound. A perhaps obvious observation, but one that highlights the importance of keeping our I/O in check.

We saw Noam Chomsky today on the street. Turning to my right, seeing him there, I could only muster a weak wave and think how Miguel would be jealous.

Monday, October 3, 2005