Buscar en Asptutor     
Demo Tienda Virtual Tutorcar
 Navegacion->Inicio | Active Server Pages  

La web de los recursos y ejemplos de asp

Versión para imprimir

 

Alojado en:


urbe-networks.com

Recomienda esta pagina a un amigo

Servicios Gratuitos

Articulos relacionados

Utilizar GetRows()

Tienda Virtual - Carrito de compra

Messenger a través de BD en ASP

Miniaplicacion de comercio electronico

Objeto Datagrid de ASP.NET en ASP

Acotación de resultados

Ejemplos básicos de uso de cookies

La Función Split

Restriccion de acceso a paginas

Como cerrar la sesión si el usuario abandona tu sitio

Redireccionar una pagina con un Timer

Como mostrar una imagen almacenada en una Base de datos

Sugerencias Microsoft sobre ASP (II)

Proyecto ASP.NET Web Matrix

Leer un fichero de texto del servidor

Crear Textos en 3D


Enlaces recomendados

   

Tutorial ASP

Sugerencias Microsoft sobre ASP (I)
Este articulo ha sido leído 115.806 veces

Sugerencias sobre ASP para la mejora del rendimiento y el estilo (I)


Len Cardinal, Consultor senior, Microsoft Consulting Services
George V. Reilly, Responsable de rendimiento de Microsoft IIS

Adaptación de un artículo (en inglés) de Nancy Cluts
Ingeniero de tecnología de desarrolladores
Microsoft Corporation

Resumen: este artículo presenta una serie de sugerencias para la optimización 
de las aplicaciones ASP y VBScript.

Contenido

Introducción
Sugerencia 1: Almacenar en caché datos utilizados frecuentemente en el servidor Web
Sugerencia 2: Almacenar en caché datos utilizados frecuentemente en el objeto de aplicación o de sesión
Sugerencia 3: Almacenar en caché datos y HTML en los discos del servidor Web
Sugerencia 4: Evitar almacenar en caché componentes no ágiles en los objetos de aplicación o de sesión
Sugerencia 5: No almacenar en caché conexiones de la base de datos en los objetos de aplicación o de sesión
Sugerencia 6: Utilizar prudentemente el objeto de sesión
Sugerencia 7: Encapsular el código en los objetos COM
Sugerencia 8: Adquirir los recursos en el último momento y liberarlos cuanto antes
Sugerencia 9: La ejecución fuera de proceso permite el equilibrio entre el rendimiento y la confiabilidad
Sugerencia 10: Utilizar Option Explicit
Sugerencia 11: Utilizar variables locales en las subrutinas y las funciones
Sugerencia 12: Copiar datos utilizados frecuentemente en las variables de la secuencia
Sugerencia 13: Evitar redimensionar las matrices
Sugerencia 14: Utilizar el búfer de respuesta

Introducción

El rendimiento es una característica fundamental y, de hecho, si una aplicación no se diseña desde un principio teniéndolo en cuenta, más adelante será preciso volver a desarrollarla. Dicho de esta manera uno se pregunta: ¿existe alguna estrategia eficaz para maximizar el rendimiento de la aplicación ASP (Páginas Active Server)?

Este artículo proporciona una serie de sugerencias que permiten optimizar las aplicaciones ASP y Visual Basic® Scripting Edition (VBScript) y en él se discuten las muchas trampas y dificultades a las que se ha tenido que hacer frente. Las sugerencias que se enumeran se han utilizado en distintos sitios, incluyendo el de Microsoft, http://www.microsoft.com, y se ha comprobado que funcionan a la perfección. Este artículo da por sentado que el lector conoce los aspectos básicos del desarrollo de ASP, incluidos VBScript y/o JScript, las aplicaciones y sesiones ASP y el resto de objetos intrínsecos ASP (Request, Response y Server).

A menudo el rendimiento de ASP depende de mucho más que el propio código ASP. En lugar de cubrir todo el tema en un solo artículo, se han enumerado al final del mismo los recursos relacionados con el rendimiento. Estos vínculos tratan sobre temas relacionados o no con ASP, por ejemplo, Objetos de datos ActiveX® (ADO), Modelo de objetos componentes (COM), bases de datos y la configuración de Internet Information Server (IIS). Se trata de algunos de nuestros vínculos preferidos y recomendamos que los visite.

Sugerencia 1: Almacenar en caché datos utilizados frecuentemente en el servidor Web

Una página ASP típica recupera los datos desde el almacenamiento central de datos y, a continuación, convierte los resultados en lenguaje de marcado de hipertexto (HTML). Independientemente de la velocidad de la base de datos, recuperar los datos desde la memoria resulta un proceso mucho más rápido que recuperarlos desde dicho almacenamiento central de datos. La lectura de los datos en un disco local también se lleva a cabo más rápidamente que si se recuperan desde la base de datos. Por otra parte, también se puede incrementar el rendimiento almacenando los datos en caché en el servidor Web, ya sea en la memoria o en el disco.

El almacenamiento en caché constituye un mecanismo clásico que permite el equilibrio entre el espacio y el tiempo. Si se almacenan los elementos adecuados, se puede observar un impresionante aumento en el rendimiento. Para que la caché resulte efectiva ésta debe almacenar los datos que se vuelven a utilizar con relativa frecuencia y aquellos que pueden resultar (moderadamente) costosos de actualizar. Contar con datos obsoletos en la caché supone malgastar la memoria.

Los datos que no cambian con excesiva frecuencia son los candidatos idóneos para que se almacenen en caché, ya que uno no debe preocuparse por la sincronización con la base de datos después de un tiempo; listas de cuadros combinados, tablas de referencia, recortes DHTML, cadenas de lenguaje de marcado extensible (XML), elementos de menú y variables de configuración de los sitios (incluyendo nombres de origen de datos (DSN), direcciones de protocolo de Internet (IP) y rutas Web). Sin embargo, es necesario señalar que lo que se almacena en caché es la presentación de los datos y no los datos en sí. Si una página ASP no se modifica con demasiada frecuencia y resulta costoso almacenarla en caché (por ejemplo, un catálogo completo de productos), se debe considerar la posibilidad de generar previamente el HTML, en lugar de volver a escribirlo para cada solicitud.

¿Dónde deben almacenarse los datos y cuáles son las principales estrategias para el almacenamiento en caché? Por regla general los datos se almacenan, bien en la memoria, bien en los discos del servidor Web. Las dos sugerencias que se proporcionan a continuación cubren ambas opciones.

