Git es muy lento para 100.000 objetos. ¿Algún arreglo?


Tengo un repositorio git-svn "fresco" (11.13 GB) que tiene más de 100.000 objetos en él.

He preformado

git fsck
git gc

En el repositorio después del pago inicial.

Entonces traté de hacer un

git status

El tiempo que toma hacer un estado de git es de 2m25.578s y 2m53. 901s

Probé el estado de git emitiendo el comando

time git status

5 veces y todas las veces transcurrieron entre las dos veces mencionadas anteriormente.

Estoy haciendo esto en un Mac OS X, localmente no a través de una máquina virtual.

No hay manera de que esto tome tanto tiempo.

¿Alguna idea? Ayuda?

Gracias.

Editar

Tengo un compañero de trabajo sentado a mi lado con una caja comparable. Menos RAM y ejecutando Debian con un sistema de archivos jfs. Su estado de git se ejecuta .3 en el mismo repositorio (también es un checkout git-svn).

Además, recientemente cambié mis permisos de archivo (a 777) en esta carpeta y redujo considerablemente el tiempo (¿por qué, no tienen ni idea). Ahora puedo hacerlo en cualquier lugar entre 3 y 6 segundos. Esto es manejable, pero sigue siendo un dolor.

Author: manumoomoo, 2010-07-23

12 answers

Se redujo a un par de elementos que puedo ver en este momento.

  1. git gc --aggressive
  2. Abriendo permisos de archivo a 777

Tiene que haber algo más, pero estas fueron las cosas que claramente tuvieron el mayor impacto.

 26
Author: manumoomoo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-06 20:15:08

Git status tiene que mirar cada archivo en el repositorio cada vez. Puedes decirle que deje de mirar árboles en los que no estás trabajando

git update-index --assume-unchanged <trees to skip>

Fuente

De la página de manual:

Cuando se especifican estas banderas, la nombres de objetos registrados para las rutas no están actualizados. En cambio, estos opciones establecer y desajustar el " asumir sin cambios " poco para los caminos. Cuando el el bit "asumir sin cambios" está activado, git deja de revisar los archivos del árbol de trabajo para posibles modificaciones, para que necesidad de desajustar manualmente el bit a decir git cuando cambias el árbol de trabajo file. Esto a veces es útil cuando trabajando con un gran proyecto en un sistema de archivos que tiene lstat muy lento (2) llamada al sistema (por ejemplo, cifs).

Esta opción también se puede utilizar como mecanismo de nivel de archivo grueso a ignorar cambios no comprometidos en archivos rastreados (similar a qué .gitignore para archivos no rastreados). Git fallará en caso de que necesite modificar esto archivo en el índice p. ej. cuando se fusiona en un commit; por lo tanto, en caso de que el archivo sin seguimiento asumido es cambiado aguas arriba, tendrá que maneje la situación manualmente.

Muchas operaciones en git dependen de su sistema de archivos para tener un eficiente lstat (2) implementación, de modo que st_mtime información para árbol de trabajo los archivos se pueden comprobar a bajo costo para ver si el contenido del archivo ha cambiado de la versión registrada en el índice file. Desafortunadamente, algunos sistemas de archivos tener lstat ineficiente (2). Si su filesystem es uno de ellos, puede establecer "asumir sin cambios" poco a las rutas que no han cambiado para causar que git no hacer esta comprobación. Tenga en cuenta que la configuración de este bit en una ruta no significa que git lo hará compruebe el contenido del archivo para ver si ha cambiado - hace que git omitir cualquier comprobación y asumir que tiene no ha cambiado. Cuando realiza cambios en archivos de árbol de trabajo, tienes que explícale a git al respecto soltar el bit" asumir sin cambios", bien antes o después de modificar ellos.

...

Para establecer " asumir sin cambios" bit, use la opción assume assume-unchanged. A unset, use no no-assume-unchanged.

El comando mira core.ignorestat variable de configuración. Cuando esto es true, rutas actualizadas con git update - index paths updated y paths actualizados con otros comandos de git que actualizan tanto el índice como el árbol de trabajo (por ejemplo, git apply index index, git checkout-index-u, y git read-tree-u) son marcado automáticamente como " asumir invariable". Tenga en cuenta que " asumir sin cambios " bit no se establece si git update-index finds refresh encuentra el el archivo de árbol de trabajo coincide con el índice (use git update-index really really-refresh si desea marcarlos como " asumir invariable").


