diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-03 17:31:59 -0500 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2016-04-04 17:27:10 -0700 |
commit | 2d760a7bff71c46c5aeba37c40d236ea16eefea2 (patch) | |
tree | 31520cecba5722150f8cddfcf627351ea1257f4f /subsurface-core/save-git.c | |
parent | 2b36091599cbc51474e103f14037e5ac44215cf3 (diff) | |
download | subsurface-2d760a7bff71c46c5aeba37c40d236ea16eefea2.tar.gz |
Don't write back dive data that hasn't changed in git
This caches the git ID for the dive on load, and avoids building the
dive directory and hashing it on save as long as nothing has invalidated
the git ID cache.
That should make it much faster to write back data to the git
repository, since the dive tree structure and the divecomputer blobs in
particular are the bulk of it (due to all the sample data). It's not
actually the git operations that are all that expensive, it's literally
generating the big blob with all the snprintf() calls for the data.
The git save used to be a fairly expensive with large data sets,
especially noticeable on mobile with much weaker CPU's. This should
speed things up by at least a factor of two.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'subsurface-core/save-git.c')
-rw-r--r-- | subsurface-core/save-git.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/subsurface-core/save-git.c b/subsurface-core/save-git.c index 693abb623..e22019ab0 100644 --- a/subsurface-core/save-git.c +++ b/subsurface-core/save-git.c @@ -622,7 +622,7 @@ static int save_pictures(git_repository *repo, struct dir *dir, struct dive *div return 0; } -static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *dive, struct tm *tm) +static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *dive, struct tm *tm, bool cached_ok) { struct divecomputer *dc; struct membuffer buf = { 0 }, name = { 0 }; @@ -631,6 +631,22 @@ static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *di /* Create dive directory */ create_dive_name(dive, &name, tm); + + /* + * If the dive git ID is valid, we just create the whole directory + * with that ID + */ + if (cached_ok && dive_cache_is_valid(dive)) { + git_oid oid; + git_oid_fromraw(&oid, dive->git_id); + ret = tree_insert(tree->files, mb_cstring(&name), 1, + &oid, GIT_FILEMODE_TREE); + free_buffer(&name); + if (ret) + return report_error("cached dive tree insert failed"); + return 0; + } + subdir = new_directory(repo, tree, &name); subdir->unique = 1; free_buffer(&name); @@ -747,7 +763,7 @@ static void verify_shared_date(timestamp_t when, struct tm *tm) #define MIN_TIMESTAMP (0) #define MAX_TIMESTAMP (0x7fffffffffffffff) -static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip_t *trip, struct tm *tm) +static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip_t *trip, struct tm *tm, bool cached_ok) { int i; struct dive *dive; @@ -781,7 +797,7 @@ static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip_t *tr /* Save each dive in the directory */ for_each_dive(i, dive) { if (dive->divetrip == trip) - save_one_dive(repo, subdir, dive, tm); + save_one_dive(repo, subdir, dive, tm, cached_ok); } return 0; @@ -897,7 +913,7 @@ static void save_divesites(git_repository *repo, struct dir *tree) } } -static int create_git_tree(git_repository *repo, struct dir *root, bool select_only) +static int create_git_tree(git_repository *repo, struct dir *root, bool select_only, bool cached_ok) { int i; struct dive *dive; @@ -946,11 +962,11 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o trip->index = 1; /* Pass that new subdirectory in for save-trip */ - save_one_trip(repo, tree, trip, &tm); + save_one_trip(repo, tree, trip, &tm, cached_ok); continue; } - save_one_dive(repo, tree, dive, &tm); + save_one_dive(repo, tree, dive, &tm, cached_ok); } return 0; } @@ -1176,6 +1192,7 @@ int do_git_save(git_repository *repo, const char *branch, const char *remote, bo { struct dir tree; git_oid id; + bool cached_ok; if (verbose) fprintf(stderr, "git storage: do git save\n"); @@ -1183,6 +1200,12 @@ int do_git_save(git_repository *repo, const char *branch, const char *remote, bo if (!create_empty) // so we are actually saving the dives git_storage_update_progress(19, "start git save"); + /* + * Check if we can do the cached writes - we need to + * have the original git commit we loaded in the repo + */ + cached_ok = try_to_find_parent(saved_git_id, repo); + /* Start with an empty tree: no subdirectories, no files */ tree.name[0] = 0; tree.subdirs = NULL; @@ -1191,7 +1214,7 @@ int do_git_save(git_repository *repo, const char *branch, const char *remote, bo if (!create_empty) /* Populate our tree data structure */ - if (create_git_tree(repo, &tree, select_only)) + if (create_git_tree(repo, &tree, select_only, cached_ok)) return -1; if (verbose) |