Sugerencia 2: Almacenar en caché datos utilizados frecuentemente en el objeto de aplicación o de sesión

Los objetos Application y Session ASP resultan unos contenedores adecuados para el almacenamiento de los datos, que se pueden asignar tanto al objeto Application como a Session y que permanecen en la memoria entre solicitudes HTTP. Los datos de la sesión se almacenan por usuario, mientras que los de la aplicación los comparten todos los usuarios.

¿En qué punto suele cargar los datos en la aplicación o la sesión? Con frecuencia los datos se cargan durante el inicio de la sesión o de la aplicación, para lo que es necesario agregar el código adecuado a Application_OnStart() o Session_OnStart()respectivamente. Estas funciones deben encontrarse en Global.asa, aunque si no es así, siempre se podrán agregar. Los datos también se pueden cargar cuando se los necesita por vez primera. Para ello, agregue el código (o escriba una función de secuencia reutilizable) a la página ASP de forma que compruebe la existencia de los datos y los cargue, si fuera necesario. Este ejemplo ilustra la técnica clásica de mejora del rendimiento conocida como evaluación perezosa, es decir, no se calcula nada hasta que no se sabe que se necesita. Un ejemplo:

<%
Function GetEmploymentStatusList
   Dim d
   d = Application("EmploymentStatusList")
   If d = "" Then
      ' La función FetchEmploymentStatusList (no se muestra)
      ' busca los datos en la BD y devuelve una matriz
      d = FetchEmploymentStatusList()
      Application("EmploymentStatusList") = d
   End If
   GetEmploymentStatusList = d
End Function
%>

Se podrían emplear funciones similares con cada grupo de datos necesario.

¿En qué formato deben almacenarse los datos? Se puede almacenar cualquier tipo Variant, ya que se trata de variables de secuencia. Por ejemplo, se pueden almacenar cadenas, enteros o matrices. A menudo se almacenará el contenido de un recordset ADO en uno de estos tipos de variables. Para extraer los datos del recordset ADO, se pueden copiar manualmente en las variables VBScript, un campo por vez. Resulta más rápido y sencillo utilizar una de las persistentes funciones del recordset ADO GetRows(),GetString() (en inglés) o Save() (ADO 2.5) (en inglés). No es el objetivo de este artículo proporcionar todos los detalles sobre este tema, sin embargo, sí que se ofrece un ejemplo ilustrativo sobre cómo utilizar GetRows() para devolver una matriz de datos del recordset:

' Obtener Recordset, devolver como matriz
Function FetchEmploymentStatusList
   Dim rs 
   Set rs = CreateObject("ADODB.Recordset")
   rs.Open "seleccionar StatusName, StatusID en EmployeeStatus", _
           "dsn=employees;uid=sa;pwd=;"
   FetchEmploymentStatusList = rs.GetRows() " Devolver datos como matriz
   rs.Close
   Set rs = Nothing
End Function

Un refinamiento aún mayor sería almacenar en caché el HTML de la lista en lugar de la matriz. Aquí se muestra un sencillo ejemplo de cómo hacerlo:

' Obtener Recordset, devolver como lista de opción HTML
Function FetchEmploymentStatusList
   Dim rs, fldName, s
   Set rs = CreateObject("ADODB.Recordset")
   rs.Open "seleccionar StatusName, StatusID en EmployeeStatus", _
           "dsn=employees;uid=sa;pwd=;"
   s = "<seleccionar nombre=""EmploymentStatus">" & vbCrLf
   Set fldName = rs.Fields("StatusName") ' Enlace de campos ADO
   Do Until rs.EOF
     ' La siguiente línea viola Evitar la concatenación de las cadenas...,
     ' pero no importa ya que estamos creando una caché
     s = s & " <option>" & fldName & "</option>" & vbCrLf
     rs.MoveNext
   Loop
   s = s & "</select>" & vbCrLf
   rs.Close
   Set rs = Nothing ' Consultar Adquirir los recursos en el último...
   FetchEmploymentStatusList = s ' Devolver datos como cadena
End Function

En las condiciones adecuadas se pueden almacenar en caché los propios recordsets ADO en el ámbito de aplicación o de sesión, con la salvedad de dos casos:

Si no se puede garantizar que se van a cumplir dichos requisitos, los recordsets ADO no se deben almacenar en caché. En la sugerencias Evitar almacenar en caché componentes no ágiles... y No almacenar en caché conexiones... que aparecen a continuación se discuten los principales riesgos que supone el almacenamiento de objetos COM en el ámbito de aplicación o de sesión.

En esta circunstancia, los datos permanecen allí hasta que el desarrollador decide modificarlos con la programación, hasta que termina la sesión o hasta que se reinicia la aplicación Web. ¿Qué ocurre si es necesario actualizar los datos? Para forzar manualmente una actualización de los datos de la aplicación, se puede llamar a una página ASP a la que sólo tenga acceso el administrador para que actualice los datos. Otra alternativa es actualizarlos automáticamente de forma periódica utilizando una función. El ejemplo siguiente almacena una marca de tiempo con los datos y los actualiza después de un intervalo de tiempo concreto.

<%
' error no mostrado...
Const UPDATE_INTERVAL = 300 ' Actualizar intervalo, en segundos

' Función para devolver lista de estado
Function GetEmploymentStatusList
   UpdateEmploymentStatus
   GetEmploymentStatusList = Application("EmploymentStatusList")
End Function

' Actualizar periódicamente los datos en caché
Sub UpdateEmploymentStatusList
   Dim d, strLastUpdate
   strLastUpdate = Application("LastUpdate")
   If (strLastUpdate = "") Or _
         (UPDATE_INTERVAL < DateDiff("s", strLastUpdate, Now)) Then

      ' Nota: se pueden obtener dos o más llamadas. Es suficiente y simplemente
      ' resultará en varias búsquedas innecesarias (existe una solución)

      ' La función FetchEmploymentStatusList (no se muestra)
      ' busca los datos en la BD y devuelve una matriz
      d = FetchEmploymentStatusList()

      ' Actualizar el objeto de aplicación. Utilizar Application.Lock()
      ' para garantizar la coherencia de los datos
      Application.Lock
      Application("EmploymentStatusList") = d
      Application("LastUpdate") = CStr(Now)
      Application.Unlock
   End If
