SBCL 1.0.55 x64 needs GLIBC 2.14

It installed on my Ubuntu 11.10 (Oneiric) laptop, but when I tried to run it, I got this message:

sbcl: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by sbcl)

Hmmm. Let’s see..

# ls -al /lib/x86_64-linux-gnu/libc.so.6
lrwxrwxrwx 1 root root 12 2012-03-06 21:17 /lib/x86_64-linux-gnu/libc.so.6 -> libc-2.13.so

Argh.

This has already been reported in the SBCL bug database.

My workaround was to grab 1.0.54 from the old file releases section on SBCL’s sourceforge site. That worked fine. So you’ll need to downgrade if you want to use the 64 bit version.

This came up when I ran into problems installing cl-libxml2 using quicklisp. The x86 version of SBCL throws an error when using cffi to load the Ubuntu-packaged libxml2 library, because it expects a 32-bit version of the library but finds a 64-bit one instead (I neglected to copy the error message, but it’s something about finding an unexpected/wrong class ELFCLASS64).

So I suspect anyone who has a x64 system that uses cffi to access libraries in this manner will run into the same problem with SBCL 1.0.55.

On a side note, I can’t imagine installing and managing Common Lisp libraries without quicklisp. It took a few seconds to do what would probably take a beginner like me hours to figure out. Awesome tools like that make a huge difference to newcomers who want to get up and running with CL without a lot of pain.

* * *

UPDATE: This is fixed in 1.0.56.

Installing DBI on Leopard’s perl 5.8.8

I needed to get my perl installation updated to do some development locally. As usual, perl was a pain in the ass. Long story short: Install Xcode 3.0, copy the “reentr.inc” file from the 5.8.8 source distribution, and DBI should install.

Below is the long-winded log of my woes, offered in the hopes it might help someone.

First, DBI 1.604 wouldn’t install via cpan, so I tried installing it by hand. But I just got the same error when running “make”:

No rule to make target `/System/Library/Perl/5.8.8/darwin-thread-multi-2level/CORE/config.h', needed by `Makefile'.

I found this blog post, “Leopard Perl 5.8.8 installation throws errors when compiling (makefile)” mentioning the exact message, which recommended copying the CORE directory from 5.8.6 instead the above location. I tried that, but then I got this error instead:

DBI.xs: In function ‘dbi_profile’:
DBI.xs:2398: warning: implicit declaration of function ‘GvSVn’
DBI.xs:2398: error: invalid lvalue in assignment
DBI.xs: In function ‘dbi_profile’:
DBI.xs:2398: warning: implicit declaration of function ‘GvSVn’
DBI.xs:2398: error: invalid lvalue in assignment
DBI.xs: In function ‘XS_DBI_dispatch’:
DBI.xs:2970: warning: assignment makes pointer from integer without a cast
DBI.xs:2972: error: invalid lvalue in assignment
DBI.xs:2985: error: invalid type argument of ‘->’
DBI.xs:2989: error: invalid lvalue in assignment
DBI.xs:3293: warning: unused variable ‘Perl___notused’
DBI.xs: In function ‘XS_DBI_dispatch’:
DBI.xs:2970: warning: assignment makes pointer from integer without a cast
DBI.xs:2972: error: invalid lvalue in assignment
DBI.xs:2985: error: invalid type argument of ‘->’
DBI.xs:2989: error: invalid lvalue in assignment

Googling these error messages turned up surprisingly little. On another blog with a post titled, “Mac OS 10.5: Leopard” that mentioned difficulties with DBI, commenters suggested various solutions, but none of them worked for me. The blog author got an older version of DBI to install but I couldn’t get that to work either.

I discovered that Xcode 3.0 (developer tools for Leopard) contains the 5.8.8 files that belong in that CORE directory. This seemed like a better option than copying the probably outdated 5.8.6 files. You can get the gigantic Xcode disk image, a whopping 1.1 gigabytes, from the Apple Developer Connection site. Registration is required through the “Member” link, and once you’re in, go to Downloads and search for Xcode.

Before installing Xcode, I cleared out the hosed CORE directory I’d been mucking with. “DeveloperTools.pkg” is what contains the perl headers, so you can probably get away with just installing that (double-click it), instead of the entire XcodeTools.pkg. It did the trick: the compiler was now finding the “GvSVn” symbol it couldn’t before. But now I got this message during make:

In file included from DBIXS.h:19,
from Perl.xs:6:
/System/Library/Perl/5.8.8/darwin-thread-multi-2level/CORE/perl.h:3993:22: error: reentr.inc: No such file or directory
In file included from DBIXS.h:19,
from Perl.xs:6:
/System/Library/Perl/5.8.8/darwin-thread-multi-2level/CORE/perl.h:3993:22: error: reentr.inc: No such file or directory
lipo: can't open input file: /var/tmp//ccQ8vbDU.out (No such file or directory)
make: *** [Perl.o] Error 1