Ahora, claramente, esta solución solo va a funcionar si hay partes del repositorio que puede ignorar convenientemente. Trabajo en un proyecto de tamaño similar, y definitivamente hay árboles grandes que no necesito para comprobar sobre una base regular. La semántica de git-status lo convierte en un problema generalmente O (n) (n en número de archivos). Necesita optimizaciones específicas de dominio para hacerlo mejor que eso.

Tenga en cuenta que si trabaja en un patrón de unión, es decir, si integra los cambios de upstream por merge en lugar de rebase, entonces esta solución se vuelve menos conveniente, porque un cambio a un objeto merging assume-unchanged que se fusiona desde upstream se convierte en un conflicto de fusión. Puede evitar este problema con un reorganizar el flujo de trabajo.

 15
Author: masonk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-25 23:51:44

Una solución a largo plazo es aumentar git para almacenar en caché el estado del sistema de archivos internamente.

Karsten Blees lo ha hecho para msysgit, que mejora drásticamente el rendimiento en Windows. En mis experimentos, su cambio ha tomado el tiempo para el "estado de git" de 25 segundos a 1-2 segundos en mi máquina Win7 que se ejecuta en una máquina virtual.

Los cambios de Karsten: https://github.com/msysgit/git/pull/94

Discusión del enfoque de almacenamiento en caché: https://groups.google.com/forum/#! topic / msysgit / fL_jykUmUNE / discussion

 5
Author: Chris Kline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-17 15:29:53

git status debería ser más rápido en Git 2.13 (Q2 2017), debido a:

Sobre este último punto, ver commit a33fc72 (14 Abr 2017) por Jeff Hostetler (jeffhostetler).
(Merged by Junio C Hamano -- gitster -- in commit cdfe138 , 24 Apr 2017)

read-cache: force_verify_index_checksum

Enseñar a git a omitir la verificación de la suma de comprobación SHA1-1 al final de el archivo de índice en verify_hdr() que se llama desde read_index() a menos que se establezca la variable global" force_verify_index_checksum".

Enseña fsck a forzar esta verificación.

La verificación de suma de comprobación es para detectar la corrupción del disco, y para proyectos pequeños, el tiempo que toma calcular SHA-1 no es tan significativo, pero para repositorios gigantescos este cálculo agrega tiempo significativo para cada comando.


Git 2.14 mejora de nuevo el rendimiento del estado de git al tener mejor en cuenta "caché sin seguimiento", lo que permite a Git omitir la lectura de los directorios no rastreados si sus datos stat no han cambiado, utilizando el campo mtime de la estructura stat.

Ver el Documentation/technical/index-format.txt para más información sobre sin marcar caché.

Véase commit edf3b90 (08 de mayo de 2017) por David Turner (dturner-tw).
(Merged by Junio C Hamano -- gitster -- in commit fa0624f , 30 May 2017)

Cuando "git checkout", "git merge", etc. manipula el índice en el núcleo, varias piezas de información en las extensiones de índice se descartan del estado original, ya que generalmente no es el caso de que se mantengan actualizadas y sincronizadas con la operación en el índice principal.

La extensión de caché no rastreada se copia en estas operaciones ahora, lo que aceleraría el "estado de git" (siempre y cuando la caché esté invalidada correctamente).


Más generalmente, escribir en la caché también será más rápido con Git 2.14.x / 2.15