End Sub

Para ver otro ejemplo consulte World’s Fastest ListBox with Application Data (en inglés).

Es necesario advertir que almacenar en caché matrices de gran tamaño en los objetos Session o Application no es muy recomendable. Antes de poder tener acceso a cualquiera de los elementos de la matriz, la semántica de los lenguajes de secuencias requiere que se realice una copia temporal de la matriz completa. Por ejemplo, si se almacena en caché una matriz de cadenas de 100.000 elementos que asigne códigos postales norteamericanos a estaciones meteorológicas locales en el objeto Application, ASP debe copiar primero las 100.000 estaciones meteorológicas antes de que se pueda extraer una sola cadena. En este caso, resultaría mucho mejor elaborar un componente personalizado con un método también personalizado que permitiera almacenar las estaciones, o bien, utilizar uno de los componentes de diccionario.

Un comentario adicional en la misma línea de no tirar las frutas frescas con las pochas: las matrices proporcionan un mecanismo rápido para la consulta y el almacenamiento de datos clave que son contiguos en la memoria. La indización de un diccionario constituye un proceso más lento que la de una matriz. Se debe seleccionar la estructura de datos que ofrezca el mejor rendimiento en cada caso.

Sugerencia 3: Almacenar en caché datos y HTML en los discos del servidor Web

Puede que en ocasiones el volumen de datos que se deben almacenar en la memoria caché sea demasiado elevado. No obstante, el término “demasiado” constituye una apreciación, ya que depende de la cantidad de memoria que se desea utilizar, así como del número de elementos que se quieren almacenar en caché y la frecuencia en la que dichos elementos se recuperan. En cualquier caso, si son demasiados los datos que se deben guardar, tenga en cuenta que siempre podrá almacenarlos en archivos XML o de texto en los discos duros de los servidores Web. Puede combinar el almacenamiento en discos y en memoria para crear una óptima estrategia de almacenamiento en caché para su sitio.

Hay que tener en cuenta que cuando se está analizando el rendimiento de una única página ASP, la recuperación de los datos del disco puede que no resulte una operación más rápida que su recuperación desde la base de datos. Sin embargo, el almacenamiento en caché reduce la carga que deben soportar la base de datos y la red. En condiciones de cargas mayores se mejorará considerablemente el rendimiento general. El almacenamiento en caché puede ser muy útil cuando se desean almacenar los resultados de una consulta costosa, como es el caso de las tablas múltiples, de procedimientos almacenados más complejos o de grandes conjuntos de resultados. Pero, como siempre, se deben comparar otros esquemas.

ASP y COM proporcionan algunas herramientas que permiten construir esquemas de almacenamiento basados en discos. Las funciones Save() y Open() del recordset ADO guardan y cargan los recordsets desde el disco. Se pueden utilizar ambos métodos para volver a escribir el código de muestra de la anterior sugerencia, Almacenar en caché datos utilizados frecuentemente en el objeto de aplicación..., sustituyendo Save() por el código que desarrolla el objeto Application.

Existen otros componentes que funcionan con archivos:

  • Scripting.FileSystemObject (en inglés), que permite crear, leer y escribir archivos.
  • MSXML, el analizador de Microsoft® XML que se incluye con Internet Explorer, que admite el almacenamiento y la carga de documentos XML.
  • El objeto LookupTable (ejemplo, utilizado en MSN) supone una elección más que acertada para la carga de listas simples desde el disco.

Por último, otra alternativa posible es el almacenamiento en caché de la presentación de los datos en un disco en lugar de los propios datos. El HTML procesado previamente puede almacenarse en disco como un archivo de extensión .htm o .asp, archivos a los que los hipervínculos pueden conducir directamente. Se puede automatizar el proceso de generación de HTML utilizando algunas de las herramientas del mercado como XBuilder (en inglés) o las características para la publicación en Internet de Microsoft® SQL Server™. Otra opción es #incluir miniprogramas de HTML en un archivo .asp. También se pueden leer los archivos HTML desde el disco utilizando FileSystemObject, o bien, emplear XML para el procesamiento previo (en inglés).

Sugerencia 4: Evitar almacenar en caché componentes no ágiles en los objetos de aplicación o de sesión

Mientras que el almacenamiento en caché de los datos en el objeto Application o Session puede ser una excelente idea, el mismo tipo de almacenamiento de objetos COM puede suponer ciertas dificultades. Puede resultar tentador guardar objetos COM utilizados frecuentemente en los objetos Application o Session. Desafortunadamente, muchos de estos objetos COM, incluyendo aquellos desarrollados en Visual Basic 6.0 o posterior, pueden ocasionar serios cuellos de botella cuando se almacenan en los objetos Application o Session.

Más específicamente, cualquier componente que no sea ágil (en inglés) puede producir cuellos de botella en los objetos Session o Application. Un componente ágil es un componente marcado como ThreadingModel=Both que agrega el ordenamiento de subprocesamiento libre (FTM) o un componente marcado como ThreadingModel=Neutral. (El modelo Neutral es una novedad en Windows® 2000 y COM+). Los siguientes componentes no son ágiles:

  • Componentes de subprocesamiento libre (a menos que agreguen el FTM).
  • Componentes de subprocesamiento controlado.
  • Componentes de subprocesamiento único.

Los componentes configurados (Microsoft Transaction Server (MTS)/biblioteca COM+ y aplicaciones/paquetes del servidor) no son ágiles a menos que se consideren Neutral. Los componentes de subprocesamiento controlado, entre otros componentes no ágiles, ofrecen mejores resultados en el ámbito de página (es decir, se crean y se destruyen en una sola página ASP).

En IIS 4.0, un componente marcado como ThreadingModel=Both se consideraba ágil. Esto ya no es suficiente en IIS 5.0. El componente no sólo debe marcarse como Ambos, sino que debe agregar el FTM. El artículo sobre agilidad (en inglés) describe cómo hacer que los componentes de C++ escritos con la biblioteca de plantillas activa (ATL) agreguen el FTM. Tenga en cuenta que si el componente almacena en caché los punteros de la interfaz, también dichos punteros deben ser ágiles o deben almacenarse en la tabla de interfaz global COM (GIT). Si no se puede volver a compilar un componente marcado como Ambos para agregar el FTM, se podrá marcar dicho componente como ThreadingModel=Neutral. De forma alternativa, si no desea que IIS realice la comprobación de la agilidad (es decir, desea que los componentes no ágiles se almacenen en el ámbito de aplicación o de sesión), puede establecer AspTrackThreadingModel como True en la metabase. Cambiar AspTrackThreadingModel no es una operación muy recomendable.