In desperation, I downloaded the perl 5.8.8 source distribution tarball, and simply copied reentr.inc into the CORE directory. Voila! Make went to completion and I could install the module. From there, I went back into cpan to install DBD::mysql without any problems (you need mysql installed in the default location, /usr/local/mysql, of course).

The Inexact Science of Optimizing MySQL

The past week or so, I’ve been playing database administrator: monitoring load, examining the log for slow queries, tweaking parameters, rewriting queries, adding indexes, and repeating the cycle over and over again. It’s a tedious, time-consuming, and exhausting process.

Tuning is tricky because inefficiencies aren’t always immediately apparent, and there may be uncontrollable factors affecting performance in VPS environments. Here are some things I’ve learned or had to refresh myself about with respect to tuning MySQL.

Don’t assume anything about why queries are slow. Under high load, a lot of queries can pop up in the slow query log just because the database is working hard. It doesn’t necessarily mean every query needs optimization. Try to look for patterns, and expect to spend time reviewing queries that are already optimized.

Look for strange queries. Don’t recognize it? Well, maybe it shouldn’t be there. I found an expensive query for a website feature that was obsolete months ago; it was being made even though the data wasn’t being used or displayed anywhere.

EXPLAIN is your friend. Interpreting the output makes my head pound sometimes, but it’s absolutely necessary. Invest the time and effort to understand it.

Multi-column indexes are a necessary evil. Most tables I was examining had only single-column indexes, causing complex WHERE clauses and/or ORDER BY to do costly “Using temporary; Using filesort” operations. Adding a few multi-column indexes helped a great deal. In general, I dislike multi-column indexes because they require maintenance: if you modify a complex query, you might have to add or change the index, or it will become slow as molasses. But unfortunately, that’s the tradeoff for performance.

The “same” query can behave differently with different datasets. A query can sometimes use an index, and sometimes use a filesort, depending, for example, on constants in the WHERE clause. Be sure to use EXPLAIN with different values.

Give the query optimizer hints. Disk access is slow, especially on the VPS, so I wanted to avoid filesorts at all costs. Using STRAIGHT_JOIN forced MySQL to process an indexed table first; otherwise, it believed that a filesort would be faster in some cases. It might be, sometimes–but if you think you know better, use the hint.

Disk access on a VPS can be wonky. It depends a lot on what else is happening on the hardware node. This relates somewhat to the previous point: all other things being equal, MySQL could be right about a filesort being faster than an index. But it’s usually not the case in an environment where disk I/O is very costly.

Reduce the number of joins wherever possible. It doesn’t seem like a few indexed joins into “lookup” tables (basically key-value types of things) would affect performance that much, but amazingly, it can. Really. Break up queries into smaller, simpler ones if at all possible.

Run ANALYZE TABLE and OPTIMIZE TABLE. The manual says you don’t typically need to run these commands, but I found frequently updated tables benefit from this maintenance, even if they have only a few thousand records.

Work iteratively. Somtimes performance problems are localized to one or two spots, but more often, inefficiencies are spread out over a lot of queries; they may become noticeable only after several passes, as server conditions fluctuate. Discovering these problem areas takes a lot of patience.

Up and Running

This domain is being served from a slicehost.com VPS account, which I’m sharing with my friend Danny. We spent a few hours installing a typical LAMP environment from Debian packages. It all went smoothly; we’re pretty much set up. Eventually, we’ll get around to putting actual content up on our respective domains, but we expect traffic and load to remain very light. So we spent most of our time dealing with the main resource limit on our “box”: memory.

There’s lots of information available on various optimizing strategies for Apache and MySQL, but it basically boiled down to 2 things for us. In Apache, we lowered the number of start/max/min servers, and loaded only modules we needed. In MySQL, we decreased the sizes of various buffers and queues, and also disabled InnoDB support. The latter alone changed the initial size of MySQL from 20 megs of resident memory to 9 megs! I’m sure we’ll continue to tweak later on, but memory usage seems fairly reasonable right now for what we’re running.

It’s funny to reflect on how far open source software has come in general. I remember talking nine years ago with some corporate guy in New York about a piece of open source he promptly dismissed as “not ready for the enterprise” (that phrase always makes me laugh. Whose enterprise, exactly? Mine?). Back then, it was common to hear disparaging stuff like that all the time.

And now–is there anything that’s NOT enterprise ready?! Maybe the suits are happy, but I’m not sure everyone else has benefitted. As the software has grown in scalability, performance, and features, the requirements have also increased drastically. And that means the bar is higher for even a fairly standard LAMP environment, for example. Default installs of Apache, MySQL and PHP can be real memory hogs.

I’ve been discovering a few interesting alternative projects with lighter feature sets. lighttpd and thttpd are both high-performance, small-foot web servers. And a lot of folks seem to be looking to SQLite if they don’t need the fancier features of a complex RDBMS. Maybe I will experiment with these at some point.