2010-08-24 10 views
6

He estado programando con Java para Android desde hace bastante tiempo. Como el rendimiento es muy importante para las cosas en las que estoy trabajando, termino simplemente enviando spam a las variables globales. Supongo que todos vendrán corriendo ahora y me dirán que este es el peor estilo de todos, pero vamos a hacerlo simple. Para Android, las variables locales significan que la recolección de basura y la recolección de basura es algo que mata el rendimiento.Mantener una variable global o recrear una variable local en c?

Últimamente comencé a usar el NDK. Ahora siento la necesidad de tomar todas las variables locales y cambiarlas a variables globales. Me pregunto si esto tiene algún sentido en el código c. Obviamente no es un buen estilo, pero si es necesario para la velocidad, sacrificaré el estilo con mucho gusto.

He revisado temas más antiguos sobre locales y globales, pero no he podido encontrar nada sobre la velocidad. Entonces, mi pregunta es, si estoy llamando a una función muy a menudo, ¿es relevante para la velocidad con la que se crean las variables locales y muere después de que se realiza la función? ¿O no importa para nada y puedo seguir usando las variables locales felizmente?

Lo probaría yo mismo, pero por alguna razón el rendimiento de mi aplicación sube y baja como una montaña rusa y dudo que pueda realmente dar sentido a los datos. Espero que alguien me pueda ayudar antes de reescribir todo el código por nada :)

+1

¿Por qué crees que "variables locales significa recolección de basura"? –

+0

Porque las variables locales son basura recolectada cuando salen del alcance. – Crashworks

+0

Y las variables globales son a) basura recolectada cuando se establece en NULL; o b) se mantiene en la memoria, lo que aumenta innecesariamente la presión de la memoria cuando no se usa, si no se establece en NULO. –

Respuesta

8

En C, la diferencia de rendimiento depende del hardware. Cargar un global en un procesador RISC es más instrucciones (porque tiene que cargar ambas mitades de la dirección en instrucciones separadas, frente a un complemento en el puntero de pila), y luego debe lidiar con problemas de caché. En su mayor parte, puede contar con que sus variables locales estén en la memoria caché. El uso de globales afectará un poco la caché y algunas funciones se verán muy negativamente afectadas.

Si tiene una gran variabilidad de rendimiento al ejecutar su aplicación, es muy probable que su afirmación sobre el impacto en el rendimiento de las variables locales sea irrelevante.

El "costo" de crear una variable local en C es cero; simplemente está golpeando un registro (el puntero de la pila) para dejar espacio para el local. Luego, inicializa esa variable por cualquier medio que sea apropiado. Debería poder saber si es costoso o no por inspección casual. Cuando la función finaliza, el puntero de pila vuelve a su valor anterior, independientemente de la cantidad de variables locales que tenga.

Si su definición de "variables locales" es objetos asignados en el montón, sin embargo, sufrirá el costo de la asignación de memoria. En mi opinión, la asignación de memoria es muy lenta, así que cualquier cosa que puedas hacer para alejarte de malloc/free (y 'nuevo' en Java), estarás mejor. (Hago juegos, y que tienden a utilizar dlmalloc pero incluso eso es demasiado lento para el uso regular;. 400ns por llamada se suma rápida)

+0

Gracias por la respuesta rápida! Supongo que todavía tengo mucho que aprender. Pero me alegro de poder seguir utilizando las variables locales en c. Es un dolor en Java. Y para responder su comentario, creo que escogí las palabras equivocadas, pero lo que noté fue que si llamo a una función 20 veces por segundo y en la función que creo, por ejemplo, un int local, esto será basura recolectada después de que la función esté lista y solo cuesta mucho tiempo. Es por eso que terminé con muchas variables globales allí. – Pandoro

+0

Los enteros locales u otros tipos de datos primitivos no deberían requerir ningún tipo de colección de basura, incluso en Java. –

11

Para Android, las variables locales: la recogida de basura ...

Esta es una declaración incorrecta. Las variables locales se asignan en la pila, no se asignan dinámicamente en el montón. Compruebe this article en qué se asigna dónde en Java

Como regla, los elementos asignados en la pila no requieren recolección/liberación de basura y "mueren" inmediatamente después de la ejecución sale de su alcance actual. La asignación/desasignación de pila es significativamente más que la asignación de montón y la recolección de basura.

Trate de evitar las variables globales por motivos de estilo y rendimiento. Las variables locales asignadas a la pila funcionarán mucho más rápido.

+0

Es bueno saberlo. Como siempre lo intenté, todos los globales todas las variables locales obtuve un mejor rendimiento en el enfoque global, principalmente porque uso muchos objetos y matrices. Pero si lo hago bien, podría dejar todos los tipos de datos primitivos como locales, ya que ganaron ir al montón de todos modos? – Pandoro

+0

+1 Es triste que muchos programadores de Java no conozcan la diferencia entre la asignación de Pila y Pila. Pero tengo que admitir que, hasta que no haya aprendido C, tampoco me molesté :-). – helpermethod

+0

@Pandoro Vea http://cslibrary.stanford.edu/102/PointersAndMemory.pdf. Esta fue una verdadera revelación también para mí. – helpermethod

2

En las CPU basadas en MIPS y ARM que se encuentran en la mayoría de los teléfonos Android, no hay ninguna razón para mover las variables locales al espacio global "para el rendimiento". Los locales se almacenan en la pila y una asignación de pila es una operación única; además, toda la pila se limpia de inmediato al llamar al ret. Moverlos al espacio global simplemente hará que su lógica se convierta en un lío gruñón de un estado indescifrable sin ninguna ventaja.

El único lugar para preocuparse por la perforación con la creación de objetos es cuando los está asignando en el montón (por ejemplo, con malloc()). Aquí es exactamente donde C tiene más "rendimiento" que los lenguajes recogidos de basura, porque puede ver y controlar exactamente cuándo ocurren estos mallocs y cuándo se liberan. No es realmente el caso que C malloc() sea más rápido que Java new; más bien, debido a que cada asignación es transparente y explícita para usted, puede hacer el trabajo necesario para asegurarse de que tales operaciones lentas sucedan lo menos posible.

+0

De acuerdo. De hecho, 'malloc' suele ser mucho más lento que' new', y un barrido GC es a menudo más rápido que el número correspondiente de llamadas a 'free'. Pero los codificadores C expertos están acostumbrados a ser lo suficientemente cuidadosos con la asignación de memoria para compensar la diferencia (o escribir sus propias rutinas especializadas de manejo de memoria que son incluso más rápidas para su caso de uso). –

0

Por cierto, declarar una variable estática dentro de una función C le dará el comportamiento de un global sin ensuciar el espacio de nombres global.

Pero como se mencionó, declarar variables automáticas en la pila lleva 0 tiempo y acceder a esas variables también es extremadamente rápido, por lo que no hay muchas razones para evitar variables locales de función.

Si realmente necesita este nivel extremo de optimización, debería buscar alinear todas sus funciones comúnmente llamadas para evitar la sobrecarga de llamadas.

Cuestiones relacionadas