IIS 5.0 enviará un mensaje de error si se intenta almacenar un componente no ágil creado con Server.CreateObject en el objeto Application. Se puede solucionar el problema utilizando <object runat=server scope=application ...> en Global.asa, aunque no es recomendable, ya que conduce al ordenamiento y serialización, como se explica a continuación.

¿Qué es lo que ocurre si se almacenan en caché componentes no ágiles? Un componente de este tipo almacenado en el objeto Session “bloqueará” la sesión a un subproceso de trabajo ASP. ASP mantiene un conjunto de procesos de trabajo que se ocupan de las solicitudes. Normalmente el primer subproceso de trabajo que estuviera libre se ocuparía de la nueva solicitud. Si se bloquea una sesión a un subproceso, la solicitud debe esperar hasta que el subproceso asociado se encuentre disponible. A continuación presentamos una analogía que bien puede servir para explicarlo: uno va al supermercado, selecciona varios tipos de artículos comestibles y abona el importe en la caja nº 3. Imagine que a partir de ese momento, siempre que compre artículos en ese supermercado, debe abonarlos en la misma caja nº 3, aunque haya menos personas esperando en otras cajas o algunas de ellas se encuentre vacía.

El almacenamiento de componentes no ágiles en el ámbito de aplicación tiene un efecto aún peor sobre el rendimiento. ASP debe crear un subproceso espacial para ejecutarlos, lo que tiene dos consecuencias: todas las llamadas deben realizarse en serie y se deben ordenar en dicho subproceso. El ordenamiento supone que los parámetros deben almacenarse en un área compartida de memoria; se realiza un costoso cambio de contexto en el subproceso especial; se ejecuta el método del componente; se ordenan los resultados en el área compartida; y un cambio adicional de contexto devuelve el control al subproceso original. La serialización implica que los métodos se ejecutan de uno en uno. No se puede dar la circunstancia de que dos subprocesos de trabajo ASP ejecuten simultáneamente métodos en el componente compartido, ya que esto acabaría con la concurrencia, especialmente en equipos con varios procesadores. Y aún peor, todos los componentes no ágiles en el ámbito de aplicación comparten un subproceso (“Host STA”), de forma que los efectos de la serialización son aún más marcados.

¿Resulta demasiado confuso? Aquí tiene algunas reglas generales. Si está desarrollando objetos en Visual Basic (6.0) o posterior, no debe almacenarlos en caché en los objetos Application o Session. Si desconoce el modelo de subprocesamiento de un objeto, es mejor que no lo almacene. En lugar de almacenar objetos no ágiles debe crearlos y liberarlos en cada página. Los objetos se ejecutarán directamente en el subproceso de trabajo, con lo que no se producirán ni la serialización ni la ordenación. El rendimiento será el adecuado si los objetos COM se ejecutan en un cuadro de IIS y si no tardan demasiado en iniciarse y destruirse. Tenga en cuenta que los objetos de subprocesamiento único no deben utilizarse de este modo. Preste atención: ¡VB puede crear objetos de subprocesamiento único! Si debe utilizar objetos de subprocesamiento único de esta manera (como una hoja de cálculo de Microsoft Excel), no espere un buen rendimiento.

Los recordsets ADO pueden almacenarse en caché de forma segura cuando ADO se marca como de subprocesamiento libre. Para marcar ADO como de subprocesamiento libre, utilice el archivo Makfre15.bat, que se ubica normalmente en el directorio \\Archivos de programa\Archivos comunes\System\ADO.

Advertencia: ADO no debe marcarse como de subprocesamiento libre si no se utiliza Microsoft Access como base de datos. El recordset ADO siempre debe estar desconectado. Por regla general, si no se puede controlar la configuración de ADO del sitio (por ejemplo, el caso de los fabricantes independientes de software [ISV], que distribuyen aplicaciones Web a los clientes y éstos de ocupan de sus propias configuraciones), probablemente sea mejor que no almacene en caché los recordsets.

Los componentes de diccionario también se incluyen en la categoría de objetos ágiles. El objeto LookupTable carga sus datos desde el archivo de datos y resulta muy útil para los datos de cuadros combinados y como información de configuración. PageCache de Duwamish Books (en inglés) proporciona la semántica del diccionario, al igual que el diccionario Caprock. Estos objetos, o derivados, pueden formar la base de una eficaz estrategia de almacenamiento. Tenga en cuenta que el objeto Scripting.Dictionary NO es ágil y que no debe almacenarse en el ámbito de aplicación o de sesión.

Sugerencia 5: No almacenar en caché conexiones de la base de datos en los objetos de aplicación o de sesión

Almacenar en caché conexiones ADO no es por lo general una buena estrategia. Si un objeto Connection se almacena en el objeto Application y se utiliza en todas las páginas, éstas competirán por utilizar la conexión. Si el objeto Connection se almacena en el objeto Session ASP, se creará una conexión a la base de datos para cada usuario. Con esto se pierden los beneficios que suponía la agrupación de conexiones y se incrementa en exceso la carga tanto en el servidor Web como en la base de datos.

En lugar de almacenar las conexiones a la base de datos, una alternativa mejor es crear y destruir los objetos ADO en cada una de las páginas ASP que los utilizan. Se trata de un mecanismo muy eficaz ya que IIS incorpora la agrupación de conexiones. De forma más precisa, IIS habilita automáticamente la agrupación de conexiones de OLEDB y ODBC. Así se garantiza que la creación y posterior destrucción de las conexiones de cada página ofrece resultados positivos.

Dado que los recordsets almacenan una referencia a la conexión a la base de datos, no se deben almacenar en caché en el objeto Application o Session. No obstante, sí que se pueden almacenar en caché de forma segura los recordsets desconectados, ya que estos últimos no guardan referencia alguna a la conexión de datos. Para desconectar un recordset, siga los dos pasos siguientes:

    Set rs = Server.CreateObject("ADODB.RecordSet")
    rs.CursorLocation = adUseClient  ' paso 1

    ' Poblar el recordset con datos
    rs.Open strQuery, strProv

    ' desconectar el recordset del proveedor de datos y el origen de datos
    rs.ActiveConnection = Nothing    ' paso 2

