MySQL Internals Manual  /  ...  /  Additional Suggestions

2.1.7 Additional Suggestions

  • Try to write code in a lot of black boxes that can be reused or at least use a clean, easy to change interface.

  • Reuse code; There are already many algorithms in MySQL that can be reused for list handling, queues, dynamic and hashed arrays, sorting, etc.

  • Use the my_* functions like my_read()/my_write()/ my_malloc() that you can find in the mysys library, instead of the direct system calls; This will make your code easier to debug and more portable.

  • Use libstring functions (in the strings directory, declared in include/m_string.h) instead of standard libc string functions whenever possible.

  • Try to always write optimized code, so that you don't have to go back and rewrite it a couple of months later. It's better to spend 3 times as much time designing and writing an optimal function than having to do it all over again later on.

  • Avoid CPU wasteful code, even when its use is trivial, to avoid developing sloppy coding habits.

  • If you can do something in fewer lines, please do so (as long as the code will not be slower or much harder to read).

  • Do not check the same pointer for NULL more than once.

  • Never use a macro when an (inline) function would work as well.

  • Do not make a function inline if you don't have a very good reason for it. In many cases, the extra code that is generated is more likely to slow down the resulting code than give a speed increase because the bigger code will cause more data fetches and instruction misses in the processor cache.

It is okay to use inline functions are which satisfy most of the following requirements:

    • The function is very short (just a few lines).

    • The function is used in a speed critical place and is executed over and over again.

    • The function is handling the normal case, not some extra functionality that most users will not use.

    • The function is rarely called. (This restriction must be followed unless the function translates to fewer than 16 assembler instructions.)

    • The compiler can do additional optimizations with inlining and the resulting function will be only a fraction of size of the original one.

  • Think assembly - make it easier for the compiler to optimize your code.

  • Avoid using malloc(), which is very slow. For memory allocations that only need to live for the lifetime of one thread, use sql_alloc() instead.

  • All functions that can report an error (usually an allocation error), should return 0/FALSE/false on success, 1/TRUE/true on failure. Other return values should go in an output argument. If you have a predicate function which returns bool, and cannot fail, document that fact clearly (in the header file). Recommendation when writing new code: use return type int, to distinguish from predicate functions. Returning true on error, allows us to write:

if (a() || b() || c())
  error("something went wrong");

However, short-circuit evaluation like that above is not the best method for evaluating options.

  • Beware of truncation when returning TRUE/true to indicate an error:

my_bool foo(int val)      { return val; } /* Bad. */
int     foo(longlong val) { return val; } /* Bad. */
my_bool foo(int val)      { return test(val); } /* Good. */
int     foo(longlong val) { return test(val); } /* Good. */
  • Using goto is okay if not abused.

  • If you have an 'if' statement that ends with a 'goto' or 'return' you should NOT have an else statement:

if (a == b)
  return 5;
else return 6;


if (a == b)
  return 5;
return 6;
  • Avoid default variable initializations. Use LINT_INIT() if the compiler complains after making sure that there is really no way the variable can be used uninitialized.

  • In C code, use TRUE and FALSE rather than 1/0

  • In C++ code, it is OK to use true and false (do not use 1/0). You can use C++ bool/true/false when calling C functions (values will be safely promoted to my_bool).

  • bool exists only in C++. In C, you have to use my_bool (which is char); it has different cast rules than bool:

int c= 256*2;
bool a= c;          /* a gets 'true' */
my_bool b= c;       /* b gets zero, that is, 'false': BAD */
my_bool b= test(c); /* b gets 'true': GOOD */
  • Do not instantiate a class if you do not have to.

  • Use pointers rather than array indexing when operating on strings.

  • Never pass parameters with the &variable_name construct in C++. Always use a pointer instead!

The reason is that the above makes it much harder for the one reading the caller function code to know what is happening and what kind of code the compiler is generating for the call.

  • Do not use the %p marker of printf() (fprintf(), vprintf(), etc) because it leads to different outputs (for example on some Linux and Mac OS X the output starts with 0x while it does not on some Solaris). In MySQL 5.5 and later, use my_vsnprint, DBUG_PRINT with %p for pointer formatting consistent across different platforms. In earlier versions, use printf-family functions with 0x%lx, but beware it truncates pointers on 64-bit Windows. Being sure that there is always 0x enables us to quickly identify pointer values in the DBUG trace.

  • Relying on loop counter variables being local to the loop body if declared in the for statement is not portable. Some compilers still don't implement this ANSI C++ specification. The symptom of such use is an error like this:

c-1101 CC: ERROR File =, Line = 187
  "i" has already been declared in the current scope.

    for (int i= 0; i < num_sockets; i++)

Download this Manual
EPUB - 0.8Mb
User Comments
Sign Up Login You must be logged in to post a comment.