repo/checkout: Cache lookups of dirmeta objects

I was reading a strace the other day and noticed we were loading the same
`.dirmeta` object many times. Unlike the other object types, `.dirmeta` objects
don't accumulate much over time; there are only so many directory metadata types.
(Without SELinux involved it'd probably be 5-6 I'd guess offhand).

For `fedora-atomic/25/x86_64/docker-host` there are currently 34 `.dirmeta` in
the tree.

But how many times during a checkout did we load those 34 dirmeta objects?
With a quick strace:

```
$ strace -s 2048 -f -o strace.log ostree --repo=repo-build checkout -U fedora-atomic/25/x86_64/docker-host host-test-checkout
$ grep dirmeta strace.log | wc -l
7165
```

After, as you'd expect, we just loaded `34` from disk.  We do
6 system calls (`openat+fstat+fstat+read+read+close`) per dirmeta,
so we dropped a total of 42780 system calls - which is about 20% of the total
system calls made.

`perf record` tells me that we're spending ~40 of our time in the kernel during
a checkout, so reducing syscall traffic helps. Though most of that appears to be
in the VFS and XFS layers for `linkat` (which isn't surprising).

So how much did perf improve? Well, on my workstation, I get a lot of
fluctuation in timing, sometimes by 30%, so this was well within the noise. But
it's well worth speeding up checkout, and I think this optimization will shine
more as we improve performance elsewhere.

Closes: #795
Approved by: jlebon
This commit is contained in:
Colin Walters authored and Atomic Bot committed 2017-04-25 13:40:53 +00:00
1 parent 4fc65b808a
commit b7afe91e21
3 files changed
+85

No files matched your search

+4
View File
@@ -799,6 +799,8 @@ ostree_repo_checkout_tree (OstreeRepo *self,
/* Backwards compatibility */
options.enable_uncompressed_cache = TRUE;
g_auto(OstreeRepoMemoryCacheRef) memcache_ref;
_ostree_repo_memory_cache_ref_init (&memcache_ref, self);
return checkout_tree_at (self, &options,
AT_FDCWD, gs_file_get_path_cached (destination),
source, source_info,
@@ -916,6 +918,8 @@ ostree_repo_checkout_at (OstreeRepo *self,
if (!target_info)
return FALSE;
g_auto(OstreeRepoMemoryCacheRef) memcache_ref;
_ostree_repo_memory_cache_ref_init (&memcache_ref, self);
if (!checkout_tree_at (self, options,
destination_dfd,
destination_path,