Interesante discusión.

Una cosa para mencionar con respecto a asignar null a las variables y que le
puede resultar útil a alguien. Si se trata de variables locales, esto no es
necesario, ya que el runtime se ocupa de rastrear el uso y sabe exactamente
cuando una referencia ya no será utilizada. Esto es así cuando el programa
es compilado en modo "Release". El comportamiento en modo "Debug" es
diferente, ya que la vida de los objetos se prolonga para permitir examinar
su estado en el debugger. Por ejemplo,

void MiMetodo()
{
   MiClase obj = new MiClase( );
   ....
   obj.OtroMetodo();    // en modo RELEASE "obj" ya es recolectable aquí
   obj = null;               // esta línea de código es innecesaria
   ....
   // más líneas de código que NO hacen referencia a "obj"
   ...
   // En modo DEBUG "obj" todavía esta "vivo" aquí
}

Un detalle significativo, y que puede derivar en bugs interesantes, es que
"obj" puede ser recolectado mientras OtroMetodo se encuentra todavía
ejecutando. Por ejemplo,

class MiClase
{
   private int _value;

   public void OtroMetodo()
   {
       ...
       HacerAlgo( _value ); // la instancia puede ser recolectada aquí
       ...
       // más código que no hace referencia a miembros de la clase
       ...
   }
}

Si el método fuera implementado como se muesta arriba, entonces "obj" podría
ser recolectado inmediatamente después de que se recupera el miembro
"_value" para hacer el llamado al método HacerAlgo, ya que no existen más
usos de la referencia 'this'.

Sin embargo, en el caso de miembros de una clase, hay circunstancias donde
asignar null puede tener beneficios. Por ejemplo,

class OtraClase
{
   private object _objetoPesado;

   public UnMetodo ( )
   {
       // utilizo un objeto "pesado"

       HacerAlgoConElObjeto( _objetoPesado );

       // de aquí en adelante no se necesita _objetoPesado

       ....
       // asigno null para evitar que sea promovido de generación
       _objetoPesado = null;

       MetodoQueBloqueaOAsignaMemoria( );
   }
}

En el ejemplo de arriba, el método UnMetodo hace uso de un objeto "pesado"
con respecto a su uso de memoria, y luego hace una llamada a otro método.
Este método podría asignar memoria o también bloquear el thread actual, por
ejemplo si fuera una consulta a una base de datos o un web service, en cuyo
caso otros threads seguirían ejecutando y estos podrían as su vez asignar
memoria. En cualquiera de los casos, la asignación de memoria podría
disparar un ciclo de GC, en cuyo caso el _objetoPesado sería promovido a la
generación siguiente. En el caso de un bloqueo, si este fuera prolongado,
podría ocurrir que haya más de un ciclo de GC, y que el objeto sea
eventualmente promovido a la generación 2. La recolección de objetos de esta
generación es muy costosa, así que en este caso en particular es beneficioso
asignar null a la variable, y de esta forma el objeto puede ser liberado en
la primera oportunidad y sin que sea promovido de generación.

Saludos,

Fernando Tubio

----- Original Message -----
From: "Carlos A. Perez" <[EMAIL PROTECTED]>
To: <puntonet@mug.org.ar>
Sent: Thursday, October 11, 2007 11:14 PM
Subject: [puntonet] Preguntas varias


Hola

Solo pensando en voz alta, con ánimo de tirar una idea más.. podes utilizar
Datareaders? Los datareaders son órdenes de magnitud más livianos en consumo
de memoria porque lo podemos ver como una "ventana deslizante" sobre las
páginas físicas de las tablas SQL Server ya que capturan una sola fila por
vez (para llenar un control deberías hacer Do..WHILE), y no -como el
dataset- una copia de datos desconectada que mantiene -para colmo de males-
dos juegos idénticos de resultados. Uno puede mejorar algo la performance
desactivando las restricciones, pero el consumo de memoria es considerable.

