Ответ 1
По крайней мере, в нашем случае проблема была git. Мы повысились с 1.9 до 2.1.2, и проблема была решена. Когда я впервые опубликовал этот вопрос, у меня возникло неправильное впечатление, что обновление уже имело место.
Из журнала Дженкинса берется следующее:
00:00:03.135 > git fetch --tags --progress [email protected]:some_org/some_repo.git +refs/heads/*:refs/remotes/origin/*
00:03:49.659 > git rev-parse origin/master^{commit} # timeout=10
Я смущен, почему этот тайм-аут происходит, потому что запуск git fetch
на том же компьютере с одним и тем же пользователем занимает от 5 до 10 секунд.
Я использую последнюю (начиная с этой записи) версию Git (2.1.2) и последнюю версию gitplugin.
Мысли?
По крайней мере, в нашем случае проблема была git. Мы повысились с 1.9 до 2.1.2, и проблема была решена. Когда я впервые опубликовал этот вопрос, у меня возникло неправильное впечатление, что обновление уже имело место.
Примечание: git fetch скорость должна снова улучшиться с помощью Git 2.2+ (ноябрь 2014 г.)
См. commit cbe7333, Джефф Кинг (peff
):
is_refname_available
Наша файловая система ref storage не разрешает конфликты D/F (каталог/файл); поэтому, если существует "
refs/heads/a/b
", мы не допускаем существование "refs/heads/a
" (и наоборот).
Это, естественно, выпадает из-за неактивных ссылок, где файловая система выполняет условие. Но для упакованных refs, мы должны сами проверить.Мы делаем это путем итерации по всему пространству имен упакованных refs и проверки того, создает ли каждое имя конфликт. Если у вас очень большое количество ссылок, это довольно неэффективно, так как вы в конечном итоге выполняете большое количество сравнений с неинтересными битами дерева ref (например, мы знаем, что все "
refs/tags
" неинтересный в приведенном выше примере, но мы проверяем каждую запись в нем).Вместо этого давайте воспользуемся тем фактом, что у нас есть упакованные ссылки, хранящиеся как trie
ref_entry
structs.
Мы можем найти каждый компонент предлагаемогоrefname
, когда мы проходим через дерево, проверяя конфликты D/F, когда мы идем. При arefname
глубиныN
(т.е. 4 в приведенном выше примере) нам нужно только посетить узлыN
. И при каждом посещении мы можем бинарно искать именаM
на этом уровне, для общей сложностиO(N lg M)
. ( "M
" различается на каждом уровне, конечно, но мы можем взять наихудший вариант "M
" в качестве границы).В патологическом случае извлечения 30 000 свежих ссылок в хранилище с 8,5 млн. рефсов это сократило время запуска "git fetch" с десятков минут до 30 с.
Это также может помочь небольшим случаям, в которых мы проверяем отсутствие ссылок (которые мы делаем при переименовании ссылки), поскольку мы можем избежать доступа к диску для несвязанных свободных каталогов.
Обратите внимание, что тесты, которые мы добавляем, на первый взгляд кажутся избыточными с тем, что уже находится в t3210. Однако ранние тесты не являются надежными; они запускаются с включенными логами, что мы вообще не тестируем
is_refname_available
!
Операции будут по-прежнему терпеть неудачу из-за того, что reflogs попадет в конфликты D/F в файловой системе.
Чтобы получить истинный тест, мы должны отключить reflogs (но мы не хотим делать это для всего script, потому что его включение включало в себя некоторые другие случаи).