Puede obtener más información sobre la agrupación de conexiones en las referencias a ADO y SQL Server.

Sugerencia 6: Utilizar prudentemente el objeto de sesión

Después de haber roto una lanza en favor de las virtudes del almacenamiento en caché en las aplicaciones y en las sesiones, vamos a sugerir evitar el objeto Session. Las sesiones pueden suponer ciertas dificultades cuando se utilizan en sitios con mucha actividad, como veremos más adelante. Por sitios con mucha actividad generalmente entendemos aquellos que solicitan cientos de páginas por segundo o los que visitan simultáneamente miles de usuarios. Esta sugerencia nos parece aún más importante en el caso de los sitios que se deben escalar horizontalmente, es decir, aquellos que utilizan varios servidores para acomodar la carga o para implementar la tolerancia a los errores. En sitios más pequeños, como los de una intranet, las ventajas que proporcionan las sesiones bien compensan los inconvenientes.

Recapitulemos: ASP crea automáticamente una sesión para cada usuario que realiza la solicitud al servidor Web. Cada sesión dispone de casi 10 KB de memoria extra (siempre por encima de la cantidad de datos almacenados en la sesión) y ralentiza un poco todo el proceso. La sesión permanece viva durante un período de tiempo de espera configurable, que generalmente es de 20 minutos.

El principal problema que plantean las sesiones no es el rendimiento, sino la escalabilidad. Las sesiones no se extienden a los servidores Web; una vez se ha creado una sesión en un servidor, sus datos permanecen allí. Esto significa que si se utilizan las sesiones en una granja Web, se debe diseñar una estrategia para las solicitudes de cada usuario de forma que siempre se dirijan al servidor en el que existe la sesión del usuario. Esto se denomina “pegar” un usuario al servidor Web. El término “sesiones pegadas” deriva de él. Si se produjera algún error en el servidor Web, se perdería el estado de la sesión de los usuarios que se han “pegado”, ya que las sesiones no se almacenan en el disco.

Las estrategias de implementación de este tipo de sesiones incluyen soluciones de hardware y software como el equilibrio de carga para redes (en inglés) en Windows 2000 Advanced Server y Local Director de Cisco, que pueden implementarlas, a expensas de cierta escalabilidad. Estas soluciones no son perfectas. Confirmar una solución de software propia en este punto no es muy recomendable (solíamos utilizar filtros ISAPI, la eliminación de URL, etc.).

El objeto Application tampoco se extiende a los servidores; si es necesario compartir y actualizar los datos de la aplicación por la granja Web, será preciso utilizar la base de datos central. No obstante, se debe señalar que los datos de una aplicación de sólo lectura aún son de utilidad en las granjas Web.

Casi con toda seguridad, en sitios de misión crítica se deseará distribuir al menos dos servidores Web, aunque simplemente sea por incrementar el tiempo de actividad (mantenimiento del servidor y control de errores). Por otra parte, para diseñar una aplicación de misión crítica se deben implementar las “sesiones pegadas” o simplemente evitar las sesiones de cualquier tipo, así como cualquier otra técnica de control del estado que almacene a los usuarios en servidores Web por separado.

Si no desea utilizar sesiones, asegúrese de desactivarlas. Esta operación se puede realizar, en el caso de la aplicación, con el Administrador de servicios de Internet (consultar la documentación de ISM). Si, por el contrario, decide utilizar sesiones, siempre puede minimizar su impacto en el rendimiento de varias formas distintas.

Puede mover el contenido que no requiera sesiones (por ejemplo, pantallas de ayuda, áreas de visitantes, etc.) a otra aplicación ASP en la que se hayan desactivado las sesiones. Utilizando el esquema de página a página, se sugiere a ASP que el objeto de sesión no es necesario en una página concreta; utilice la directiva siguiente situada en la parte superior de la página ASP:

<% @EnableSessionState=False %>

Una buena razón por la que conviene utilizar esta directiva es que las sesiones crean un interesante problema con los conjuntos de marcos. ASP garantiza que sólo se ejecutará una solicitud de la sesión por vez. De esta manera, si el explorador solicita varias páginas para un sólo usuario, la sesión sólo se ocupará de una solicitud ASP; con ello se evitan los problemas ocasionados por el subprocesamiento múltiple cuando se tiene acceso al objeto Session. Desafortunadamente, se obtiene como resultado que todas las páginas de un conjunto de marcos aparecen en serie, una tras otra, en lugar de hacerlo simultáneamente. Puede que el usuario se vea obligado a esperar algún tiempo hasta que aparezcan todos los marcos. La moraleja de esta pequeña historia es la siguiente: si ciertas páginas de conjuntos de marcos no dependen de la sesión, es necesario informar de ello a ASP utilizando la directiva @EnableSessionState=False.

Como alternativa a la utilización del objeto Session existen varias opciones que permiten controlar el estado de la sesión. Con tamaños reducidos (menos de 4 KB), generalmente recomendamos que se utilicen las cookies, las variables QueryString y las de formulario oculto. Cuando se trata de tamaños de datos mayores como los de un carro de la compra, la elección más adecuada es una base de datos central. El tema de las técnicas de control de estado en las granjas Web ha generado mucha literatura; se pueden consultar algunas referencias en la sección relativa al estado de la sesión.

Sugerencia 7: Encapsular el código en los objetos COM

Si se dispone de mucho VBScript o JScript, siempre se puede mejorar el rendimiento moviendo el código a un objeto COM compilado. El código compilado generalmente se ejecuta con mayor rapidez que el interpretado. Los objetos COM compilados pueden tener acceso a otros objetos COM gracias a un “enlace en tiempo de compilación”, un método más eficaz para invocar métodos de objetos COM que el de “enlace en tiempo de ejecución” que emplea la secuencia.

Existen más ventajas (además de la mejora del rendimiento) al encapsular el código en objetos COM:

  • Los objetos COM permiten separar la lógica de presentación de la lógica empresarial.
  • Los objetos COM permiten reutilizar el código.
  • Muchos desarrolladores encuentran que el código escrito en VB, C++ o Visual J++ es mucho más sencillo de depurar que ASP.