Como contrapartida, para aplicaciones ASP.NET , el dataset puede ser
cacheado, y el datareader necesita de una conexión con estado el 100% del
tiempo. Igualmente, en performance, es normalmente admitido que si
dataset=100, datareader=80 como mucho. No es significativamente más
performante, sino que consume muchísima menos memoria (se hace captura de
una fila por vez, y no de todo el conjunto de resultados).

Por otro lado, en entornos ASP.NET, los datasets se pueden almacenar en
variables session(), mientras que el datareader, al ser incapaz de leer más
de una sola fila por vez, necesita reconsultar a la base de datos cada vez
que se recrea la página. En este caso podríamos preparar la consulta, y
confiar en el plan de acceso cacheable que nos brinda el SQL Server, pero en
escalabilidad, parece que el caché de los datasets le lleva mucha ventaja a
cualquier otra técnica que uno pueda imaginar.

Si tus usuarios no son miles, y tu problema es el consumo de memoria de un
dataset muy grande, podrías probar con el frugal datareader, no esperes
mejoras *impresionantes* en velocidad, pero si en consumo de memoria.

Para aumentar el tiempo de respuesta de la consulta, deberías probar (no es
seguro, por eso digo probar) el colocarle parámetros al query, y pedirle a
ADO.NET que PREPARE la consulta. En este caso, el SQL SERVER calcula y
cachea el plan de acceso, y en subsiguientes consultas, como solamente
varían los parámetros y no la semántica del query, el plan de acceso no se
reevalúa sino que se ejecuta directamente desde el caché. Igualmente, las
UNION ALL son ejecuciones muy costosas, así que en este caso vería de
tenerle paciencia, si hay mejora sería en el manejo de las subconsultas. Si
las subconsultas son correlacionadas (es decir, la subconsulta interna
depende de qué registro se evalúa en la consulta externa a cada momento del
query), quizás convendría reescribir el query usando JOINs. Normalmente el
optimizer hace esto, pero nunca está demás probarlo. Con los JOINS
explícitos, el optimizador puede reindexar al vuelo y mantener los índices
de las juntas internas (si prepara la consulta), y así aumentar
significativamente la velocidad global de consulta.

Carlos


-----Mensaje original-----
De: puntonet@mug.org.ar [mailto:[EMAIL PROTECTED] En nombre de
Damián Herrera
Enviado el: Jueves, 11 de Octubre de 2007 04:53 p.m.
Para: puntonet@mug.org.ar
Asunto: [puntonet] Preguntas varias


Que lastima :s A mi me paso lo mismo y los convencí en mostrarselos de
a 20
registros. En total, en una de las grillas me quedaron 7500 páginas :)
Entre
pagina y pagina tengo un retardo de 4 segundos más o menos, por
cuestión de la
complejidad de la consulta (tiene más de 5 union all y varios sub
queries).
Siempre trato de sobresaltar que hay que aplicar buenos filtros para
evitar
mostrar tanta info. Pero es complejo :)


Saludos,
Damián Herrera