Véase commit ce012de, commit b50386c, commit 3921a0b (21 Aug 2017) by Kevin Willford (`).
(Merged by Junio C Hamano -- gitster -- in commit 030faf2 , 27 Aug 2017)

Solíamos gastar más de los ciclos necesarios asignación y liberación pedazo de memoria mientras escribe cada entrada de índice.
Esto ha sido optimizado.

[Eso] ahorraría entre un 3-7% cuando el índice tenía más de un millón de entradas sin degradación de rendimiento en repositorios pequeños.


Actualización Dic. 2017: Git 2.16 (Q1 2018) propondrá una mejora adicional, esta vez para git log, ya que el código para iterar sobre archivos objeto sueltos acaba de optimizarse.

Véase commit 163ee5e (04 Dec 2017) by Derrick Stolee (derrickstolee).
(Merged by Junio C Hamano -- gitster -- in commit 97e1f85, 13 Dec 2017)

sha1_file: utilice strbuf_add() en lugar de strbuf_addf()

Sustitúyase el uso de strbuf_addf() por strbuf_add() al enumerar objetos sueltos en for_each_file_in_obj_subdir(). Ya que ya compruebe la longitud y los valores hexadecimales de la cadena antes de consumir el camino, podemos evitar el cálculo adicional mediante el uso de la menor- método de nivel.

Un consumidor de for_each_file_in_obj_subdir() es la abreviatura codificar. OID (identificadores de objetos) las abreviaturas usan una lista en caché de objetos sueltos (por subdirectorio de objeto) para realizar consultas repetidas rápidamente, pero hay tiempo de carga de caché significativo cuando hay muchos objetos sueltos.

La mayoría de los repositorios no tienen muchos objetos sueltos antes de volver a empaquetar, pero en el GVFS caso (ver " Anunciando GVFS (Git Virtual File System)") los repositorios pueden crecer hasta tener millones de objetos sueltos.
Perfilar el rendimiento de 'git log' en Git Para Windows en un repositorio habilitado para GVFS con ~2,5 millones de objetos sueltos reveló que el 12% del tiempo de CPU se gastó en strbuf_addf().

Añadir una nueva prueba de rendimiento a p4211-line-log.sh que es más sensible a esta carga de caché.
Al limitar a 1000 confirmaciones, nos parecemos más al tiempo de espera del usuario al leer el historial en un buscapersonas.

Para una copia del repositorio de Linux con dos paquetes de ~512 MB y objetos sueltos de ~572K, ejecutando 'git log on oneline parents parents raw raw -1000' tuvieron el siguiente rendimiento:

 HEAD~1            HEAD
----------------------------------------
 7.70(7.15+0.54)   7.44(7.09+0.29) -3.4%

Actualización de marzo de 2018: Git 2.17 mejorará git status un poco más: ver esta respuesta.

 5
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-11 03:34:21

En general, mi mac está bien con git, pero si hay muchos objetos sueltos, se vuelve mucho más lento. Parece que hfs no es tan bueno con muchos archivos en un solo directorio.

git repack -ad

Seguido de

git gc --prune=now

Hará un solo archivo de paquete y eliminará los objetos sueltos que queden. Puede tomar algún tiempo para ejecutar estos.

 4
Author: slobobaby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-06 20:13:03

Podrías intentar pasar el interruptor --aggressive a git gc y ver si eso ayuda:

# this will take a while ...
git gc --aggressive

También, puedes usar git filter-branch para eliminar confirmaciones y/o archivos antiguos si tienes cosas que no necesitas en tu historial (por ejemplo, archivos binarios antiguos).

 3
Author: David Underhill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 22:12:14

Por si sirve de algo, recientemente encontré una gran discrepancia entre el comando git status entre mis ramas master y dev.

Para acortar una larga historia, rastreé el problema a un solo archivo de 280MB en el directorio raíz del proyecto. Fue un chequeo accidental de un volcado de base de datos por lo que estaba bien eliminarlo.

Aquí está el antes y el después:

⚡ time git status
# On branch master
nothing to commit (working directory clean)
git status  1.35s user 0.25s system 98% cpu 1.615 total

⚡ rm savedev.sql

⚡ time git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   deleted:    savedev.sql
#
no changes added to commit (use "git add" and/or "git commit -a")
git status  0.07s user 0.08s system 98% cpu 0.157 total

Tengo 105,000 objetos almacenados, pero parece que los archivos grandes son más una amenaza que muchos archivos pequeños.

 2
Author: Brendon McLean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-02 16:40:15

También puede intentar git repack

 1
Author: baudtack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 22:14:48

Tal vez usted utiliza un escáner de virus? He probado algunos grandes proyectos aquí en Windows y en Linux, ¡fue muy rápido!

No creo que necesites hacer un git gc en un repositorio clonado (debería estar limpio).

¿Está bien su disco duro? IOPS y R / W por segundo? Tal vez está dañado?

 0
Author: Andreas Rehm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 22:14:45

Tal vez spotlight está tratando de indexar los archivos. Tal vez desactivar spotlight para su código dir. Compruebe el Monitor de actividad y vea qué procesos se están ejecutando.

 0
Author: neoneye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 22:26:31

Crearía una partición usando un sistema de archivos diferente. HFT + siempre ha sido lento para mí en comparación con hacer operaciones similares en otros sistemas de archivos.

 0
Author: srparish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-24 18:43:47

Intente ejecutar el comando Prune se deshará de los objetos sueltos

Git remote prune origin

 0
Author: Devnegikec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-10 11:49:36