#!/bin/sh global test_description := ''performance with large numbers of packs'' source ./perf-lib.sh test_perf_large_repo # A real many-pack situation would probably come from having a lot of pushes # over time. We don't know how big each push would be, but we can fake it by # just walking the first-parent chain and having every 5 commits be their own # "push". This isn't _entirely_ accurate, as real pushes would have some # duplicate objects due to thin-pack fixing, but it's a reasonable # approximation. # # And then all of the rest of the objects can go in a single packfile that # represents the state before any of those pushes (actually, we'll generate # that first because in such a setup it would be the oldest pack, and we sort # the packs by reverse mtime inside git). proc repack_into_n { rm -rf staging && mkdir staging && git rev-list --first-parent HEAD | sed -n '1~5p' | head -n $1 | perl -e 'print reverse <>' \ >pushes # create base packfile head -n 1 pushes | git pack-objects --delta-base-offset --revs staging/pack # and then incrementals between each pair of commits global last := '' && while read rev { if test -n $last { do { echo $rev && echo "^$last" } | git pack-objects --delta-base-offset --revs \ staging/pack || return 1 } global last := $rev } /dev/null ' # This simulates the interesting part of the repack, which is the # actual pack generation, without smudging the on-disk setup # between trials. test_perf "repack ($nr_packs)" ' git pack-objects --keep-true-parents \ --honor-pack-keep --non-empty --all \ --reflog --indexed-objects --delta-base-offset \ --stdout /dev/null ' } test_done (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"performance with large numbers of packs">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./perf-lib.sh)}) (C {(test_perf_large_repo)}) (FuncDef name: repack_into_n body: (BraceGroup children: [ (AndOr children: [ (C {(rm)} {(-rf)} {(staging)}) (AndOr children: [ (C {(mkdir)} {(staging)}) (Pipeline children: [ (C {(git)} {(rev-list)} {(--first-parent)} {(HEAD)}) (C {(sed)} {(-n)} {(SQ <"1~5p">)}) (C {(head)} {(-n)} {(DQ ($ VSub_Number "$1"))}) (SimpleCommand words: [{(perl)} {(-e)} {(SQ <"print reverse <>">)}] redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(pushes)} spids:[118])] ) ] negated: False ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) (Pipeline children: [ (C {(head)} {(-n)} {(1)} {(pushes)}) (C {(git)} {(pack-objects)} {(--delta-base-offset)} {(--revs)} {(staging/pack)}) ] negated: False ) (AndOr children: [ (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:last) op:Equal rhs:{(SQ )} spids:[154])] spids: [154] ) (AndOr children: [ (While cond: [(C {(read)} {(rev)})] body: (DoGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(test)} {(-n)} {(DQ ($ VSub_Name "$last"))}) terminator: ) ] action: [ (AndOr children: [ (Pipeline children: [ (BraceGroup children: [ (AndOr children: [ (C {(echo)} {(DQ ($ VSub_Name "$rev"))}) (C {(echo)} {(DQ ("^") ($ VSub_Name "$last"))}) ] op_id: Op_DAmp ) ] spids: [183] ) (C {(git)} {(pack-objects)} {(--delta-base-offset)} {(--revs)} {(staging/pack)} ) ] negated: False ) (ControlFlow token: arg_word: {(1)} ) ] op_id: Op_DPipe ) ] spids: [-1 180] ) ] spids: [-1 227] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:last) op: Equal rhs: {($ VSub_Name "$rev")} spids: [230] ) ] spids: [230] ) ] spids: [166 234] ) redirects: [(Redir op_id:Redir_Less fd:-1 arg_word:{(pushes)} spids:[236])] ) (AndOr children: [ (C {(rm)} {(-f)} {(.git/objects/pack/) (Lit_Other "*")}) (C {(mv)} {(staging/) (Lit_Other "*")} {(.git/objects/pack/)}) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] op_id: Op_DAmp ) ] spids: [55] ) spids: [50 54] ) (C {(test_expect_success)} {(SQ <"simplify reachability">)} { (SQ <"\n"> <"\ttip=$(git rev-parse --verify HEAD) &&\n"> <"\tgit for-each-ref --format=\"option no-deref%0adelete %(refname)\" |\n"> <"\tgit update-ref --stdin &&\n"> <"\trm -rf .git/logs &&\n"> <"\tgit update-ref refs/heads/master $tip &&\n"> <"\tgit symbolic-ref HEAD refs/heads/master &&\n"> <"\tgit repack -ad\n"> ) } ) (ForEach iter_name: nr_packs iter_words: [{(1)} {(50)} {(1000)}] do_arg_iter: False body: (DoGroup children: [ (C {(test_expect_success)} {(DQ ("create ") ($ VSub_Name "$nr_packs") ("-pack scenario"))} {(SQ <"\n"> <"\t\trepack_into_n $nr_packs\n"> <"\t">)} ) (C {(test_perf)} {(DQ ("rev-list (") ($ VSub_Name "$nr_packs") (")"))} {(SQ <"\n"> <"\t\tgit rev-list --objects --all >/dev/null\n"> <"\t">)} ) (C {(test_perf)} {(DQ ("repack (") ($ VSub_Name "$nr_packs") (")"))} { (SQ <"\n"> <"\t\tgit pack-objects --keep-true-parents \\\n"> <"\t\t --honor-pack-keep --non-empty --all \\\n"> <"\t\t --reflog --indexed-objects --delta-base-offset \\\n"> <"\t\t --stdout /dev/null\n"> <"\t"> ) } ) ] spids: [306 370] ) spids: [299 -1] ) (C {(test_done)}) ] )