2012-09-05 11 views
18

Algunas veces es posible que desee evitar/minimizar el recolector de basura, por lo que quiero estar seguro de cómo hacerlo.Cómo minimizar la recolección de basura en Go?

creo que el siguiente es correcta:

  • declarar variables al comienzo de la función.
  • Para usar una matriz en lugar de una división.

¿Algo más?

+0

Supongo que primero debe hacer un perfil antes de realizar una optimización como esta. Consulte [este] (http://blog.golang.org/2011/06/profiling-go-programs.html) entrada de blog sobre la creación de perfiles. También optimizan la recolección de basura. ¿Debería ser un buen comienzo? – Christian

+4

¿Por qué está cerrado? Pregunta: ¿Cómo evitar la recolección de basura? Evite la asignación de heap (con ejemplos referenciados específicos). La pregunta es relevante y específica, y la respuesta no parece discutible. – user634175

Respuesta

21

Evitar la basura es relativamente sencillo. Debe comprender dónde se realizan las asignaciones y ver si puede evitar la asignación.

Primero, declarar variables al principio de una función NO ayudará. El compilador no sabe la diferencia. Sin embargo, los humanos sabrán la diferencia y los molestará.

El uso de una matriz en lugar de una división funcionará, pero eso se debe a que las matrices (a menos que se eliminen las referencias) se colocan en la pila. Las matrices tienen otros problemas, como el hecho de que se pasan por valor (copiado) entre funciones. Cualquier cosa en la pila es "no basura", ya que se liberará cuando la función regrese. Cualquier puntero o segmento que pueda escapar de la función se coloca en el montón que el recolector de basura debe tratar en algún momento.

Lo mejor que puede hacer es evitar la asignación. Cuando haya terminado con grandes cantidades de datos que no necesita, vuelva a utilizarlos. Este es el método utilizado en el profiling tutorial en el blog Go. Sugiero leerlo.

Otro ejemplo además del que está en el tutorial de creación de perfiles: digamos que tiene una porción del tipo []int llamada xs. Continuamente agrega al []int hasta llegar a una condición y luego la reinicia para que pueda comenzar de nuevo. Si lo hace xs = nil, ahora está declarando que la matriz subyacente del sector como basura se debe recopilar. Append reasignará xs la próxima vez que lo use. Si en su lugar lo hace xs = xs[:0], aún está restableciéndolo pero manteniendo la matriz anterior.

En su mayor parte, tratar de evitar la creación de basura es una optimización prematura. Para la mayor parte de tu código, no importa. Pero puede encontrar de vez en cuando una función que se llama muchas veces que asigna mucho cada vez que se ejecuta. O un bucle donde reasignas en lugar de reutilizar. Esperaría hasta que veas el cuello de la botella antes de ir por la borda.

29

Para minimizar la recolección de basura en Go, debe minimizar las asignaciones de pila. Para minimizar las asignaciones de montón, debe comprender cuándo ocurren las asignaciones.

Los siguientes cosas siempre causa asignaciones (al menos en el compilador GC como de Go 1):

  • Utilizando el new función integrada de
  • Uso de la función incorporada make (excepto en algunos casos de esquina improbables)
  • Literales compuestos cuando el tipo de valor es una división, un mapa o una estructura con el operador &
  • Poniendo un valor mayor que una palabra de máquina en una interfaz. (Por ejemplo, cadenas, sectores y algunas estructuras son más grandes que una palabra de máquina).)
  • La conversión entre string, []byte, y []rune
    • A partir de Go 1.3, los casos especiales del compilador esta expresión no asignar: m[string(b)], donde m es un mapa y b es un []byte
  • la conversión un valor entero no constante a una string
  • defer declaraciones
  • go declaraciones
  • literales de funciones que capturan las variables locales

las siguientes cosas pueden causa asignaciones, dependiendo de los detalles:

  • tomar la dirección de una variable. Tenga en cuenta que las direcciones se pueden tomar implícitamente. Por ejemplo, a.b() podría tomar la dirección de a si a no es un puntero y el método b tiene un tipo de receptor de puntero.
  • Uso de la append función integrada de
  • Llamar a una función variadic o método
  • Rebanar una matriz
  • Adición de un elemento a un mapa

La lista pretende ser completa y I' Estoy razonablemente seguro de ello, pero estoy feliz de considerar adiciones o correcciones.

Si no está seguro de dónde están pasando sus asignaciones, siempre puede hacer un perfil como otros sugirieron o mirar el ensamblado producido por el compilador.

+1

Puede usar 'go build -gcflags =" - m "' para ver el análisis de escape del compilador. Se ha mejorado mucho al poner cosas como 'x: = make ([] byte, 42)' en la pila cuando es posible. –

Cuestiones relacionadas