[Date Prev][Date Next] [Chronological] [Thread] [Top]

common pessimization: ber_mem*_x(...,NULL)

The OpenLDAP code is a bit too clever sometimes.  If someone has too
much time on their hands, it could be useful to look for places where
the code tries and fails to be more clever than the compiler, and
simplify that.

E.g. compilers are commonly very good at optimizing array operations -
i.e. when a function takes a pointer which it *does not modify* and
walks an index up and down the pointed-to array.  However once the
function starts doing pointer games, a number of compilers seem to be
scared away from array optimizations and instead just do plain pointer

Another example:

OpenLDAP has a fair number of calls like ber_memfree_x(ptr, NULL) which
I guess is intended as an optimization - it avoids the ber_memfree(ptr)
wrapper call.  Actually that's a pessimization if liblber/memory.c is
optimized to inline ber_memfree_x() into ber_memfree(): ber_memfree_x()
cannot be optimized on ctx==NULL.

For an optimization, assuming it makes any difference, it would make
more sense remove the _x from the call and inline by hand some of the
ber_*_x() functions in memory.c.
gcc even has some builtins that can be use to turn ber_foo_x(bar,NULL)
calls into ber_foo(bar).  Someething like this:
  #ifdef __GNUC__
  # define ber_memfree_x(ptr, ctx) \
	((__builtin_constant_p(ctx) && ((ctx) == NULL)) \
	 ? ber_memfree(ptr) : (ber_memfree_x)(ptr, ctx))
That'll also help code like this:
  void foo(void *bar)              { foo_x(bar, NULL); }
  void foo_x(void *bar, void *ctx) { ber_memfree_x(bar, ctx); }
If foo_x() is into foo(), that will turn ber_memfree_x into ber_memfree.