Skip to content

Commit

Permalink
Use glibc version in ruby_platform cache header if available
Browse files Browse the repository at this point in the history
Previously, the `ruby_platform` header in the cache was calculated as a
hash of the `RUBY_PLATFORM` (e.g. x86_64-linux-gnu) with the `uname -v`
output (e.g. `#75-Ubuntu SMP Tue Oct 1 05:24:09 UTC 2019`).

However, using `uname -v` is a bit restrictive on Linux systems. It
makes it difficult for a containerized application to bundle the
Bootsnap cache with the application itself. For example, in Docker, the
host operating system determines the kernel version, so even though a
Docker image may be built with a specific base image, the output of
`uname -v` will change depending on where it's run. As a result, the
application will need to rebuild the Bootsnap cache every time unless a
persistent volume is used AND the kernel version is fixed. However, both
requirements can be difficult to guarantee, which negates any speed-up
that Bootsnap provides.

We observe that in a Linux system, the application binary interface
(ABI) is defined by the kernel version and glibc version. A change in
the kernel ABI requires a change to glibc. Instead of hashing the output
of `uname -v`, we hash the glibc version if it is defined by the
compiler.
  • Loading branch information
stanhu committed Jan 11, 2020
1 parent 224e770 commit 0de36ee
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.jp.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ close n
Bootsnap は、64バイトのヘッダーとそれに続くキャッシュの内容を含んだキャッシュファイルを書き込みます。ヘッダーは、次のいくつかのフィールドで構成されるキャッシュキーです。

- `version`、Bootsnapにハードコードされる基本的なスキーマのバージョン
- `ruby_platform``RUBY_PLATFORM`(x86_64-linux-gnuなど)変数とOSバージョンのハッシュ(Linux、BSD、macOSでは` uname -v`
- `ruby_platform``RUBY_PLATFORM`(x86_64-linux-gnuなど)変数とglibcバージョン(Linuxの場合)またはOSバージョン(BSD、macOSの場合は` uname -v`のハッシュ
- `compile_option``RubyVM::InstructionSequence.compile_option` の返り値
- `ruby_revision`、コンパイルされたRubyのバージョン
- `size`、ソースファイルのサイズ
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ Bootsnap writes a cache file containing a 64 byte header followed by the cache c
is a cache key including several fields:

* `version`, hardcoded in bootsnap. Essentially a schema version;
* `ruby_platform`, A hash of `RUBY_PLATFORM` (e.g. x86_64-linux-gnu) variable and OS version (`uname -v` on Linux, BSD, macOS)
* `ruby_platform`, A hash of `RUBY_PLATFORM` (e.g. x86_64-linux-gnu) variable and glibc version (on Linux) or OS version (`uname -v` on BSD, macOS)
* `compile_option`, which changes with `RubyVM::InstructionSequence.compile_option` does;
* `ruby_revision`, the version of Ruby this was compiled with;
* `size`, the size of the source file;
Expand Down
6 changes: 6 additions & 0 deletions ext/bootsnap/bootsnap.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#ifndef _WIN32
#include <sys/utsname.h>
#endif
#ifdef __GLIBC__
#include <gnu/libc-version.h>
#endif

/* 1000 is an arbitrary limit; FNV64 plus some slashes brings the cap down to
* 981 for the cache dir */
Expand Down Expand Up @@ -236,6 +239,9 @@ get_ruby_platform(void)

#ifdef _WIN32
return (uint32_t)(hash >> 32) ^ (uint32_t)GetVersion();
#elif defined(__GLIBC__)
hash = fnv1a_64_iter(hash, gnu_get_libc_version());
return (uint32_t)(hash >> 32);
#else
struct utsname utsname;

Expand Down

0 comments on commit 0de36ee

Please sign in to comment.