Los objetos COM también tienen sus inconvenientes, incluyendo el tiempo de desarrollo inicial y la necesidad de nuevas habilidades de programación. Encapsular pequeñas cantidades de ASP puede ir en detrimento del rendimiento en lugar de mejorarlo. Esto ocurre normalmente cuando una pequeña cantidad de código ASP se incluye en el objeto COM. En este caso, la carga que supone crear e invocar el objeto COM supera a las ventajas de utilizar código compilado. Se trata de una cuestión de ensayo y error el determinar qué combinación de secuencia ASP y código de objetos COM genera el mejor resultado en cuanto a rendimiento. Microsoft ha mejorado enormemente el rendimiento de las secuencias y de ADO en Windows 2000/IIS 5.0 en comparación con Windows NT® 4.0/IIS 4.0. De esta forma, la ventaja del rendimiento que se disfrutaba al utilizar el código compilado sobre el código ASP se ha reducido con la introducción de IIS 5.0.

Para conocer algunos interesantes debates sobre las ventajas e inconvenientes de utilizar objetos COM en ASP, consulte Guía del componente ASP y Programming Distributed Applications with COM and Microsoft Visual Basic 6.0 (en inglés). Si desea distribuir los componentes COM, es importante que realice una prueba de carga (en inglés) de los mismos. De hecho, se deberían realizar por norma pruebas de este tipo en todas las aplicaciones ASP.

Sugerencia 8: Adquirir los recursos en el último momento y liberarlos cuanto antes

Se trata de una pequeña sugerencia. En general, es mejor adquirir los recursos tarde y liberarlos pronto. Esto se refiere tanto a objetos COM como a los controladores de archivos y demás recursos.

Las conexiones y recordsets ADO son los candidatos idóneos para esta optimización. Cuando haya terminado de utilizar un recordset, por ejemplo, tras crear una tabla con sus datos, se debe liberar inmediatamente, en lugar de esperar hasta el final de la página. Establecer la variable de VBScript como Nothing es la mejor opción. No permita que el recordset se quede fuera de ámbito. Libere, además, todos los objetos Command o Connection relacionados. (No olvide llamar a Close() en los recordsets o conexiones antes de establecerlos como = Nothing). De esta manera se reduce el intervalo de tiempo durante el cual la base de datos debe hacer juegos malabares con los recursos y se libera la conexión de la base de datos a la agrupación de conexiones tan pronto como es posible.

Sugerencia 9: La ejecución fuera de proceso permite el equilibrio entre el rendimiento y la confiabilidad

Tanto ASP como MTS/COM+ presentan una serie de opciones de configuración que permiten compensar la confiabilidad y el rendimiento. Es preciso entender dichas compensaciones cuando se está construyendo y distribuyendo una aplicación.

Opciones de ASP

Las aplicaciones ASP pueden configurarse de forma que se ejecuten de tres formas distintas. Con IIS 5.0, el “nivel de aislamiento” de la terminología se ha introducido para describir dichas opciones. Los tres valores del nivel de aislamiento son bajo, medio y alto:

  • Aislamiento bajo. Se admite en todas las versiones de IIS y se trata del método más rápido. Ejecuta ASP en Inetinfo.exe, el proceso primario de IIS. Si se produjera un error en la aplicación ASP, éste se trasladaría a IIS. (Para reiniciar IIS en la versión 4.0, los Webmasters deberían supervisar el sitio empleando herramientas como InetMon y lanzar archivos por lotes para reiniciar el servidor en caso de error. IIS 5.0 introduce el proceso de reinicio confiable (en inglés), que permite reiniciar automáticamente un servidor en el que se ha producido un error).
  • Aislamiento medio. IIS 5.0 introduce este nuevo nivel, que se denomina como fuera de proceso, ya que ASP se ejecuta fuera de proceso de IIS. En el aislamiento medio, todas las aplicaciones ASP configuradas para ejecutarse como medias comparten un único espacio de proceso. Esto reduce el número de procesos que son necesarios que ejecutar varias aplicaciones ASP fuera de proceso en un cuadro. Medio corresponde al nivel de aislamiento predeterminado en IIS 5.0.
  • Aislamiento alto. Admitido en IIS 4.0 e IIS 5.0, el aislamiento alto también está fuera de proceso. Si se produjera un error en ASP, el servidor Web no se vería afectado. La aplicación ASP se reiniciaría automáticamente en la siguiente solicitud ASP. Con el aislamiento alto, cada aplicación ASP configurada para ejecutarse como alta lo hace en su propio espacio de proceso. De esta forma se protegen las aplicaciones ASP unas de otras. El principal problema que presenta este sistema es que requiere un proceso independiente para cada aplicación ASP. También puede suponer un incremento en la carga que se debe soportar cuando se deben albergar docenas de aplicaciones en un cuadro.

Entonces, ¿cuál es la opción más adecuada? En IIS 4.0 se podía observar un declive en el rendimiento cuando la aplicación se ejecutaba fuera de proceso. Se ha trabajado a conciencia en este tema en IIS 5.0 y se ha logrado minimizar el coste de la ejecución de las aplicaciones ASP fuera de proceso. De hecho, en la mayoría de las comprobaciones, las aplicaciones ASP fuera de proceso en IIS 5.0 se ejecutan más rápidamente que las aplicaciones en proceso en IIS 4.0. No obstante, las aplicaciones en proceso generan (con un nivel de aislamiento bajo) el mejor rendimiento en ambas plataformas. A pesar de esta circunstancia, resulta difícil obtener beneficios del nivel bajo si la frecuencia de aciertos o la salida máxima son relativamente bajas. Por tanto, es mejor no alcanzar el nivel de aislamiento bajo hasta que se necesiten cientos o miles de páginas por segundo y por servidor Web. Como siempre, se deben comprobar las distintas configuraciones para determinar las compensaciones se que desean obtener.

Nota: cuando se ejecutan aplicaciones ASP fuera de proceso (con aislamiento medio o alto), se ejecutan en MTS en NT4 y en COM+ en Windows 2000. Es decir, en NT4 se ejecutan desde Mtx.exe y, en Windows 2000, por su parte, lo hacen en DllHost.exe. Se pueden ver los procesos en el Administrador de tareas. También se pueden conocer los detalles de la configuración de los paquetes MTS o de las aplicaciones COM+ por parte de IIS para aplicaciones ASP fuera de proceso.

Opciones de COM