>-----Original Message-----
>From: puntonet@mug.org.ar [mailto:[EMAIL PROTECTED] On
>Behalf Of JATEMLIANSKY, Diego
>Sent: Thursday, October 11, 2007 3:49 PM
>To: puntonet@mug.org.ar
>Subject: [puntonet] Preguntas varias
>
>Si, lamentablemente los usuarios acá quieren ver todos los datos.
>
>Yo le explique que ya mas de 1000 datos en una grilla en
>pantalla era mucho,
>pero no lo pude convencer.
>
>
>-----Mensaje original-----
>De: Damián Herrera [mailto:[EMAIL PROTECTED]
>Enviado el: Jueves, 11 de Octubre de 2007 14:21
>Para: puntonet@mug.org.ar
>Asunto: [puntonet] Preguntas varias
>
>
>Hola Diego,
>
>Consulta, ¿estos dataset grandes los mostras al usuario todos juntos?
>Pregunto,
>porque talvez una solución de paginación en base de datos
>pueda resultar más
>optima.
>
>Saludos,
>Damián Herrera
>
>>-----Original Message-----
>>From: puntonet@mug.org.ar [mailto:[EMAIL PROTECTED] On
>>Behalf Of JATEMLIANSKY, Diego
>>Sent: Thursday, October 11, 2007 10:43 AM
>>To: puntonet@mug.org.ar
>>Subject: [puntonet] Preguntas varias
>>
>>Gente como andan ?
>>Tengo un par de preguntas para hacerles que nos están sacando
>>el sueño y que
>>tal vez con algunos tips que nos puedan dar nos puedan
>>orientar un poco como
>>encararlo.
>>
>>La arquitectura que tenemos es de FrontEnd en ASP.NET, BackEnd
>>en Servicios
>>de Windows VB.NET accedidos por Remoting y SQL Server.
>>(Todo esto instalado en servidores, no instalamos nada en las
>>PC clientes)
>>
>>Ahora les paso las preguntas (Todas con respecto a la parte
>>del BackEnd en
>>donde tenemos todas las reglas de negocios y el grueso de la
>>codificacion):
>>
>>1- Liberar memoria:
>> En algunos casos nos esta costando entender como hacer
>>para liberar
>>memoria.
>> Por un lado encontramos que nos recomiendan hacer los
>>Dispose de los
>>DataSets una vez utilizados y por otro lado también
>encontramos algunos
>>sites que recomiendan hacer un ds = nothing para liberar la
>>memoria, cual es
>>la opción mas recomendable?
>>
>> Por otro lado, que pasa si un método de nuestro BackEnd hace
>>solamente lo siguiente:
>>
>> Function traer() as dataset
>> Dim ds as new dataset
>>
>> ds = CargarDatasetdesdeSQL
>>
>> return ds
>> end function
>>
>> Como hacemos para liberar la memoria utilizada por este
>>DataSet (que
>>en algunos casos trae muchos datos para mostrar en pantalla)
>>si después del
>>return no podemos hacer mas nada.
>>
>>2- Prioridad de procesos:
>> Tenemos varios procesos que son del tipo Batch, o sea, que el
>>usuario levanta un archivo y lo vamos procesando.
>> Estos procesos pueden llevar al procesador a consumir
>>mas de lo que
>>queremos y afectan al funcionamiento optimo del Server. (Ya
>>que en el Server
>>de BackEnd tenemos varios servicios corriendo y no podemos
>>afectar a los
>>otros)
>> Como hacemos para establecer prioridades a estos
>>procesos o decirle
>>que solamente consuman hasta por Ej. un 30% o que tengan menor
>>prioridad ?
>> O para que el Loop que hacemos con los registros del
>>archivo no se
>>lleve todo el procesador.
>> (Estos procesos los tenemos que hacer OnLine, no
>>podemos dejarlos
>>como procesos nocturnos)
>>
>>
>>Muchas Gracias.
>>
>>
>>
>> AVISO: El presente mensaje y los archivos adjuntos que incluya
pueden
>>contener información confidencial de uso exclusivo del destinatario
>>indicado. Cualquier uso en desacuerdo con su propósito, difusión o
>>publicación, total o parcial, se encuentra prohibida. Si recibió este
>>mensaje por error, rogamos reenviarlo al emisor y destruir las copias
>>impresas o grabadas en su sistema. Las opiniones contenidas, son
>>exclusivas de su autor y no representan necesariamente la opinión de
>>OMINT S.A. de Servicios.
>>
>>
>
>
>
> AVISO: El presente mensaje y los archivos adjuntos que incluya pueden
>contener información confidencial de uso exclusivo del destinatario
>indicado. Cualquier uso en desacuerdo con su propósito, difusión o
>publicación, total o parcial, se encuentra prohibida. Si recibió este
>mensaje por error, rogamos reenviarlo al emisor y destruir las copias
>impresas o grabadas en su sistema. Las opiniones contenidas, son
>exclusivas de su autor y no representan necesariamente la opinión de
>OMINT S.A. de Servicios.
>
>



__________ Información de NOD32, revisión 2587 (20071011) __________

Este mensaje ha sido analizado con NOD32 antivirus system
http://www.nod32.com




Responder a