git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 4/9] index-helper: new daemon for caching index and related stuff

From
Eric Sunshine <sunshine@sunshineco.com>
Date
Jul 30, 2014, 08:08 UTC
Message-ID
<CAPig+cTDxTpo53WhfkQbt8EuY15Ttj1NHbh2Do-TKYq2xVvP+g@mail.gmail.com>
In-Reply-To
<1406548995-28549-5-git-send-email-pclouds@gmail.com>
On Monday, July 28, 2014, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:
Show 7 quoted lines
> Instead of reading the index from disk and worrying about disk
> corruption, the index is cached in memory (memory bit-flips happen
> too, but hopefully less often). The result is faster read.
>
> The biggest gain is not having to verify the trailing SHA-1, which
> takes lots of time especially on large index files. But this also
> opens doors for further optimiztions:
s/optimiztions/optimizations/
Show 7 quoted lines
>  - we could create an in-memory format that's essentially the memory
>    dump of the index to eliminate most of parsing/allocation
>    overhead. The mmap'd memory can be used straight away.
>
>  - we could cache non-index info such as name hash
>
> The shared memory's name folows the template "git-<object>-<SHA1>"
s/folows/follows/
Show 13 quoted lines
> where <SHA1> is the trailing SHA-1 of the index file. <object> is
> "index" for cached index files (and may be "name-hash" for name-hash
> cache). If such shared memory exists, it contains the same index
> content as on disk. The content is already validated by the daemon and
> git won't validate it again (except comparing the trailing SHA-1s).
>
> Git can poke the daemon to tell it to refresh the index cache, or to
> keep it alive some more minutes via UNIX signals. It can't give any
> real index data directly to the daemon. Real data goes to disk first,
> then the daemon reads and verifies it from there.
>
> $GIT_DIR/index-helper.pid contains a reference to daemon process (and
> it's pid on *nix). The file's mtime is updated every time it's accessed
s/it's pid/its pid/
Show 21 quoted lines
> (or should be updated often enough). Old index-helper.pid is considered
> stale and ignored.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
> diff --git a/index-helper.c b/index-helper.c
> new file mode 100644
> index 0000000..8fa0af9
> --- /dev/null
> +++ b/index-helper.c
> @@ -0,0 +1,157 @@
> +static void share_index(struct index_state *istate, struct index_shm *is)
> +{
> +       void *new_mmap;
> +       if (istate->mmap_size <= 20 ||
> +           hashcmp(istate->sha1,
> +                   (unsigned char *)istate->mmap + istate->mmap_size - 20) ||
> +           !hashcmp(istate->sha1, is->sha1) ||
> +           git_shm_map(O_CREAT | O_EXCL | O_RDWR, 0700, istate->mmap_size,
> +                       &new_mmap, PROT_READ | PROT_WRITE, MAP_SHARED,
> +                       "git-index-%s", sha1_to_hex(istate->sha1)) < 0)

Do any of these failure conditions deserve a diagnostic message to let the user know that there was a problem?

Show 32 quoted lines
> +               return;
> +
> +       free_index_shm(is);
> +       is->size = istate->mmap_size;
> +       is->shm = new_mmap;
> +       hashcpy(is->sha1, istate->sha1);
> +       memcpy(new_mmap, istate->mmap, istate->mmap_size - 20);
> +
> +       /*
> +        * The trailing hash must be written last after everything is
> +        * written. It's the indication that the shared memory is now
> +        * ready.
> +        */
> +       hashcpy((unsigned char *)new_mmap + istate->mmap_size - 20, is->sha1);
> +}
> diff --git a/read-cache.c b/read-cache.c
> index b679781..ff28142 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -1465,6 +1467,65 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
>         return ce;
>  }
>
> +/*
> + * Try to open and verify a cached shm index if available. Return 0 if
> + * succeeds (istate->mmap and istate->mmap_size are updated). Return
> + * negative otherwise.
> + */
> +static int try_shm(struct index_state *istate)
> +{
> +       void *new_mmap = NULL;
> +       size_t old_size = istate->mmap_size;

Is old_size needed? Can you not simply reference istate->mmap_size directly each place old_size is mentioned?

> +       ssize_t new_length;
Nit: 'size' vs. 'length' inconsistency in variable name choices.
Show 46 quoted lines
> +       const unsigned char *sha1;
> +       struct stat st;
> +
> +       if (old_size <= 20 ||
> +           stat(git_path("index-helper.pid"), &st))
> +               return -1;
> +       sha1 = (unsigned char *)istate->mmap + old_size - 20;
> +       new_length = git_shm_map(O_RDONLY, 0700, -1, &new_mmap,
> +                                PROT_READ, MAP_SHARED,
> +                                "git-index-%s", sha1_to_hex(sha1));
> +       if (new_length <= 20 ||
> +           hashcmp((unsigned char *)istate->mmap + old_size - 20,
> +                   (unsigned char *)new_mmap + new_length - 20)) {
> +               if (new_mmap)
> +                       munmap(new_mmap, new_length);
> +               poke_daemon(&st, 1);
> +               return -1;
> +       }
> +       munmap(istate->mmap, istate->mmap_size);
> +       istate->mmap = new_mmap;
> +       istate->mmap_size = new_length;
> +       poke_daemon(&st, 0);
> +       return 0;
> +}
> +
>  /* remember to discard_cache() before reading a different cache! */
>  int do_read_index(struct index_state *istate, const char *path, int must_exist)
>  {
> diff --git a/shm.c b/shm.c
> new file mode 100644
> index 0000000..4ec1a00
> --- /dev/null
> +++ b/shm.c
> @@ -0,0 +1,67 @@
> +#include "git-compat-util.h"
> +#include "shm.h"
> +
> +#ifdef HAVE_SHM
> +
> +#define SHM_PATH_LEN 72                /* we don't create very long paths.. */
> +
> +ssize_t git_shm_map(int oflag, int perm, ssize_t length, void **mmap,
> +                   int prot, int flags, const char *fmt, ...)
> +{
> +       va_list ap;
> +       char path[SHM_PATH_LEN];
Is there a reason to avoid strbuf here?
Show 29 quoted lines
> +       int fd;
> +
> +       path[0] = '/';
> +       va_start(ap, fmt);
> +       vsprintf(path + 1, fmt, ap);
> +       va_end(ap);
> +       fd = shm_open(path, oflag, perm);
> +       if (fd < 0)
> +               return -1;
> +       if (length > 0 && ftruncate(fd, length)) {
> +               shm_unlink(path);
> +               close(fd);
> +               return -1;
> +       }
> +       if (length < 0 && !(oflag & O_CREAT)) {
> +               struct stat st;
> +               if (fstat(fd, &st))
> +                       die_errno("unable to stat %s", path);
> +               length = st.st_size;
> +       }
> +       *mmap = xmmap(NULL, length, prot, flags, fd, 0);
> +       close(fd);
> +       if (*mmap == MAP_FAILED) {
> +               *mmap = NULL;
> +               shm_unlink(path);
> +               return -1;
> +       }
> +       return length;
> +}
Previous: Nguyễn Thái Ngọc DuyNext: Duy Nguyen
Message 6 of 13 in “Speed up cache loading time”
  1. 0/9 Speed up cache loading timeNguyễn Thái Ngọc Duy, Jul 28, 2014
  2. 1/9 trace.c: add GIT_TRACE_PACK_STATS for pack usage statisticsNguyễn Thái Ngọc Duy, Jul 28, 2014
  3. 2/9 read-cache.c: fix constness of verify_hdr()Nguyễn Thái Ngọc Duy, Jul 28, 2014
  4. 3/9 read-cache: allow to keep mmap'd memory after readingNguyễn Thái Ngọc Duy, Jul 28, 2014
  5. 4/9 index-helper: new daemon for caching index and related stuffNguyễn Thái Ngọc Duy, Jul 28, 2014
  6. Eric SunshineJul 30, 2014
  7. Duy NguyenJul 30, 2014
  8. David TurnerJul 31, 2014
  9. 5/9 trace.c: add GIT_TRACE_INDEX_STATS for index statisticsNguyễn Thái Ngọc Duy, Jul 28, 2014
  10. 6/9 index-helper: add --strictNguyễn Thái Ngọc Duy, Jul 28, 2014
  11. 7/9 daemonize(): set a flag before exiting the main processNguyễn Thái Ngọc Duy, Jul 28, 2014
  12. 8/9 index-helper: add --detachNguyễn Thái Ngọc Duy, Jul 28, 2014
  13. 9/9 index-helper: add Windows supportNguyễn Thái Ngọc Duy, Jul 28, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.