Los componentes COM también presentan tres opciones de configuración que, sin embargo, no son completamente análogas a las de ASP. Los componentes COM pueden estar: “no configurados”, configurados como aplicaciones de biblioteca o configurados como aplicaciones de servidor. No configurado significa que el componente no se ha registrado con COM+ y que se ejecutará en el espacio de proceso de quien realizó la llamada, es decir, se encuentran “en proceso”. Las aplicaciones de biblioteca también se encuentran en proceso, sin embargo se benefician de los servicios de COM+, incluyendo la seguridad, las transacciones y el soporte del contexto. Las aplicaciones de servidor se configuran para ejecutarse en su propio espacio de proceso.

Puede que vea unos beneficios importantes en el uso de componentes no configurados comparados con las aplicaciones de biblioteca, lo que sí está claro es que verá unos beneficios mucho mayores en cuanto al rendimiento si utiliza estas últimas en lugar de las aplicaciones de servidor. Esto se debe a que las aplicaciones de biblioteca se ejecutan en el mismo proceso que ASP, mientras que las del servidor lo hacen en su propio espacio de proceso. Las llamadas de inter-proceso resultan mucho más costosas que las llamadas en proceso. Asimismo, cuando se pasan datos, por ejemplo, recordsets, entre procesos, todos ellos se deben copiar entre los dos procesos.

¡He aquí un problema! Cuando se utilizan aplicaciones de servidor COM, si se pasan objetos entre ASP y COM, es preciso asegurarse de que dichos objetos implementan el denominado “subprocesamiento por valor” o MBV, ya que los que lo hacen se copian a sí mismos de un proceso a otro. Esto resulta mucho mejor que la otra alternativa, que consistiría en que el objeto debe permanecer en el proceso del creador y que el resto de los procesos llamarían repetidamente al proceso que se está creando para que utilice el objeto. Los recordsets ADO desconectados se subprocesarán por valor; los conectados no. Scripting.Dictionary no implementa MBV y no debería pasarse entre procesos. Por último, enviamos un mensaje a los programadores de VB: MBV NO se obtiene pasando el parámetro ByVal. El autor del componente original implementaría MBV.

¿Qué se puede hacer?

Si tuviéramos que recomendar una configuración con una compensación razonable en cuanto a rendimiento y confiabilidad, sería la siguiente:

  • En IIS 4.0, utilizar el nivel de aislamiento bajo de ASP y los paquetes de servidor de MTS.
  • En IIS 5.0, utilizar el nivel de aislamiento medio de ASP y aplicaciones de biblioteca de COM+.

Estas son únicamente unas líneas generales; las empresas dedicadas a ello generalmente ejecutan ASP con un nivel de aislamiento medio o alto, mientras que los servidores Web de un único propósito pueden ejecutarse con un aislamiento bajo. Analice las compensaciones y decida la configuración que se ajusta en mayor medida a sus necesidades.

Sugerencia 10: Utilizar Option Explicit

Utilice Option Explicit en los archivos .asp. Situada en la parte superior del archivo .asp, esta directiva fuerza al desarrollador a declarar todas las variables que se van a emplear. Muchos programadores consideran que es de gran utilidad para depurar las aplicaciones, ya que evita la posibilidad de escribir incorrectamente el nombre de una variable o de crear accidentalmente otras nuevas (por ejemplo, MyXLMString=... en lugar de MyXMLString=).

Quizás algo aún más importante, resulta que las variables declaradas son más rápidas que las no declaradas. El tiempo de ejecución de las secuencias hace referencia por nombre a las variables no declaradas cada vez que se utilizan. A las variables declaradas, por otra parte, se asigna un ordinal ya sea durante el tiempo de compilación o el de ejecución. Por consiguiente, el ordinal hace referencia a las variables declaradas. Debido a que Option Explicit fuerza la declaración de las variables, garantiza que todas ellas se declaran para, de esta forma, facilitar el acceso a las mismas.

Sugerencia 11: Utilizar variables locales en las subrutinas y las funciones

Las variables locales son aquellas que se declaran con las subrutinas y las funciones. Dentro de una subrutina o función, el acceso a una variable local es mucho más rápido que a una global. La utilización de las variables también tiende a hacer que el código presente una mayor claridad, por lo que se recomienda su uso siempre que sea posible.

Sugerencia 12: Copiar datos utilizados frecuentemente en las variables de la secuencia

Cuando se tiene acceso a los objetos COM en ASP, se deben copiar los datos de objetos utilizados frecuentemente en las variables de la secuencia. De esta forma se reduce el número de llamadas a los métodos COM, que resultan relativamente costosos comparados con el acceso a las variables de las secuencias. Obtener acceso a los objetos Collection y Dictionary reduce el número de costosas consultas que es preciso llevar a cabo.

Por regla general, si se desea obtener acceso a datos de objetos más de una vez, éstos se deben introducir en una variable de secuencia. Los protagonistas principales a los que va dirigida esta optimización son las variables de solicitud (Form y QueryString). Por ejemplo, puede que su sitio pase una variable QueryString denominada UserID. Supongamos que se hace referencia a UserID una docena de veces en una página concreta. En lugar de llamar a Request("UserID") doce veces, es mejor asignar UserID a una variable en la parte superior de la página ASP y, a continuación, utilizar dicha variable por toda la página. De esta manera se evitarán 11 llamadas al método COM.

En la práctica, el acceso a las propiedades o métodos COM puede resultar costoso en apariencia. A continuación se proporciona un ejemplo de código muy común (desde el punto de vista sintáctico):

Foo.bar.blah.baz = Foo.bar.blah.qaz(1)
If Foo.bar.blah.zaq = Foo.bar.blah.abc Then ' ...

Esto es lo que sucede cuando se ejecuta el código:

  1. La variable Foo se resuelve como un objeto global.
  2. La variable bar se resuelve como miembro de Foo, que resulta ser una llamada al método COM.
  3. La variable blah se resuelve como miembro de Foo.bar. Este también resulta ser una llamada al método COM.
  4. La variable qaz se resuelve como miembro de foo.bar.blah. Sí, de nuevo una llamada al método COM.
  5. Invoque Foo.bar.blah.quaz(1). Otra llamada al método COM. ¿Se hace una idea?
  6. Siga los pasos 1-3 otra vez para resolver baz. El sistema desconoce si la llamada a qaz ha cambiado el modelo de objeto, por lo que se deben volver a realizar los pasos 1-3 para resolver baz.
  7. Resuelva baz como miembro de Foo.bar.blah. Introduzca la propiedad.
  8. Vuelva a seguir los pasos 1-3 para resolver zaq.
  9. Siga de nuevo los pasos 1-3 y resuelva abc.

