Performance improvements on distributed file systems#43
Conversation
This speeds up indexing and is useful when you don't care about xattr or ACL metadata, and is especially effective on distributed network file system mounts like GlusterFS, where each such syscall is a network roundtrip. Signed-off-by: Niklas Hambüchen <mail@nh2.me>
scandir() is a generator, so this makes bup index have getdents() and stat() syscalls interleaved just like `ls` and `rsync` do. Many file systems have optimisations for doing stat() on the results of getdents(); especially on networked file systems this can make a big performance difference. On GlusterFS, this change, together with turning off metadata (previous commit) results in a ~20x speedup of bup index. Signed-off-by: Niklas Hambüchen <mail@nh2.me>
Python < 3.6 thinks it's signed when in fact it's unsigned. This blows up in bup when scandir() is used on systems with large inodes (such as glusterfs). Signed-off-by: Niklas Hambüchen <mail@nh2.me>
Signed-off-by: Niklas Hambüchen <mail@nh2.me>
|
Thanks for the help. In accordance with HACKING I've redirected this pull request to the list for discussion: https://groups.google.com/d/msg/bup-list/SNNxvGtFtaA/j38p7jmcAgAJ |
| scandir = None | ||
| try: | ||
| # scandir allows much faster directory traversals, but is | ||
| # only included in the stanard library from Python 3.3 upwards. |
| # only included in the stanard library from Python 3.3 upwards. | ||
| import scandir | ||
| except ImportError: | ||
| log('Warning: scandir support missing; install python-scandir' |
There was a problem hiding this comment.
not really sure it's worth it ... after all, people who have happily been using bup would not really care too much, and there's no way to suppress this other than to actually install it ... that's a bit annoying?
OTOH, I guess there's precedent for it since we do similar things with xattr
However, then again, python 3.5 has os.scandir() with all the performance improvements incorporated, I think, so maybe just use that instead of the extra library?
| # We need to use xstat instead of entry.stat() because | ||
| # entry.stat() uses Python's normal floating-point mtimes. | ||
| st = xstat.lstat(n) | ||
| yield (n,st) |
There was a problem hiding this comment.
nit: maybe add a space after the , in the tuple
| except OSError as e: | ||
| add_error(Exception('%s: %s' % (resolve_parent(n), str(e)))) | ||
| continue | ||
| for (n,st) in _filename_stat_generator('.'): |
| for n in os.listdir(path): | ||
| try: | ||
| st = xstat.lstat(n) | ||
| yield (n,st) |
| st = xstat.lstat(n) | ||
| yield (n,st) | ||
| except OSError as e: | ||
| add_error(Exception('%s: %s' % (resolve_parent(n), str(e)))) |
There was a problem hiding this comment.
this is strange - you copied it from the one place that was already weird, with the Exception() think? normally add_error just takes a string
| st = xstat.lstat(n) | ||
| yield (n,st) | ||
| except OSError as e: | ||
| add_error(Exception('%s: %s' % (resolve_parent(n), str(e)))) |
| try: | ||
| st = xstat.lstat(n) | ||
| except OSError as e: | ||
| add_error(Exception('%s: %s' % (resolve_parent(n), str(e)))) |
There was a problem hiding this comment.
yeah here was the odd use you removed ...
| # https://github.com/python/cpython/commit/0f6d73343d342c106cda2219ebb8a6f0c4bd9b3c | ||
| # | ||
| # To work around it, any `st_ino` as obtained from `os.stat()` | ||
| # should be cast to unsigned using `thestat.st_ino & INO_FIX`. |
There was a problem hiding this comment.
wouldn't it make more sense to use it like a function?
ino_fix(st_ino)
and in the uncommon cases,
st_ino = ino_fix(st_ino)
Here are 4 patches that I've been using in the past 8 months to dramatically speed up bup when run against a distributed file system like GlusterFS (and actually makes it possible to use it in such scenarios).
I've shortly discussed them on the bup IRC channel in the past.
Please see the commit descriptions for details.
The use of
scandirand the fix forst_inoare reasonably well tested (over thousands of bup runs), theno-nonstat-metadataflag has not been tested as extensively.One question:
Right now, when I run
make teston Ubuntu 16.04, it fails with:This is because I'm emitting the
Warning: scandir support missing; install python-scandir to speed up directory traversalswhen scandir couldn't be found. I think having this warning is good because scandir really helps a huge deal with performance.But Ubuntu 16.04 doesn't have
python-scandiravailable, only >= 17.10 has it.(How) should I modify the two failing tests so that they ignore if this warning is emitted?
Thanks!