From: Stefan Sperling Subject: Re: Optimized branch switching? To: Christian Weisgerber , gameoftrees@openbsd.org Date: Tue, 13 Sep 2022 13:17:19 +0200 On Tue, Sep 13, 2022 at 12:34:49PM +0200, Stefan Sperling wrote: > The attached profile trace graph suggests a bottleneck is in the open() > call in get_file_status(). We might be able to work around that somehow. This patch avoids the open() call in favour of lstat(); However, this does not improve performance. We spend 37% runtime in either open() or lstat(), so this patch makes no difference. I don't see how to make this code path faster by tweaking userland code. Disabling unveil() would make it faster, but we don't want to do that. diff /home/stsp/src/got commit - c9f38fbe5854f0986bfe240a76c72ca0e66b058b path + /home/stsp/src/got blob - 30e991da06f030404cbce64de63293d385ff1ac8 file + lib/worktree.c --- lib/worktree.c +++ lib/worktree.c @@ -1629,7 +1629,7 @@ get_file_status(unsigned char *status, struct stat *sb const struct got_error *err = NULL; struct got_object_id id; size_t hdrlen; - int fd = -1, fd1 = -1; + int fd = -1, fd1 = -1, have_file = 1; FILE *f = NULL; uint8_t fbuf[8192]; struct got_blob_object *blob = NULL; @@ -1646,36 +1646,28 @@ get_file_status(unsigned char *status, struct stat *sb */ if (dirfd != -1) { if (fstatat(dirfd, de_name, sb, AT_SYMLINK_NOFOLLOW) == -1) { - if (errno == ENOENT) { - if (got_fileindex_entry_has_file_on_disk(ie)) - *status = GOT_STATUS_MISSING; - else - *status = GOT_STATUS_DELETE; + if (errno != ENOENT) { + err = got_error_from_errno2("fstatat", abspath); goto done; - } - err = got_error_from_errno2("fstatat", abspath); - goto done; + } else + have_file = 0; } } else { - fd = open(abspath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); - if (fd == -1 && errno != ENOENT && - !got_err_open_nofollow_on_symlink()) - return got_error_from_errno2("open", abspath); - else if (fd == -1 && got_err_open_nofollow_on_symlink()) { - if (lstat(abspath, sb) == -1) - return got_error_from_errno2("lstat", abspath); - } else if (fd == -1 || fstat(fd, sb) == -1) { - if (errno == ENOENT) { - if (got_fileindex_entry_has_file_on_disk(ie)) - *status = GOT_STATUS_MISSING; - else - *status = GOT_STATUS_DELETE; + if (lstat(abspath, sb) == -1) { + if (errno != ENOENT) { + err = got_error_from_errno2("lstat", abspath); goto done; - } - err = got_error_from_errno2("fstat", abspath); - goto done; + } else + have_file = 0; } } + if (!have_file) { + if (got_fileindex_entry_has_file_on_disk(ie)) + *status = GOT_STATUS_MISSING; + else + *status = GOT_STATUS_DELETE; + return NULL; + } if (!S_ISREG(sb->st_mode) && !S_ISLNK(sb->st_mode)) { *status = GOT_STATUS_OBSTRUCTED; @@ -1727,6 +1719,12 @@ get_file_status(unsigned char *status, struct stat *sb err = got_error_from_errno2("openat", abspath); goto done; } + } else { + fd = open(abspath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); + if (fd == -1) { + err = got_error_from_errno2("open", abspath); + goto done; + } } f = fdopen(fd, "r");