Como se puede ver, se trata de un sistema terriblemente ineficaz (y lento). La forma rápida de escribir el código en VBScript es:

Set myobj = Foo.bar.blah ' resolver blah UNA VEZ
Myobj.baz = myobj.qaz(1)
If Myobj.zaq = Myobj.abc Then '...

Si se utiliza VBScript 5.0 o posterior, se puede escribir utilizando la instrucción With:

With Foo.bar.blah
    .baz = .qaz(1)
    If .zaq = .abc Then '...
    ...
End With

Tenga en cuenta que esta sugerencia también se puede aplicar a la programación en VB.

Sugerencia 13: Evitar redimensionar las matrices

Se debe intentar evitar la redimensión de las matrices con Redim. Por lo que se refiere al rendimiento, si se dispone de un equipo restringido por el tamaño de la memoria física, resulta mejor establecer la dimensión inicial de la matriz en el peor de los casos posible, o bien, establecerla en la situación más óptima y redimensionar cuando sea necesario. Esto no significa que simplemente se deben asignar un par de megabytes de memoria si se sabe que no se va a necesitarla.

El código que aparece a continuación muestra la utilización gratuita de Dim y Redim.

<%
Dim MyArray()
Redim MyArray(2)
MyArray(0) = "hola"
MyArray(1) = "adiós"
MyArray(2) = "hasta pronto"
...
' otro código en el que es necesario más espacio, entonces ...
Redim Preserve MyArray(5)
MyArray(3) = "más material"
MyArray(4) = "aún más material"
MyArray(5) = "todavía mucho más material"
%>

Es mucho más fácil dimensionar la matriz con Dim al tamaño correcto inicialmente (en este caso, 5), que redimensionarla con Redim para aumentar su tamaño. Puede que se utilice algo de memoria (si al final no se utilizan todos los elementos), pero el incremento en la velocidad que se obtiene bien compensa esta inversión.

Sugerencia 14: Utilizar el búfer de respuesta

Se puede almacenar en búfer la salida de una página completa activando la opción de “búfer de respuesta”. Se minimiza la cantidad de veces que es necesario escribir en el explorador y se mejora el rendimiento general. Cada escritura supone una sobrecarga (tanto en IIS como en la cantidad de datos que se envían), por tanto, cuantas menos escrituras sea preciso realizar, mejor. TCP/IP ofrece mejores resultados cuando se envían varios bloques de datos grandes que cuando se deben enviar muchos bloques pequeños debido al inicio lento (en inglés) y al algoritmo de Nagle (en inglés) (empleados para reducir las sobrecarga de la red).

Existen dos maneras de activar el búfer de respuesta. En primer lugar, se puede activar para toda la aplicación utilizando para ello el Administrador de servicios de Internet. Se trata del enfoque recomendado, por lo que el búfer de respuesta se encuentra activado de forma predeterminada en las aplicaciones ASP en IIS 4.0 y IIS 5.0. En segundo lugar, página a página; es decir, se puede activar el búfer de respuesta introduciendo la siguiente línea de código en la parte superior de la página ASP:

<% Response.Buffer = True %>

Esta línea de código debe ejecutarse antes de que se escriba cualquier dato de repuesta en el explorador (es decir, antes de que aparezca el HTML en la secuencia ASP y antes de que se envíe cualquier cookie con la colección Response.Cookies). En líneas generales, resulta mucho mejor activar el búfer de respuesta en toda la aplicación, ya que así se evita la necesidad de escribir la anterior línea de código en cada página.

Response.Flush

Uno de los problemas que se plantean con el búfer de respuesta es los usuarios perciben que la respuesta que obtienen de las páginas ASP es menor (aunque el tiempo global de respuesta se haya mejorado) ya que deben esperar a que se genere toda la página antes de poder ver algo. En el caso de las páginas que tardan en cargarse, se puede activar el búfer de respuesta con Response.Buffer = False. Sin embargo, una estrategia mucho más eficaz sería utilizar el método Response.Flush, que descarga todo el HTML de ASP en el explorador. Por ejemplo, después de que aparezcan 100 filas de una tabla de 1.000, ASP puede llamar a Response.Flush para que fuerce los resultados y que éstos aparezcan en el explorador; de esta forma el usuario puede ver las primeras 100 filas antes de que las restantes estén listas. Esta técnica puede proporcionar además lo mejor de ambos métodos: el búfer de respuesta combinado con la presentación gradual de los datos en el explorador.

(Es importante señalar que en el ejemplo anterior de una tabla de 1.000 filas, muchos exploradores no empezarán a cargar la tabla hasta que vean la etiqueta de cierre </table>. Compruebe los exploradores para obtener información sobre compatibilidad. Para solucionar este problema, intente dividir la tabla en varias más pequeñas con menos filas cada una de ellas y llame a Response.Flush después de cada tabla. Las últimas versiones de Internet Explorer mostrarán las tablas antes de descargarlas completamente y lo harán a una velocidad considerable especialmente si se especifica la anchura de columna previamente; con esto, Internet Explorer se evita tener que calcular la anchura de la columna en función del contenido de cada celda).

Otro de los problemas más comunes que presenta el búfer de respuesta es que puede utilizar gran parte de la memoria del servidor cuando genera páginas muy extensas. Dejando a un lado la cuestión de si es recomendable o no generar páginas extensas, también se puede hacer frente a este problema utilizando Response.Flush.

 

 



 

¿Estas empezando y este articulo es muy complejo para tí?
Empieza por el principio, visita Ejemplos Básicos

Puedes obtener un listado completo de todos los artículos y ejemplos de ASP en http://www.asptutor.com/asp/todoslosarticulos.asp
 

Valora este articulo   Malo Excelente  
140 usuarios han valorado este articulo. Valoracion media:

Nota: Para cualquier consulta u opinión sobre este articulo puedes usar los foros

 

 

AspTutor lo hacemos entre todos ¿Como vas a colaborar hoy?


Google

 

Descargas de manuales¦ Ejemplos de código ¦ Artículos mas visitados ¦ Envía tu articulo ¦ Foros ¦
  Libro de visitas ¦Crea un enlace con ASPTutor 
 

    © 2001-Hasta hoy  Pedro Rufo Martín  contactar