You are on page 1of 148

UNIVERSIDAD DE VALLADOLID ESCUELA TÉCNICA SUPERIOR DE INGENIEROS DE TELECOMUNICACIÓN

I.T. TELECOMUNICACIONES SISTEMAS DE TELECOMUNICACIÓN FEBRERO 2010

PROYECTO FIN DE CARRERA

AUTOR: PABLO NAVARRETE ALMARZA TUTORES: JUAN PABLO DE CASTRO FERNÁNDEZ RICARDO GARCÍA MARTÍN

BENCHMARKING DE SERVICIOS WMS-C

INDICE

0. Introducción                                                                                                                                       1                   0.1 Introducción a los servicios de mapas                                                                    1  0.2 Objetivos del proyecto                                                                                                  2  0.3 Estructura de la memoria                                                                                          3 1. Servicios Web de Mapas                                                                                                                5                      1.1 Servicio Web Map Service (WMS)                                                                         5 1.2 Propuesta Web Map Tiling Service (WMTS)                                                        7 1.3 Propuesta WMS­C                                                                                                         7 2. Implementaciones WMS­C                                                                                                         10                    2.1 Cacheado en WMS                                                                                                        10 2.2 TileCache                                                                                                                         11 2.3 Geowebcache                                                                                                                    11 2.4 WMSCwrapper                                                                                                                   12

3. Benchmarking de servicios Web de Mapas                                                                          16 4. Desarrollo de la aplicación de Benchmarking                                                                      20         4.1 Objetivos de la aplicación                                                                                          20 4.2 Estructura de la aplicación                                                                                         20 4.2.1 Archivo de Jmeter                                                                                        20 4.2.2 Generador de Bboxes                                                                                  23 4.2.3 Reporte de resultados                                                                                  34 4.2.4 Estructura Maven­SVN                                                                            39 4.2.5 Scripts                                                                                                                40 4.2..6 Resumen                                                                                                        42 4.3 Conclusiones                                                                                                                    43 5. Análisis de Resultados                                                                                                                   44 6. Conclusiones y líneas futuras                                                                                                      75 Bibliografía  Apéndice I. Instalación de las cachés  Apéndice II. Manual de uso de la aplicación  ANEXOS: Código completo de la aplicación

0

INTRODUCCIÓN

 con el telón de  fondo del impresionante desarrollo del hardware y el acceso del gran público a ordenadores cada  vez mas manejables y potentes a precios asequibles. Los Sistemas de Información Geográfica (SIG o GIS en su nomenclatura inglesa) definidos como  una integración de software hardware y datos geográficos. nacieron en Canadá [2] en el año 1962  cuando   el  Canadian   Geographic   Information   System   (CGIS)   cartografió   parte   de   su   territorio  nacional.   y   su   uso   quedó   reducido   al   entorno   gubernamental   y  administrativo  Posteriores proyectos como los llevados a cabo por la Universidad de Harvard en la década de los  70 o por M&S Computing en los ochenta.   una   codificación   de   líneas   en  "arcos" que poseían una verdadera topología integrada y que almacenaba los atributos de cada  elemento y la información sobre su localización en archivos separados.   puesto   que   permitía   superponer   capas   de   información..0. soportaba un sistema nacional de  coordenadas   que   abarcaba   todo   el   continente   norteamericano. Este sistema jamas llegó a  estar   disponible   al   público   general.     con el fin de llevar a cabo una gestión integral de sus recursos naturales  mediante el uso de factores de clasificación para poder analizar toda la información El CGIS supuso un considerable avance con respecto a las aplicaciones cartográficas existentes  hasta   entonces. así  como una conectividad creciente a las  redes globales de datos y por tanto a múltiples servidores de mapas de cualquier clase situados  en cualquier parte del mundo 1 . la realidad es que comparten dos elementos básicos: una imagen  asociada con un atributo de información. incluyendo datos referentes a tipos de suelo.   realizar   mediciones   y  llevar a cabo digitalizaciones y escaneo de datos. Asimismo..­ INTRODUCCIÓN A LOS SERVICIOS DE MAPAS Históricamente el hombre ha utilizado mapas con los mas diversos fines [1]. especies animales. y si bien poco tienen  en común los toscos dibujos efectuados en el neolítico con los complejos sistemas de información  que se manejan hoy en día.. El uso comercial de estos servicios no llegaría hasta la década de los noventa.  recursos fluviales.1. fueron perfilando los modelos que han llegado hasta  nuestros días. especies vegetales..

 para poder así   establecer   un   uso   óptimo   de   estas   y   propiciar   mejoras   que   puedan   ser   de   utilidad   para   la  integración de los servidores de mapas y la optimización de los recursos disponibles. Para propiciar  esta convergencia.  en forma de un archivo de imagen digital  (png.  En  este  proyecto se pretende comparar  el  funcionamiento  de  tres  de  estas  diferentes caches poniéndolas a prueba bajo diferentes condiciones de estrés.   2 . uno de los principales “cuellos de botella” en este tipo de  servicios online.  jpeg. que facilitan información vía web a cualquier cliente que la  solicite.   contenidos.. el Open Geospatial Consortium  (OGC) definió  hace algunos  años el sistema Web Map Services (WMS). con el propósito de producir mapas georreferenciados  espacialmente de forma dinámica. capas. sino en una representación visual de la misma. la existencia de información  redundante en el trafico servidor­cliente. Cada mapa no consistiría por tanto en un cúmulo de información contenida en  la  región precisada. se han desarrollado herramientas para optimizar  el  uso  de los recursos tanto del servidor de mapas  como del cliente.­ OBJETIVOS DEL PROYECTO En la actualidad. en la medida de lo posible. Dicha información suele estar soportada en protocolos propios.).. gif. Este estándar define cada mapa como la representación de la  información geográfica contenida en el servidor.   formatos   y   sobre   todo   de   servidores   tanto   a   nivel  regional.2. aligerando notablemente las cargas de computación. nacional o supranacional.0. existe una gran demanda de servicios de información geográfica de una enorme  diversidad   tanto   en   temática..  con  el fin de realizar el menor  numero de peticiones posibles y evitar. tanto en el  lado del cliente como en el del servidor. por lo que resulta muy  complicado poder integrar datos provenientes de mas de un servidor distinto. . usuarios.. disponibles para ser consultadas en un futuro sin tener que hacer uso de nuevo de las  peticiones al servidor.. Quizá  el principal tipo de herramientas optimizadoras en el campo de los proveedores de mapas  sean las diferentes implementaciones de memorias de caché para almacenar datos de regiones y  capas. creando de este modo un forma  rápida y cómoda de consultar dicha información Haciendo uso de estas recomendaciones.

­ En el segundo capítulo se detallarán las distintas implementaciones WMS­C que van a ser  testadas a lo largo del proyecto.   dando   así   una   clara   idea   del  rendimiento que ofrecerán cada una de ellas en términos absolutos en función de las distintas  condiciones a las que serán sometidos. 2. trabajando la tres sobre estándares WMS. y por otro lado se tendrá que poner a prueba  cada   una   de  las   tres   caches  escogidas mediante es uso de la anterior aplicación sumada a   otras ya existentes.­  En este  capítulo  se detallará  cómo se  lleva a  cabo un  Benchmarking  o  comparativa entre  distintos sistemas de servicios Web de mapas 4. En nuestro caso hemos  optado por la creación de dos aplicaciones diferenciadas.3.­   Como   continuación   se   procederá   a   implementar   las   distintas   aplicaciones   que   van   a   ser  necesarias para la realización de las pruebas anteriormente descritas.  GeowebCache y WMS – C – Wrapper. 0.  destinadas a mejorar los sistemas de mapas.­ ESTRUCTURA DE LA MEMORIA Los objetivos principales del proyecto se centrarán en dos aspectos diferentes. 3. Para ello la memoria constará de los siguientes apartados: 1. Por un lado es  necesario crear una aplicación que permita controlar los distintos parámetros de cada una de las  peticiones Http que será necesario enviar al servidor.Las  tres  caches  elegidas han sido TileCache.­ En un primer capítulo se presentarán las tecnologías de los Servicios Web de Mapas así como  las   propuestas   WMS­C   (Web   Map   Service   ­   Cached)   y   WMTS   (Web   Map   Tiling   Service). por lo  que los resultados obtenidos en las pruebas para un servidor concreto (en este caso Geoserver)  pueden   ser   extrapolados   a   otro   servidor   de   mapas   cualquiera.­ Posteriormente será necesario analizar los diferentes resultados obtenidos mediante el uso de  las aplicaciones anteriores y obtener conclusiones acerca del funcionamiento y rendimiento de las  distintas implementaciones analizadas. La primera  construida en python y las  otras dos en JAVA. 5. 3 .

6.   se   adjuntan   dos   anexos   que   complementan   la   redacción   del   proyecto   y   sirven   para  ampliar conocimientos de cada uno de los  capítulos principales.­   Finalmente   se   obtendrán   las   conclusiones   y   se   sugerirán   posibles   lineas   futuras   de  investigación y desarrollo.  APENDICE I: instalación de las cachés APENDICE II: manual de uso de la aplicación 4 . Además.

1 SERVICIOS WEB DE MAPAS .

 Cada una de estas peticiones define la capa y el  área de interés que va a  ser   procesado. Un mapa no consiste por tanto en los propios datos.   Del   mismo   modo. El estándar implementa tres operaciones distintas [5]. Devolver un mapa cuyos parámetros geográficos y dimensionales han sido bien definidos.  1. Devolver metadatos del nivel de servicio.   GIF   o   JPEG   y   opcionalmente   como   gráficos   vectoriales   en  formato SVG (Scalable Vector Graphics) o WebCGM (Web Computer Graphics Metafile).  desde navegadores  específicos a simples visores de imágenes.  2.  Si analizamos un ejemplo podemos ver de que modo se incluyen todos los parámetros necesarios  para que el servidor envíe la respuesta deseada por el cliente: 5 .1.1.  3. sino en la  representación visual de estos. Esta interfaz también implementa la posibilidad de  especificar ciertos grados de transparencia si se realiza una petición sobre distintas capas pero  sobre un área idéntica. Devolver información de características particulares mostradas en el mapa (opcionales).   la   respuesta   va   a   consistir   en   una   o   varias   imágenes  georreferenciadas que pueden ser visualizadas  en diferentes aplicaciones. De este modo pueden ser visualizadas de forma conjunta y formando una  sola unidad datos provenientes de varios  servidores y/o capas. consiguiendo así  una absoluta  integración entre diferentes fuentes de datos y servidores de mapas en un sólo sistema[4].­ SERVICIO WEB MAP SERVICES El servicio Web Map Services (WMS) fue definido por el Open Geoespatial Consortium (OGC) [3]  como estándar para la generación de mapas georreferenciados de forma dinámica a partir de  información geográfica.  Cada   una   de   estas   operaciones   pueden   ser   invocadas   por   el   cliente   mediante   un   navegador  estándar realizando peticiones en forma de URLs en las que se indican los diferentes parámetros. WMS   proporciona   una   interfaz   HTTP   de   fácil   manejo   para   realizar   peticiones   de   mapas  georreferenciadas sobre una o varias capas provenientes   así  mismo de una o mas bases de  datos geoespaciales. Este estándar internacional define un "mapa" como una representación de  la información geográfica en forma de un archivo de imagen digital conveniente para la exhibición  en una pantalla de ordenador. Los mapas producidos por WMS se generan normalmente en un  formato   de   imagen   como     PNG.

Estas normas y recomendaciones tratan de conseguir  un estándar  de referencia a la hora de  implementar   tanto  servidores   como   clientes   de   mapas   para   permitir   la   obtención   de   datos   de  manera independiente a su origen. Cada petición HTTP utilizada para obtener la información de los servidores ha de cumplir unos  requisitos especificados en la norma ISO/DIS 19128. Un servidor WMS básico clasifica sus recursos  geográficos  en capas. que indica tanto los parámetros que han de  especificarse.   FondoUrbano. correspondientes a los máximos y mínimos del BBox en  cada uno de los dos ejes (en el apartado 4 de la presente memoria se detallan estas coordenadas  así   como   el   método   que   se   sigue   para   obtenerlas). Para indicar al servidor el  área sobre el que se va a trabajar (Boundig Box o BBox) WMS   implementa una referenciación  absoluta indicada por cuatro parámetros. Esta norma Internacional sólo admite capas y estilos con nombres propios y especificados.http://www. que en este caso será  una imagen png.   Por   último   se   incluye   en   la   petición   una  referencia al tamaño (WIDTH y HEIGHT) de la imagen que se desea obtener.   Vial  y   División  territorial. 6 .  Esta norma se aplica a un servidor de mapas  que ofrece sus servicios para producir mapas más  que a su capacidad de acceso a datos específicos.se_inimage&SRS=EPSG%3A4326&BBOX=­180%2C  ­90%2C0%2C90&WIDTH=256&HEIGHT=256  Se puede observar que se efectúa la petición al servidor cartociudad indicándole que las capas  requeridas  son   Topónimo.   También   se  le   especifica   el  formato de salida del mapa. el modo que se utiliza cada uno de ellos así como las operaciones que permite cada  tipo de servidor.1.  y  ofrece un  número finito de  estilos  predefinidos  en  el que mostrar  las  capas.  y no incluye ningún mecanismo para que el usuario pueda efectuar una caracterización propia de  los datos.ogc.cartociudad.1&REQUEST=GetM  ap&STYLES=&EXCEPTIONS=application%2Fvnd.es/wms/CARTOCIUDAD/CARTOCIUDAD?LAYERS=Toponimo %2CDivisionTerritorial %2CFondoUrbano%2CVial&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.

  nacen   los   actuales   modelos   de  servidores   y   clientes   de   mapas   orientados   a   la   total   convergencia   y   la   interconectabilidad  operativa.3.­ PROPUESTA WEB MAP TILING SERVICES (WMTS) Un concepto muy importante en el estándar WMS y por tanto en el desarrollo de este proyecto es  el   de   tesela   (tile   en   su  terminología   inglesa). 1. En caso de tener que efectuar de nuevo una  petición sobre una tesela ya visualizada con anterioridad. será preciso efectuar una petición al servidor indicándole que teselas son las requeridas  y a partir de que capas queremos obtener los datos.1.   definido   mediante   el   TilingStandard   y   concebido  como   una   representación   de   una   porción   de   terreno   correspondiente   a   una   o   mas   capas  determinadas. una vez definido el área del que se desean obtener  los datos.   en   un   lugar  intermedio. la propuesta debe de  ser capaz de advertir al cliente de que un conjunto de teselas ya cacheadas está disponible para  una determinada capa de un particular proxy WMS. Además.  7 . Basados en este concepto. el cliente tendrá que volver a actuar del  mismo modo sin que la anterior petición agilice en modo alguno el proceso. en  caso de desearlo.2. De este modo una  área cualquiera de terreno puede ser subdividida en parcela  regulares   (generalmente   de   forma   cuadrada)   de   tamaño   variable   en   función   de   la   resolución  deseada. obtener datos de diferentes servidores. para de este modo simplificar y estandarizar las petición de datos al servidor y poder. El objetivo de una propuesta WMS Tile Cache (WMS­C) es encontrar una manera de optimizar la  distribución de imágenes de mapas a través de Internet.   las   especificaciones   concretas   de   los   servicios   implementados   por   los  servidores   [7]   y   otras   varias   que   atañen   a   los   clientes   [8]. La propuesta debe de ofrecer algunos  medios por los cuales los clientes puedan obtener teselas  de los  servidores  existentes. y en las múltiples  recomendaciones  efectuadas  por OsGeo (Open  Source   Geospatial   Foundation)   en   referencia   a   cómo   deben   implementarse   estas   teselas  (TilingStandard  [6]).­ PROPUESTA WMS­C Tal como se ha visto en el apartado anterior. de tal  manera   que   las   imágenes   pueden   almacenarse   en   una   caché   en   el   servidor. o incluso ser completamente generados si se desea.

 sino también  a las teselas adyacentes en un radio concreto. SRS.  y sólo a los niveles de escala particular en que fueron almacenados. Formato de salida fijo Obsérvese por tanto que los argumentos LAYERS. Esto invita a una serie de limitaciones a  las solicitudes de WMS GetMap [9]: 1. Nombre de capa fijo (o al menos su orden) 7. a diferencia de WMS. Mínima cadena de argumentos en las consultas (no se permiten argumentos opcionales). HEIGHT. y FORMAT  de   una   petición   GetMap   estarán   fijados   para   una   capa   WMS­C   de   teselas. WIDTH. STYLES. 8 . dando así  una sensación de continuidad absoluta  en su navegación. activando opciones como el metatiling. 2. Rango fijo de posibles Bounding Boxes. podemos  conseguir que el cliente efectúe peticiones no sólo referentes a las teselas indicadas. con el fin de optimizar el tráfico entre ambos. dos peticiones diferentes para una misma tesela  WMS­C debe generar una petición HTTP GET idéntica. Por otro lado. Todos estos  proceso tienen como fin dinamizar  los   procesos   de visualización  de los   mapas  y  agilizar la obtención de resultados. Estilo fijo 8. Tamaño fijo de las teselas (en píxeles) 6. Precisión fija en los valores de los Bounding Boxes 5. un proxy WMS­C debe de tener libertad para devolver una excepción o redirigir la  petición que recibe si ésta no es totalmente compatible o no corresponde a un Bounding Box que  corresponda exactamente a una única tesela en la caché. Por ejemplo. Un servicio WMS­C probablemente sólo  ofrecerá imágenes de Bounding Boxes ajustadas a un origen determinado y en rejilla rectangular.Con estos objetivos se definió el actual estándar WMS­C.   pero   las  especificaciones de WMS obligan a que estos campos se incluyan en todas y cada una de las  peticiones. 4. que bien podría definirse como un perfil  limitado de WMS que permite almacenar teselas en algún punto intermedio entre el cliente y el  servidor. Cadena de argumentos fija. La idea básica es que. 3.

 dado que el servidor  que utilizaremos será  también un servidor local (concretamente GeoServer).En nuestro caso las teselas se almacenarán localmente en el lado del cliente. eliminando así  de la  comparativa el factor de dependencia referente a la conexión al servidor y a la disponibilidad de la  linea de comunicaciones. 9 .

2 IMPLEMENTACIONES WMS-C .

2. la labor de las cachés para WMS es actuar de intermediario  entre   el   servidor   encargado   de   proporcionar   las   teselas   y   el   cliente   que   es   quien   va   a  demandarlas.1.   10 . Por tanto. Como contrapartida. Como es lógico. cuanto más cerca del  cliente se implementen estos sistemas más rendimiento vamos a obtener. las que la  rodean son pedidas de forma conjunta. alcanzado un punto  máximo si el cacheado se realiza de modo local. ya sea de modo local  o  en algún punto entre el servidor y el cliente. bien sea en el lado del servidor o en el del cliente. exige la necesidad de reservar espacios de memoria  que pueden llegar a tener  tamaños importantes según sea la máquina con la que se trabaje y la  cantidad   de   teselas   que   se   vayan   a   cachear. de modo que si deseamos acceder a ellas (habitual en las  consultas realizadas en los servidores de mapas vía web) sólo tendremos que acceder a nuestra  memoria local para obtenerlas.   dado   que   las   respuestas   que   hayan   sido   cacheadas   y  vuelvan a ser solicitadas estarán almacenadas en la propia máquina del usuario.­ CACHEADO EN WMS Según lo visto en el capitulo anterior.   así   como   también   acarreará   una   carga  computacional añadida que puede suponer un lastre importante para otras operaciones que este  llevando a cabo el usuario de manera simultánea a la consulta del mapa. dado que las comunicaciones a través de internet  suponen en principio el principal cuello de botella en estas conexiones. el hecho físico de tener que almacenar las teselas. A priori esta labor podría ser llevada a cabo en cualquier punto intermedio entre  ambos. Estos procesos deberían de propiciar una mayor velocidad en la navegación del cliente a través  del mapa. cuantificar estos parámetros para conocer cuál de las implementaciones posee una  mayor eficiencia tanto en el almacenamiento de las teselas (en nuestro caso en el propio disco  duro local) como en el uso de recursos de la máquina. eliminando en  gran parte los tiempos de espera para la interconexión. Será también objetivo de  este proyecto. dando una sensación absoluta de continuidad en la navegación. los casos que vamos a estudiar se encuentran en el extremo  más alto de eficiencia que  se   va   a   alcanzar   con   estos   sistemas. ya que en el preciso momento en el que se solicita una tesela al servidor.

 la capacidad de ejecutar scripts Python CGI y un servidor WMS para ser cacheado.2. como es lógico.­ GEOWEBCACHE Dado   que   Geowebcache   nació   como   una   adaptación   de   Tilecache   construida   en   Java. intentando acercar la experiencia de usuario de estos  sistemas a otros como los populares Google Maps o Yahoo Maps.  TileCache nació  como un prototipo o prueba de concepto para testear las capacidades de esta  forma de recuperar cartografía en la  web. dado  que   entre   las   tres   cachés   que   van   a   ser   analizadas. De esta manera  las peticiones que incluyan teselas pedidas con anterioridad no serán remitidas al servidor sino  que serán respondidas mediante el uso de esa información almacenada. 2.   es   la   única   que   no   está   construida  íntegramente en JAVA. Fue el primer intento serio de implementar  una memoria caché  que agilizase la  comunicación  servidor­cliente almacenando las peticiones para su posterior uso.   Es   un   proyecto   basado   en   Python   que   realiza   la   función   de   proxy   entre   un  servidor WMS y un cliente WMS­C proporcionando una gestión de Cache para el almacenamiento  de las teselas.  11 .2. En su modo más básico de uso.­ TILECACHE TileCache   [10]   es   una   implementación   del   WMS­C   en   la   parte   del   servidor   desarrollado   por  Metacarta   Labs.  integrabilidad en diferentes máquinas respecto a las implementaciones en JAVA. pero en la actualidad su uso ha  decaído en gran medida debido a su que su construcción en Python le resta. Tilecache sólo necesita permisos de escritura y acceso a un disco  de memoria. funcionando igualmente como proxy entre el  cliente y el servidor y almacenando teselas a medida que  éstas son requeridas. Será  necesario  tener en cuenta este aspecto de su arquitectura a la hora de analizar los resultados finales.3. ya podemos crear nuestra propia caché local de cualquier servidor WMS  y utilizar los resultados en algún cliente que soporte WMS­C.  Con sólo estos recursos.   [11]  comparte con  ésta muchas de sus características.

  añade   a   las   características   de  Tilecache la posibilidad de trabajar en cualquier máquina que implemente un entorno de JAVA y  presumiblemente.   al   estar   construido   íntegramente   en   JAVA. El sistema se encarga de respetar los tiempos recomendados de actualización de la información y  de asegurarse de que la caché  atiende a la mayoría de las peticiones de forma  óptima gracias a  su sistema de cacheado espacial y estadístico. 2. WMSCwrapper consiste en un filtro que permite transformar cualquier servidor de mapas estándar  en un potente servidor de teselas y una fuente de imágenes para Google Earth. Para ello  solamente se requiere un disco duro para realizar caché  y un tipo de información que no deba  actualizarse instantáneamente. está  desarrollado completamente en java por el IDELab (laboratorio  de   Infraestructura   de   Datos   Espaciales)   perteneciente   al   grupo   de   investigación   universitario  ITAST   (Infraestructuras. Además. Este sistema se encarga de adaptar las distintas  peticiones de teselas para cachear las distintas áreas contiguas a la solicitada sin que en ningún  caso haya una repetición en la solicitud. a priori un mayor rendimiento efectivo a la hora de gestionar las peticiones y las  teselas GeoWebCache ha adelantado a TileCache como implementación más utilizada en la actualidad. De este modo conseguimos que cualquier servidor de información  geográfica   ofrezca   un   formato   de   salida   compatible   con   los   clientes   que   utilizamos.   pudiendo  compaginar y superponer de este modo capas e información provenientes de fuentes totalmente  distintas de una manera fácil y rápida.   Tecnologías. 12 . [12]. en la actualidad se considera la tecnología de  referencia en el desarrollo de cachés destinadas a almacenar teselas en este tipo de servicios de  información geográfica.­ WMSCWRAPPER Al igual que GeoWebCache.7.4.1 en adelante) ya  incluyen esta imlementación por defecto.   Aplicaciones   y   Servicios   de   Telecomunicaciones)   de   la  Universidad de Valladolid.  en gran medida debido a que las versiones más recientes de GeoServer (1.Evidentemente.

2:   metatiling 4x4 13 . formando anillos concéntricos centrados en ella.  mientras que en WMSCwrapper este comportamiento viene también influenciado por el hecho de  si las teselas adyacentes están o no cacheadas.El metatiling tanto en TileCache como en GeowebCache funcionaría realizando peticiones sobre  las teselas adyacentes a la que hemos solicitado. En la imagen vemos cómo funciona el metatiling  para las tres cachés si no tenemos ninguna zona precacheada (En rojo tesela solicitada y en  negro las que van a ser pedidas debido al metatiling)                                                                        Imagen 2.1: metatiling 3x3                                                                     Imagen 2.

Sin embargo.3: TileCache y GeowebCache Imagen 2. Lo  vemos en una imagen: Imagen 2. si tenemos una zona precacheada (en azul) antes de solicitar la misma tesela. los  resultados no van a ser los mismos para TileCache y GeoWebCache que para WMSCwrapper.4: WMSCwrapper 14 .

 si bien se   adapta   mejor   a   las   zonas   cacheadas.Como   puede   observarse. y por tanto tendremos una zona ya  almacenada en las caches mayor que en el primer caso.   es   posible   que   genere   un   retardo   mayor   que   sus  competidores al tener que solicitar un porcentaje mayor de teselas al servidor (en el caso de la  imagen. serían 3) La   instalación   y   configuración   de   las   diferentes   implementaciones   puede   consultarse   en   el  Apéndice I de este proyecto.   existen   tres   teselas   ya  cacheadas que son solicitadas de nuevo. mientras que en WMSCwrapper. todas las teselas que  van a ser solicitadas no han sido pedidas en ningún momento.   en   el   caso   de   TileCache   y   GeowebCache. 15 . Este sistema de WMSCwrapper.

3 BENCHMARKING DE SERVICIOS WEB DE MAPAS .

 el tipo de servicio que demandan y el tipo  de   información   que   tratan   de   obtener. A ojos del cliente el mapa siempre ha de mantener una continuidad y  no   ha   de   percibir   el   modo   en   el   que   las   teselas   van   siendo   cargadas   y   visualizadas   en   su  navegador. los  tiempos de espera si bien eran importantes. Ya  no resulta admisible mantener un tiempo de espera que sea percibido por el usuario como una  molestia en su navegación. El ingente desarrollo de las redes de comunicaciones globales y de la capacidad de procesado de  los   terminales   de   usuario   propició   que   cada   vez   más   clientes   se   interesaran   por   acceder   a  información   geográfica.3. Para hacernos una idea de lo significativo o no de estos tiempos de espera y por tanto de la  calidad de servicio que ofrece un determinado servidor surgen los Benchmarks o comparativas  entre cada una de las diferentes cachés.  sino  que  el  servidor sólo atendía peticiones de un único cliente a la vez y normalmente de una sola tesela por  cliente. el aumento de la demanda llevó aparejado un aumento no sólo de los clientes que  realizaban peticiones sino también del número de peticiones por cliente.­ RETARDOS EN WMS Dada la apertura de los sistemas de mapas al gran público. Este cambio en el ratio de  peticiones   por   cliente   fue   debido   en   gran   medida   a   la   sustitución   del   usuario   institucional   o  administrativo.1.   cambiando   en   gran   medida   el   sistema   de   trabajo   de   los   distintos  servidores.   En   origen   estos   sistemas   fueron   diseñados   para   uso  administrativo o militar. no eran determinantes en la comunicación.   por   un   usuario  particular con un patrón de búsquedas mucho más irregular y complejo para el servidor.  En el primer escenario en el cual eran las administraciones quienes demandaban los recursos. por lo que en las peticiones que se realizaban al servidor no primaban  criterios  de  velocidad  u optimización  de  la  atención  a  varios   clientes   simultáneos. dado que  la información tenía que ser obtenida a partir de un servidor concreto que era el único que alojaba  ese mapa. En la disposición actual el retardo en el ofrecimiento de las teselas es quizá el principal  factor   de   calidad   que   rige   la   comunicación   entre   el   usuario   y   el   servidor.   que   demandaba   un   plano   concreto   para   un   fin   determinado. se ha producido un cambio en el  modo en el cual los usuarios acceden a la información. Si antes cada servidor se tenía que preocupar de servir unas pocas teselas a unos  pocos usuarios. 16 .   dado   que   el   cliente  demanda principalmente una gran interactividad y una sensación de continuidad en los mapas.

3.2.­ BENCHMARKS EN WMS

A lo largo de la historia de la informática, el uso de pruebas en detalle o benchmarks ha sido algo  muy común, de forma que los resultados obtenidos de forma objetiva en las distintas arquitecturas  mediante   estas   pruebas   podían   ser   comparados.   En   general,   la   realización   de   pruebas  comparativas   no   suele   ser   una   tarea   fácil   y   requiere   de   sesiones   repetitivas   para   llegar   a  conclusiones  útiles, siendo también difícil la interpretación de los resultados de las pruebas. Un  factor a tener en cuenta durante la realización de las pruebas es que los fabricantes suelen afinar  sus productos específicamente para los benchmarks más comúnmente utilizados en su sector, por  lo que hay que tener especial precaución a la hora de interpretar los resultados. Además, los  benchmarks generalmente, aparte de las mediciones cuantitativas del rendimiento de un sistema,  no suelen tener en cuenta ninguna medición cualitativa acerca del servicio como pueden ser la  seguridad, la disponibilidad, la confiabilidad, la escalabilidad, o el grado de conformidad con las  especificaciones, las cuales son tan o más importantes que las anteriores [15]. Dentro del amplio  espectro de pruebas de Benchmarking que existen para evaluar el rendimiento de casi cualquier  componente software o hardware, hay dos campos que son de especial relevancia para el caso  que nos ocupa en este trabajo: las bases de datos y los servicios web. Dentro de los objetivos de  este proyecto no se encuentra el hacer un estudio en profundidad del rendimiento de los distintos  gestores de bases de datos, ya sean libre distribución como MySQL y PostgreSQL o propietarias  como Oracle Server y Microsoft SQL Server. Pero es interesante hacer mención de la existencia  de multitud de benchmarks orientados a la evaluación de  éstos, ya que las bases de datos, y en  concreto   aquellas   que   disponen   de   extensión   espacial,   son   comúnmente   utilizadas   como  repositorios para el manejo y acceso a la información geoespacial, bien sea de forma directa a  través de clientes, o indirectamente por medio de servicios web de geo­procesamiento como es el  caso de los Web Map Services.  Existe además algunos estudios comparativos acerca de los rendimientos tanto de los servidores  (nosotros sólo usaremos geoserver) como de las cachés en sí. Este  último grupo es el que más  nos interesa por ser el más parecido al estudio que vamos a llevar a cabo. Como ejemplo tenemos  un estudio llevado a cabo por OpenGeo bajo el título “Comparing the Performance of Open Source   Web   Map   Servers”,   en   el   que   se   incluye   entre   otros   muchos,   un   apartado   comparativo   entre  GeoWebCache y Tilecache para unas determinadas condiciones.

17

Los resultados obtenidos son para Tilecache 2.04 y GeoWebCache 1.0­beta0 (en este proyecto  las versiones a analizar serán   2.10 y 1.1.3 para Tilecache y GeoWebCache respectivamente), e  indican un resultado muy parejo en una simulación concreta sobre Geoserver 1.7.0 (en nuestro  caso será la versión 1.7.5)

Imagen 3.1: Estudio sobre TileCache y GeoWebCache
Estos resultados se han obtenido saturando una línea de conexión con el servidor de 100 Mbps,  llegando   a   alcanzar   en   ambos   casos   (sus   comportamientos   son   prácticamente   iguales)   una  velocidad de 450 teselas por segundo. Dado que las distintas implementaciones de las cachés  han ido mejorando y que en nuestro caso el servidor será  local, es de esperar que se mejoren  sensiblemente los resultados obtenidos en esta medición.

18

Así  pues, la comparativa que llevaremos a cabo se basará principalmente en el tiempo de espera  que ha de soportar el cliente a la hora de recibir una respuesta a su petición, dado que será  éste  el   principal   parámetro  de  medición   de   la   calidad   de   servicio   en   este   tipo   de  comunicaciones.  Además también se reflejará  una medición de la tasa de transmisión de teselas  por parte del  servidor, que dará  idea del rendimiento comparativo para cada una de las implementaciones que  vamos a estudiar. A partir de los datos anteriores es de esperar que lleguemos a las conclusiones necesarias para  afirmar qué caché se comporta mejor en cada uno de los escenarios y cuál es el motivo de dicha  diferencia.

19

4 DESARROLLO DE LA APLICACIÓN DE BENCHMARKING .

Generar un interfaz cómodo y simple que permita una rápida gestión de las variables y de los  campos.  20 .­ ESQUEMA DE FUNCIONAMIENTO En este apartado se detallará  la estructura que ha de seguir nuestra aplicación. será necesario dividir el trabajo a realizar entre más de una  aplicación.­ OBJETIVOS DE LA APLICACIÓN Los objetivos generales en este apartado.2. Gestionar de manera rápida y sencilla todas y cada una de las variables incluidas en el las  peticiones.   cada  una  construida  en  el  lenguaje  y   formato  mas  adecuado  para sus   respectivas  funcionalidades. así  como las  partes de las que estará compuesta para su correcto funcionamiento. que se  pueden resumir en 6 principalmente: Generar un archivo legible por Jmeter con cada uno de los campos y parámetros necesarios  para las peticiones Http. – – – Generar un archivo legible por Jmeter con valores de los bboxes válidos.­ ARCHIVO DE JMETER Para la realización de las peticiones se utilizará  la aplicación Jmeter. 4. Flexibilidad   suficiente   para   poder   ser   adaptada   en   posteriores   pruebas   en   entornos  suficientemente similares. 4.1. serán los marcados al comienzo del proyecto.1. – – – Para   cumplir   estos   objetivos   contaremos   además   con   otras   aplicaciones   ya   desarrolladas   y  presentadas en anteriores apartados dentro de este mismo proyecto. que permite generar tráfico  http con la condiciones que se deseen en cada momento.4. No generar demasiada carga computacional que pueda alterar los resultados obtenidos en las  medidas de eficiencia. Dado que es necesario que  realice un buen número de funciones.2.

21 .valor_por_defecto)} en determinados campos.jmx y deberá de tener los siguientes componentes: – – – – – – – grupo de hilos cuatro bloques de parámetros definidos por el usuario bloque de configuración de csv data set valores por defecto para una petición HTTP un bloque de petición HTTP un escritor de datos simple un generador de un sumario de resultados.jmx   cuyo   significado   será   explicado   mas  adelante): Imagen 4.El archivo que ha de crearse y ejecutarse cada vez que se quiera realizar una petición será  del  tipo . El esquema general del archivo . es posible introducir el valor concreto de estos  campos mediante la utilización de argumentos del tipo ­Jvariable=valor_deseado.jmx una vez ejecutado por el Jmeter quedará  por tanto de la  siguiente   forma   (el   nombre   elegido   es   Non­GUI­Text. o en caso de no  hacer   uso   de   estos   argumentos. cuando ejecutemos la aplicación. Esto se puede hacer mediante el uso  de valores de variable del tipo ${__P(variable.   el   programa   tomará   por   defecto   el   valor_por_defecto   que  hallamos agregado.1: Estructura generada en JMeter En   archivos   de   Jmeter   existe   la   posibilidad   de   no   asignar   un   valor   numérico   concreto   a   las  variables de cada uno de los bloques que hemos colocado. De  esta manera.

1)} ● RAMP_UP: ${__p(ramp_up.EPSG:4326)} WIDTH: ${__P(width.py)} ● CSV: ${__P(csv.0)} ● VARIABLES DEFINIDAS POR EL USUARIO (para la petición HTTP) HOST: ${__P(host.256)} HEIGHT: ${__P(height.tilecache/tilecache.1.De esta manera   en nuestro caso las variables que hemos colocado en cada uno de nuestros  bloques han sido las siguientes: GRUPO DE HILOS: Nombre: WMS­C Users Numero de Hilos: ${THREADS} ● Periodo de Subida: ${RAMP_UP} ● ● VARIABLES DEFINIDAS POR EL USUARIO (para el grupo de hilos ) THREADS: ${__P(threads. )} ● PATH: ${__P(path.csv)} ● VARIABLES DEFINIDAS POR EL USUARIO (valores petición WMS­C) ● ● ● ● ● ● ● ● LAYERS: ${__P(layers.topp:hidrografia)} SERVICE: ${__P(service.localhost)} ● PORT: ${__P(port.txt)} VARIABLES POR DEFECTO PARA PETICION HTTP (listener) ● ● ● ● ● ● ● ● LAYERS: ${LAYERS} SERVICE: ${SERVICE} VERSION: ${VERSION} REQUEST: ${REQUEST SRS: ${SRS} WIDTH: ${WIDTH} HEIGHT: ${HEIGHT} FORMAT: ${FORMAT 22 .256)} FORMAT: ${__P(format.bboxes/bboxes.WMS)} VERSION: ${__P(version.1.image/png)} VARIABLES DEFINIDAS POR EL USUARIO (listener) ● OUT: ${__P(out.GetMap)} SRS: ${__P(srs.1)} REQUEST: ${__P(request.results.

 la longitud de los laterales de cada tesela va venir determinado por una serie de  valores numéricos concretos propios de esta tecnología.2.2.  ha de estar en unos rangos pre­establecidos.CONFIGURACIÓN DEL CSV DATA SET NOMBRE: BBox from CSV ● NOMBRE DE ARCHIVO: ${CSV} ● VARIABLE: BBOX ● PETICIÓN HTTP ● NOMBRE: WMS­C Request ESCRITOR DE DATOS SIMPLE ● ● NOMBRE: Result Listener NOMBRE DE ARCHIVO: ${OUT} GENERAR SUMARIO DE RESULTADOS ● NOMBRE: Results Summary Todos   estos   datos   tendrán   que   ser   proporcionados   al   Jmeter   en   función   de   la   caché   que  queramos probar. Por tanto se hace imprescindible construir  una   aplicación   que   genere   grupos   de   teselas   válidos   o   bounding   boxes   (bboxes)   para   las  peticiones. Por tanto tendremos que crear  un   sistema   para   poder   hacerlo. 4.­ GENERADOR DE BBOXES Todas   las   implementaciones   de   cachés   con   las   que   vamos   a   trabajar   manejan   sistemas   de  teselas (o tiles en su nomenclatura inglesa). la capa que deseemos. el numero de threads. Una tesela es una porción de mapa (en nuestro caso de forma cuadrada) de tamaño variable en  función de la resolución.   pero   con   la   configuración   actual. por lo que las aplicaciones que creemos tienen que  adaptarse a este funcionamiento...  En los sistemas WMS­C que  vamos a utilizar. que representa una sección de una capa. El tamaño de las teselas no  puede ser arbitrario.   podríamos   realizar   ya   una  simulación de trafico satisfactoria.  23 ..

2: Teselización para resolución = 0 Imagen 4. y la segundo para una resolución de 2: Imagen 4. A. además de poder realizar el trabajo con poco  esfuerzo tanto de desarrollo como de carga computacional a la hora de su ejecución. así   como de las resoluciones máxima y mínima y el tamaño de cada tesela (ancho y alto).Dicha  aplicación  será  generada  en  Java  a  través  de  eclipse  dado  que  así  podemos  crear  un  sistema portable a otras maquinas y distribuciones. La primera la obtendríamos para la resolución mínima (0).3: Teselización para resolución = 2 24 . constando por tanto de sólo  dos teselas. Dicha  matriz está definida en los estándares de WMS.­ GENERACIÓN ALEATORIA DE TESELAS En primer lugar veamos cómo podemos generar un BBox válido a partir de los valores máximo y  mínimo tanto en el eje X como en el Y del trozo de mapa que queremos tomar (para ser válidos  estos valores también van a tener que cumplir unas condiciones que veremos más adelante). Además  será necesaria una matriz (resmat[]) con los valores válidos de los tamaños de las teselas. Podemos   visualizar   lo   que   significa   una   teselización   global   a   partir   de   las   siguientes   dos  imágenes.

 mientras  que el segundo si: Imagen 4. En la primera figura el programa tendría que ser capaz de detectar que no le estamos  indicando una zona correcta y por tanto elegir automáticamente la teselas  que  contiene. Se puede observar también que la precisión con la que se va a ajustar  al contorno de la zona deseada va a depender en gran medida de la resolución a la que estemos  trabajando: 25 . por lo que el hecho de que sea o no válido va a  depender   de   la   resolución   a   la   que   se   trabaje.5: BBox válido Por tanto el primer objetivo que tendrá  que salvar nuestra aplicación es implementar un corrector  de   coordenadas   que   nos   calcule   qué   Bounding   Box   válido   es   el   mayor   dentro   del   que   le  indiquemos.   en   las   siguientes   dos   imágenes  podemos ver como en un caso el BBox elegido no será correcto para la resolución dada. la zona que se le indica a la aplicación es la dibujada en negro y la zona que  él debe de tomar es la roja.   Por   ejemplo.4: BBox no válido Imagen 4. es necesario que contenga  un número exacto de subdivisiones o teselas.Para que el BBox sea válido y podamos trabajar con el sin problemas. Si lo  vemos en un dibujo.

Dado que conocemos la resolución a la que estamos trabajando.6:Resolución baja => poco  ajuste Imagen 4.8:parámetro que caracterizan un BBox 26 . La siguiente imagen representa este hecho. El siguiente paso consistirá  en ir proporcionando cada tesela  contenida   en  esta  zona   de  manera   individual  y   aleatoria  conforme  a  las   especificaciones   que  deseemos. resulta sencillo saber cuantas filas y columnas de teselas tenemos dentro del  área de trabajo.Imagen 4. por lo que podemos  trabajar con  él sin riesgo alguno. Imagen 4. el tamaño en píxeles que va a  tener cada una de las imágenes que vamos a obtener y las coordenadas del BBox con el que  estamos trabajando.7:Resolución mayor => mayor   ajuste En este punto ya tenemos un BBox que incluye un numero entero de teselas.

 como conocemos ambos factores. Por lo tanto. pero tomando como parámetros maxX y minX. Debido a la restricción antes impuesta. Evidentemente el número  de filas y de columnas se irá multiplicando a medida que vaya aumentando la resolución tomada.9:Tesela seleccionada aleatoriamente y sus parámetros 27 . Finalmente bastará  con elegir de manera aleatoria una fila y una columna para tener una tesela  concreta.  conocemos el tamaño exacto de cada una de las teselas.Sabemos que el ancho de una tesela (que será igual que el alto dado que las teselas con las que  trabajamos van a ser cuadradas y denominaremos TileSpanX) va a ser el producto del tamaño en  píxeles   (por   defecto   normalmente   serán   256x256)   por   un   factor   sacado   de   una   matriz   de  elementos y que va a depender de la resolución. este  número de filas y de columnas va a resultar siempre un número entero. En el siguiente ejemplo se habría elegido aleatoriamente la segunda fila (numrow=1) y  tercera columna (numcol=2). Para las columnas se operará  de igual  forma. Para saber el número de filas de teselas que contiene nuestro BBox basta con operar maxY­minY  y dividirlo entre el tamaño de las teselas ya calculado.Las filas se cuentan de arriba a abajo y las columnas de izquierda a  derecha Imagen 4.

 En nuestro caso contamos con una base de datos proporcionada por cartociudad en  la que se incluye una lista de teselas de diferentes tipos y resoluciones conjuntamente con otros  datos que no van a ser utilizados en la realización de este proyecto.csv. tilemaxX y tilemaxY separando cada elemento por una coma y escribiendo cada tesela  en una linea separada del archivo. será  necesario hacer uso de JDBC  (Java DataBase Conectivity). La forma de efectuar esta conexión es simple.csv para su posterior uso. En  nuestra aplicación se ha implementado un mecanismo para que la resolución a la que se toman  las teselas pueda variar dentro de un rango indicado.  Cabe reseñar que el orden en el que se escribe cada una de las cuatro coordenadas de cada  tesela  no  es  permutable.  B.Para calcular los distintos parámetros de la tesela pedida se operará de la siguiente forma: tileminX = minX+numcol*TileSpanX tilemaxX=minX+(numcol+1)*TileSpanX tilemaxY=maxY­numrow*TileSpanY tileminY=maxY­(numrow+1)*TileSpanY De este modo ya tenemos una tesela con la resolución pedida y dentro del BBox indicado. de modo que cuando queramos obtener un archivo legible por Jmeter que las  contenga sólo tengamos que efectuar un acceso a dicha base de datos y una transcripción al  archivo . de manera que aunque la zona de trabajo  quede   fija   desde   un   primer   momento. Finalmente sólo resta escribir los datos de cada tesela en un archivo .  tileminY. indicándole un usuario y un password válidos para el acceso a dicha base de  datos (que habremos creado con anterioridad). Para permitir que la aplicación acceda a la base de datos. herramienta de Java que permite establecer conexiones con bases  de datos. 28 . bastará  con establecer una conexión  mediante un driver.  y  será  el  siguiente  (según  se  han  nombrado  en  el  dibujo):  tileminX.   el   tamaño   de  las   teselas   dependerá   de   otro  generador  aleatorio que irá escogiendo la resolución entre los valores indicados.­ OBTENCIÓN A PARTIR DE UNA BASE DE DATOS Puede resultar interesante tener almacenadas en una base de datos las distintas teselas que van  a ser utilizadas.

y1)). El formato en el que están registradas las teselas sería como se indica en la imagen: Imagen 4.x2. Conociendo el número de teselas que deseamos obtener bastará con leer un número de registros  igual a a ese número de peticiones.x1.x2.   podemos   obtener   los   datos   contenidos  mediante consultas.Una   vez   establecida   la   conexión   de   manera   correcta. tendriamos que: tileminX = X1 tileminY = Y2 tilemaxX = X2 tilemaxY = Y1  29 .x1.10: Parámetros de una tesela en formato Polygon Cada tesela estará representada como ((x1.y1.y2.y1. accediendo sólo a la columna deseada y transformar los datos  que obtendremos (escritos en forma poligonal) al formato de cuatro coordenadas que estamos  utilizando.y2. Si lo adaptamos a nuestro sistema. de manera análoga a como podría realizarse con postgresql o con cualquier  otro gestor.

C. no será necesario configurar manualmente cada uno de los componentes ni las relaciones  que se establecen entre ellos.De nuevo ya sólo resta escribirlo en el archivo .  Dado  que  eclipse   incluye  opciones   para   crear   aplicaciones   gráficas   de  una   manera  sencilla   y  eficaz.­ INTERFAZ GRÁFICA. 30 .11: Interfaz gráfica de la aplicación BBoxgenerator como puede observarse no contiene una gran cantidad de información.csv correspondiente y cortar la conexión con la  base   de   datos   para   no   consumir   recursos   de   una   manera   innecesaria.  hemos  optado por  introducirle un  interfaz gráfico que permita gestionar todos los parámetros de una forma mas sencilla y visual.   ya   que   no   existe   la  posibilidad de romper la conectividad por defecto. Para que el manejo de esta aplicación  resulte mas sencillo. El aspecto que va a tomar nuestra interfaz va a ser el siguiente Imagen 4. pero si la precisa para  poder gestionar de manera eficaz la generación de Bboxes válidos u obtenerlos a partir de la base  de datos de cartociudad.

 100. 31 . Hay que reseñar que a efectos del cálculo de la validez de la zona que posteriormente  indicaremos como la zona  deseada. la aplicación tomará  el valor  mínimo dentro del  rango de  resoluciones que le hayamos introducido. 0. La zona 4 permite establecer el nombre del archivo que va a ser generado con todos los Bboxes  válidos. Por defecto generará un fichero llamado bboxes.csv En   la   zona   3   podemos   introducir   el   numero   de   teselas   que   deseamos   pedir   así   como   una  indicación de las que deseamos que estén repetidas de manera directa. En caso de que ésta se repita.Está compuesta por cuatro zonas o apartados: Imagen 4. Por tanto si por  ejemplo indicamos que las probabilidades respectivas para una. volverá a hacer lo mismo con la posibilidad de que esté  repetida una segunda vez (“prob 2 rep”) y así  sucesivamente hasta cuatro veces.csv.  posteriormente evalúa la probabilidad de que esta tesela esté  o no repetida (“prob 1 rep” en el  interfaz ).12: Componentes de la Interfaz gráfica de BBoxGenerator En la zona 1 podemos establecer las resoluciones mínima y máxima con las que vamos a generar  los Bboxes.  0 cada tesela aparecerá tres veces. dos tres y cuatro repeticiones  son: 100. Funciona de la siguiente  manera: la aplicación genera los parámetros de un BBox particular y lo escribe en el archivo .

 por lo que si  le pedimos que nos genere 100 Bboxes. 32 . los valores que hayamos introducido no tienen por qué   ser válidos. el programa sólo tendrá dos teselas donde elegir.13: Ejemplo de autocorrección de BBox Además de mostrarlo en un mapa. La ventana queda de este modo: Imagen 4. En las cuatro casillas superiores se  debe de escribir las cuatro coordenadas del BBox que deseemos. es seguro que 98 de ellos como mínimo serán repetidos. No obstante si se desea una visualización de la zona que se ha escogido  en referencia a un mapa del mundo. Como se ha visto anteriormente. se ha implementado la posibilidad de ver no sólo la zona que  hemos elegido como nuestro BBox deseado. La zona 2 es quizá  la que tiene un manejo mas complejo. sino también la zona que la aplicación tomará como  corrección de la introducida por el usuario y que será el BBox válido mas grande dentro del que se  le haya indicado. Si  pensamos  en  el caso visto anteriormente para una  resolución que se establezca en 0.Hay   que   tener   en   cuenta   que   en   el   proceso   aleatorio   de   elección   de   teselas   es   posible   que  también se produzca alguna repetición. en las cuatro casillas que esta inmediatamente bajo las que  hemos   escrito   los   valores   del   BBox   deseado   aparecerán   los   valores   válidos   con   los   que   la  aplicación trabajará. que será  el que la aplicación  tomara. por lo que se ha diseñado un sistema que corrige dichos valores sin que el usuario  tenga por qué advertirlo.

En caso de que resulte imposible generar un BBox válido a partir de los que le indique el usuario  aparecerá   una   ventana   de   advertencia   y   los   valores   que   tomará   entonces   la   aplicación   como  correctos será los valores por defecto. todo el mapa completo. hemos decidido incluir un archivo de propiedades para que no sea necesario  cambiar   nada   más   que   los   valores   precisos   de   estos. En esta zona también se encuentra el botón BBDD.csv ha sido generado. que permite obtener el número de teselas que  se  indique   en  en  la  casilla   “number   of   Bboxes”   directamente  a  partir   de  la   base  de   datos   de  cartociudad. es decir.  emergerá  una ventana indicando que la operación ha sido realizada correctamente y el archivo  . 33 .   También   ha   sido   necesario   incluir   un  mecanismo para leer este archivo de propiedades y proporcionar los resultados a la aplicación.  Finalmente si se han introducido todos los  datos de manera correcta y se pulsa el botón OK. Dado que algunos parámetros puede que tengan que ser modificados una vez finalizada la labor  de programación.

 del modo siguiente.4 para su gestión. Este modelo tendrá dos gráficas para los dos juegos de resultados  que obtendremos.­ REPORTE DE RESULTADOS Cada simulación efectuada por el Jmeter generará  (como se vio anteriormente) un archivo . en función  del   numero   de   threads   de   la   simulación   y   del   tipo   de   caché   testada. Para este proyecto. geowebcache1..  A. así  como  OpenOffice 2.3..­ Template.xls.csv  con todos y cada uno de los resultados obtenidos. se ha utilizado Excel2003 para la generación del archivo modelo. y les asignamos valores siguiendo el siguiente patrón: nombre=DESREF(hoja1!primera_celda. Por lo tanto al finalizar todas las iteraciones  existirán varios archivos del tipo tilecache1.xls Para la generación del archivo .csv (dado que a priori no conoceremos el número de threads utilizados) y a que cada  uno contenga un número indeterminado de lineas (en función de número de bboxes).xls partiremos de un modelo flexible que permita visualizar los  resultados de manera gráfica. es decir.csv.. El sistema ha de ser lo suficientemente flexible como para adaptarse a un diferente número de  archivos .  geowebcache.csv.CONTARA(hoja1!$A:$A)­1.. el tiempo medio por tesela y las velocidad medida en teselas por segundo que  alcanza cada cache..xls existiría un  conflicto a la hora de generar los nuevos ficheros csv.   en   nuestro   caso   tilecache.4. Seleccionamos la opción Insertar  –   Nombre   –   Definir. este archivo  puede almacenar sucesivas pruebas para un numero de threads repetido.   Definimos   un   nombre   para   la   variable.. se ha optado  por generar a partir de ellos un solo archivo  que resuma los datos mas importantes en una sola  tabla y que  ésta sea visualizada gráficamente mediante un archivo . mientras que si no fueran escritos en un archivo .  Para poder conseguir que las gráficas representen un número variable de entradas. Además. wmscwrapper y threads.   Dado   que   no   toda   la  información que contienen estos archivos es de utilidad para nuestra investigación.csv. los resultados se  almacenarán de forma individual...2. si realizamos  una simulación para 5 threads y posteriormente otra para 5 threads igualmente.1) 34 . tilecache5. haremos uso  de definiciones de área mediante nombres.

 pero se  han incluido en el ejemplo para una mejor visualización. por lo que si le indicamos a una gráfica. 35 .xls zona superior   Imagen 4.   obtendremos   una   gráfica   de   mas   o   menos   numero   de   columnas  dependiendo de las casillas con valor en dicha columna. que ha de tomar los valores  incluidos   en   dicha   variable. que contendría  las dos gráficas quedaría del siguiente modo Modelo de Template. Finalmente indicar que la  única tarea que nos resta.Con esta función conseguimos definir un  área que variará  en función del número de valores que  contenga la primera columna.xls zona inferior En el modelo que almacenaremos. no se encontrarían valores en las casillas numéricas. es sobreescribir los valores que se deseen  incluir en el gráfico en cada una de sus correspondientes casillas mediante una aplicación que  generaremos. De este modo el modelo.14: Modelo de Template.

csv  que genera Jmeter  en  cada una  de las   ejecuciones  (tilecacheNUMERODETHREADS. y calcular a partir de cada uno el tiempo medio por  tesela y la tasa media de emisión de teselas por parte del servidor.   Estos   dos   serán   los   parámetros   que   utilizaremos   para   calcular   tanto   la   tasa   de  transmisión del servidor como el tiempo  medio por tesela.csv.B.­ ALMACENAMIENTO DE RESULTADOS Y GENERACIÓN DE REPORTE En cada ejecución hemos decidido almacenar los datos relevantes en un archivo con el fin de  poder tener un índice de ls ejecuciones con sus resultados propios.   y  lo   establecemos   como   tiempo  de   origen   o  tiempo  cero.csv). será necesario sobreescribir la hoja modelo de excel con  los datos obtenidos y generar una visualización en linea de comandos con los mismos.csv   y  wmscwrapperNUMERODETHREADS. Para calcular el tiempo medio que emplea cada implementación en responder una tesela.   seguidamente  hallamos el momento exacto en el cual la última tesela llega al receptor hallando el máximo valor  de una hipotética columna que nos reflejase el código temporal en el que cada respuesta llega al  usuario (TimeStamp + elapsed) 36 .   Para   ello   calculamos   el   mínimo   de   la  columna  TimeStamp. bastará  con sumar el tiempo individual que emplea en cada una de ellas y calcular la media. Típicamente uno de estos archivos tendrá el siguiente formato: timeStamp elapsed 1258446582713 141 1258446582868 25 1258446582896 2 1258446582901 3 1258446582907 3 1258446582913 3 label WMS­C Request WMS­C Request WMS­C Request WMS­C Request WMS­C Request WMS­C Request responseCode 200 200 200 200 200 200 responseMessage OK OK OK OK OK OK threadName dataType success bytes bin 562 WMS­C Users 1­1 true bin 562 WMS­C Users 1­1 true WMS­C Users 1­1 true bin 562 WMS­C Users 1­1 true bin 562 bin 562 WMS­C Users 1­1 true bin 562 WMS­C Users 1­1 true TimeStamp es un código temporal correspondiente al momento exacto del envío de cada petición  por parte del Jmeter y elapsed es el tiempo que tarda cada tesela en ser respondida por parte del  servidor.   geowebcacheNUMERODETHREADS. Para calcular  la tasa será  necesario conocer el lapso de tiempo total desde que se envía la primera de las  teselas   hasta   que   la   última   es   recibida   por   el   usuario. Cuando finalicen todas las ejecuciones. para luego poder calcular los  parámetros que se crea convenientes y poder mostrarlos en el modelo anterior. Para ello partiremos de  los archivos  .

37 . En primer lugar se parte de una hoja de  cálculo   vacía.54 WMSCwrapper 601.01 TileCache 1.7 703. resulta necesario almacenar estos datos individuales en un archivo     . 1 y 2 respectivamente. Al final de las tres iteraciones si consultamos el archivo store. Como se puede ver  dos entradas distintas tienen el mismo valor para la columna threads. despues “store 1” de  nuevo y finalmente “store 2”.99 Cada una de las lineas será por tanto el resultado de una simulación distinta.52 AVG RATE GeoWebCache 431. Como  se dijo anteriormente. De este modo obtenemos los datos de cada una de las cachés para cada prueba individual. Para ello haremos uso de POI. pero diferentes valores para  el resto dado que pertenecen a pruebas independientes.Una   vez  hallados  los  valores  inicial   y  final   del  experimento.83 602.11 1.74 1.   bastará   dividir   el  numero  total  de  teselas pedidas entre el tiempo total del ensayo y transformarlo en segundos multiplicando por  1000.45 858. El método usado para almacenar los datos es sencillo.69 499.   será   necesario introducir una bifurcación dentro del código.82 2. un API para JAVA [16] que permite crear y  gestionar hojas de cálculo de una manera rápida y sencilla.02 1.xls  para su posterior uso.83 1. Como sólo se quiere tener una aplicación para realizar dos funciones (ir almacenando los datos a  medida   que   se   generan   y   generar   el   archivo   gráfico   al   finalizar   todas   las   ejecuciones).xls.46 2. En nuestro caso hemos optado por hacerlo  a partir de los argumentos que se introduzcan en la ejecución: “store” seguido del numero de  threads en el caso de que se pretenda almacenar los datos o simplemente “0” para el caso de que  se quieran mostrar los resultados finales.94 646. podremos encontrarnos con los  siguientes resultados: threads 1 1 2 WMSCwrapper 1. por cada prueba individual para un numero de threads concreto.6 AVG TIME GeoWebCache 1.7 419.  bastará  con ejecutar al final de cada iteración (cuando los archivos .   a   la   cual   se   añade   una   linea.jar primero con los argumentos “store 1”.   con   los   datos   obtenidos   como   se   explicó   anteriormente.19 TileCache 27.csv estén completos y en su  lugar) la aplicación JmeterReports. Así por ejemplo si  se realizan tres ejecuciones con unos valores del numero de threads de 1.

 se ha incluido un archivo de configuración y un  sistema interno para leerlo con el fin de simplificar la configuración de las aplicaciones y poder  introducir cambios en las rutas a los archivos de entrada y salida con facilidad.xls que tenemos almacenado en la sección de recursos y escribir las celdas adecuadas  para que éste muestre las gráficas deseadas. se ordenarán todas las  entradas   en   función   del   numero   de   threads   de   cada   una.jar.Una vez que se ha creado el archivo de almacenamiento store. dado que es posible que algunas pruebas hayan sido repetidas. la tabla las mostrara de forma diferenciada. por lo que si  existen dos o mas pruebas repetidas.   hemos  decidido  implementa  otra funcionalidad  que  escribe  una  tabla   de   resultados   en   la   linea   de   comandos   con   todos   los   datos   obtenidos   en   las   distintas  iteraciones. Este proceso se llevará  a cabo en dos fases. En primer lugar.   para   posteriormente   ir   leyendo   las  distintas lineas del archivo y e ir calculando las medias de las que estén repetidas. 38 .jar con el argumento  “0”. Una vez que tenemos sólo los valores que queremos mostrar.xls. bastará  con acceder al modelo  template. En una primera operación. Esta tabla tomas los datos directamente a partir del archivo store.   bastará   con   ejecutar  JmeterReports. será  necesario  calcular la media entre las distintas entradas con un valor igual de la columna thread. Al igual que en el caso de BboxGenerator. Para  una  visualización  rápida.xls y habiendo finalizado todas y  cada   una   de   las   diferentes   pruebas   que   se   quieren   mostrar.

 dado que la naturaleza de estas  tareas requiere de un administrador con suficientes permisos para ello. así   como un repositorio a partir del cual se pueda.4.   pudiendo   así   fomentar   la   colaboración   de   una   manera   muy  notable y permitiendo además trabajar reutilizando módulos ya existentes. El uso de SVN permite además que varias personas estén trabajando y modificando el mismo  proyecto   de   manera   simultanea. Para ello se ha creado una estructura que defina el software a construir y sus dependencias. se hace necesario la creación de una  estructura   que   permita   su   portabilidad   a   cualquier   ámbito   y   su   accesibilidad   dentro   de   los  servidores en lo que se trabaja.4.2. Tanto la definición de la estructura de Maven como la creación de repositorios en el servidor del  laboratorio. 39 . tanto descargar la aplicación como actualizarla. Estas estructuras permiten también alojar recursos  (como template. corrieron a cargo de técnicos del propio laboratorio.  modificarla o simplemente integrarla en otros proyectos Maven.­ ESTRUCTURA MAVEN – SVN Dado que se pretende integrar los resultados y los métodos que componen este proyecto con  otros proyectos y trabajos llevados a cabo por el IDELAB.xls) dentro de la estructura  reduciendo así el número de archivos externos que el usuario va a tener que manejar.

 siempre que se tengan los permisos necesarios para ello.sh Este script consiste en una serie de ordenes encaminadas a introducir todos los datos que son  necesarios para el correcto funcionamiento de la estructura que hemos construido con el Jmeter. dejando los  datos obtenidos de otras capas intactos.  dado que se encuentra ubicados en la carpeta /tmp/ del sistema de archivos 40 ..2. Su  funcionamiento es muy simple. Tanto TileCache como WMSCwrapper pierden sus caches al cabo de un tiempo determinado.4.  Además funciona como elemento de cohesión entre los distintos elementos y permite direccionar  los flujos de datos en función de donde se encuentren ubicados cada uno .  así   como   proporcionar   una   visualización   del   punto   en   el   que   se   encuentra   el   proceso   en   un  determinado momento.png. Para facilitar la labor hemos creado este sencillo script.5. A.. PATH. lo  único  que hay que hacer es localizar estos archivos dentro de las direcciones de las caches y eliminarlos  . En función de la capa a la que se haya accedido es posible realizar un vaciado parcial.­ SCRIPTS A la hora de llevar a cabo   cada una de las  pruebas. HOST. Esto facilita la tarea de  configuración de todo el sistema mediante unos pocos cambios en su código.­Clean_caches.­ Benchmark. Para solucionar este problema nos hemos planteado la opción de  crear tres sencillos scripts que facilitan sensiblemente la tarea y reducen la posibilidad de error al  introducir todos los datos que se requieren para cada una de las simulaciones. Dado que las teselas son almacenadas en formato .sh En muchos casos es necesario proceder al vaciado de las caches para poder controlar y restringir  su uso en determinadas situaciones.   B.. sería necesario realizar una orden que  incluyese cada una de las variables recogidas en el archivo de Jmeter (OUT.)  para todas y cada una de las iteraciones.. lo que supondría ralentizar el proceso y provocar la  existencia de posibles errores.

sh   1.   luego   . provocará que ejecutemos  un   .  Asi por tanto una ejecución del tipo ./benchmark./clean_caches.sh 4 cleancache 7 8.sh   8./benchmark.­ Bench_start.jar con el argumento correspondiente para la  realización del reporte de los resultados (0)./benchmark.   realizará  automáticamente una llamada a la aplicación JMeterReport con el fin de almacenar los resultados  de esa iteración concreta.   así   como   la   gestión   del   script   clean_caches.sh. Si no se desea añadir argumentos a la hora de la ejecución.   Justo   después   de   la   ejecución   de   .C. Este script ofrece la posibilidad de indicarle el numero de threads deseados para cada ejecución.  así como ordenarle o no la limpieza de caches entre cada una de las ejecuciones.sh   y   la   eliminación   de   los   archivos  pertenecientes a anteriores ejecuciones.sh 10./benchmark. la función tomará  los valores que le  hemos   asignado   por   defecto./bench_start. o bien efectuar  una prueba por defecto.   es   decir.sh   5   y  finalmente . Finalmente ejecutamos la aplicación JmeterReports. 5 y 10 respectivamente sin realizar  vaciado en las cachés.   ejecutará   .   luego   un   .sh   para   distintos   valores   de   la   variable  THREADS.sh Tiene   como   finalidad   ejecutar   el   script   benchmark.   posteriormente   ./benchmark.sh   4. con los valores de threads iguales a 1.sh   7   y  finalmente       . 41 ./benchmark./benchmark.

4. tamaño. tanto en formato .  llame al script benchmark.sh para cada valor de la variable Thread indicado y genere los archivos  de salida.­ RESUMEN El esquema final del montaje realizado quedaría como indica la figura: Imagen 4.csv como las gráficas en formato .sh  para   que   éste  limpie   las   cachés.jar para generar el archivo con los bboxes con las  características que desee en cuanto a resolución. Posteriormente   bastará   con   ejecutar   el   script   bench_start.6.2. o bien las tomará de la  base de datos de cartociudad.xls 42 . zona deseada.15: Estructura del montaje final El cliente ejecutará la aplicación BboxGenerator.

3.  Hemos   conseguido   una   aplicación   que   además   de   generar   bboxes   válidos   para   realizar   las  peticiones con un interfaz de fácil comprensión.­ CONCLUSIONES Si   analizamos   las   funcionalidades   de   las   aplicaciones   creadas   y   las   características   que  buscábamos al comienzo del apartado.   se   ha   implementado   la   posibilidad   de  promediar   entre   las   distintas  pruebas repetidas sin el menor perjuicio para el rendimiento del programa.   necesaria   en   este   proyecto.4. sino que además se han añadido otras que originalmente no se encontraban en el proyecto. 43 . permite delimitar una zona cualquiera del mundo y  calcular a partir de ella los bboxes válidos siempre y cuando la resolución sea lo suficientemente  grande como para permitirlo. podemos ver que no sólo se cumplen todas y cada una de  ellas.jar a parte de conseguir igualmente todos los objetivos  marcados   en   un   principio. La principal preocupación a la hora de la realización de las aplicaciones ha consistido no sólo en  aportar   una   funcionalidad   garantizada   y   robusta. Por otro lado se ha añadido también la posibilidad de obtener los  bboxes a partir de una base de datos data.   sino   también   un  manejo sencillo y una gran portabilidad a otras máquinas para la futura realización de pruebas  similares. En cuanto a la aplicación JmeterReports.

5 ANÁLISIS DE RESULTADOS .

0. con el fin de evitar las distorsiones que se pueden producir  al tomar un número que no sea representativo de las situaciones y cargas normales de trabajo. es decir.   Cabria   esperar   que   el   rendimiento   del   servidor   vaya   variando   en   función   del   nivel   de  saturación al que va a estar sometido. alojado como servidor local.  para lo cual podemos  ir  aumentando progresivamente el número de hilos generados hasta un máximo que se ha tomado  en   20. podemos afirmar que los resultados cualitativos serán extrapolables a cualquier otra  situación. pero dado que este proyecto trata de establecer  una   comparativa   entre   las   distintas   cachés. como ya se ha  indicado con anterioridad será GeoServer [13]. Las pruebas se han realizado en una máquina Compaq Presario C700 con una conexión a internet  vía ADSL de 2Mb.   han   de   ser   realizadas   sobre   un   número  suficientemente grande de peticiones. si el factor limitante de la comunicación es la capacidad de  procesado del servidor (como es esperable).04.­ INTRODUCCIÓN En primer lugar cabe indicar que los siguientes resultados puede variar en términos absolutos en  función de la máquina en la que se realicen. las condiciones de trabajo en las que se encuentre o  de la conexión a internet de la que se disponga. estableciéndose un valor máximo estable si se produce en  él un “cuello de botella”. mientras que los datos  sobre los que se realizarán las peticiones han sido obtenidos de cartociudad [14].   y   todas   han   sido   testadas   bajo   las   mismas  condiciones. 44 .5.   El servidor utilizado. Para   que   las   pruebas   tengan   el   mayor   rigor   posible. Resulta   además   igual   de   interesante   saber   como   se   va   a   comportar   cada   caché   al   variar   el  número de usuarios que tratan  de acceder a unos  mismos  recursos. con un sistema operativo Ubuntu 8.

  para   posteriormente  enviárselas a través de cada una de las diferentes implementaciones de caché. es interesante ver en  que   medida   va   a   afectar   el   hecho   de   tener   que   pasar   todas   las   peticiones   por   un   sistema  intermedio en lugar de enviarlas directamente al servidor.2: Reducción en la tasa de servicio de teselas para TileCache 45 .   al   cual   le   enviamos   peticiones   de   manera   directa.5. En cada una de las siguientes gráficas podemos observar la  Imagen 5.1: Retardo provocado por TileCache Imagen 5.­ RETARDO AÑADIDO Antes de proceder al análisis de las diferentes cachés que se van a analizar.1. Para ello utilizamos un servidor local  WMS   (GeoServer). Evidentemente  para este estudio no puede repetirse ninguna tesela dado que sería almacenada en las caches diferencia entre cada tecnología y una situación de envío directo de peticiones al servidor:   y se desvirtuarían los resultados.

4: Reducción en la tasa de servicio de teselas para Geowebcache 46 .En la imagen 5.2 puede observarse como el servidor de teselas ofrece una tasa constante de 40  teselas   por   segundo   independientemente   del   numero   de   usuarios   que   tenga. esta tasa efectiva se sitúa entre los  30­35 teselas por segundo    Imagen 5.   mientas   que   si  tenemos que enviar las peticiones a través de TileCache.3: Retardo provocado por Geowebcache Imagen 5.

 por lo que se pierde mas de un 50% de la  eficiencia inicial del servidor Imagen 5.En el caso de Geowebcache tal y como puede verse en la imagen 5.4. la tasa efectiva de servicio  de teselas se va a situar en unas 18 por segundo.5: Retardo provocado por WMS­C­Wrapper Imagen 5.6: Reducción en la tasa de servicio de teselas para WMS­C­Wrapper En este  último caso la reducción en la tasa de provisión de teselas por parte del servidor llega  hasta casi un 25% respecto al obtenida en un escenario sin caches entre en cliente y el servidor  WMS.  47 .

48 .Vemos en general como el efecto que provocan las distintas caches que interponemos entre el  servidor y el cliente ralentizan el proceso de comunicación entre ambos entre un 50% en el caso  de Geowebcache y un 15% para TileCache. Este aumento en los tiempos de espera tendrá  que  ser compensado por el aumento en los rendimientos que se obtendrá  cuando se estudien las  ventajas del almacenamiento de teselas para cada una de las caches.

 Para ello utilizamos la misma configuración de la prueba anterior pero  rellenando previamente las caches con todas las teselas que van a ser solicitadas.2.7: Tiempo medio de respuesta. comparativa caches­servidor local 49 . En primer lugar vemos la diferencia existente entre una situación sin caches. De este modo el   cliente no tendrá que enviar ninguna petición hasta el servidor.   y   los   resultados   obtenidos   para  cada  una   de  las  caches que estamos testando: Imagen 5.­ GANANCIA Una vez cuantificado el retardo que añade el hecho de tener que pasar todas las peticiones a  través de un  nuevo sistema intermedio entre el cliente y el servidor (las caches) vamos a analizar  ahora el ahorro de tiempo que supone obtener las teselas  a  partir de las caches en lugar de   recibirlas desde el servidor. y por tanto teniendo  que  recibir   las  solicitudes   desde   el  servidor.5.

Imagen 5. comparativa caches­servidor local Podemos ver en la gráfica anterior como se obtienen unas tasas de servicio muy superiores en el  caso de solicitar las teselas a las caches que en el caso de tener que conseguirlas desde el servidor.   Si cuantificamos las ganancias como el resultado de dividir las distintas tasas de provisión de  teselas de las caches entre la tasa de la situación sin caches. obtenemos el siguiente grafico: Imagen 5.8: Tasa de provisión de teselas.9: Tasa de provisión de teselas. ganancias de las caches respecto a servidor local 50 .

 independientemente del  numero de usuarios que estén enviando solicitudes. mientras que en el caso de las caches este  parámetro si que va a condicionar ligeramente el rendimiento. 51 .   Se  puede observar también que la respuesta del servidor es siempre lineal.Podemos   ver   como   el   rendimiento   del   sistema   se   multiplica   por   un   factor   entre   8   y   12  aproximadamente  en   función   de  la   cache   utilizada   y   del   numero   de   usuarios   simultáneos.

86 400.6 1360.3 TileCache 1024.69 1313.05 Se puede observar que el mejor comportamiento va a ser siempre para Geowebcache.72 5341.49 630. por  lo que es interesante conocer a qué velocidad pueden procesar las peticiones que van a tener que  ser enviadas obligatoriamente al servidor.55 500.67 395.28 1963.86 1793.5.02 960.42 GeoWebCache 539.28 431.10: Tiempo medio de respuesta en almacenamiento threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 755.69 1490.26 708.35 2140.33 539. que se  mantiene   estable   en   el   entorno   de   los   500   ms   hasta   que   se   superan   los   10   usuarios  simultáneamente.95 444.95 2303.15 2797. Para ello probamos en primer lugar a realizar peticiones  sobre teselas totalmente diferentes y con un rango variable de resoluciones.65 1286. De el hecho de que se mantenga estable el tiempo de respuesta aunque se  vayan añadiendo más usuarios se puede deducir que el factor limitante en este caso no va a estar  en la capacidad del servidor de ofrecer teselas.­ VELOCIDAD DE ALMACENAMIENTO Inicialmente las caches respectivas de las diferentes implementaciones van a estar vac ías.74 750.3.25 806.38 419.01 1072.47 470.78 673.61 461. sino más bien en la tasa de solicitudes que tenga  52 .54 487.2 491.14 629.51 782.65 3458.27 1335.7 1459. Imagen 5.

84 4. por lo que  podemos deducir que el sistema alcanza su máximo rendimiento antes que para Geowebcache.08 3.37 2.17 5.52 11.18 4.59 7.11: Tasa media de transmisión en almacenamiento threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 1. a partir de  este punto ambas cachés parecen estar saturadas.69 16.36 4.63 GeoWebCache 1. puede observarse como existe un punto de mínimo  tiempo de espera para cuatro usuarios y que a partir de este punto  éste se dispara.56 4.93 5.88 4.25 7.46 TileCache 1.55 12.47 8.17 4.73 2.65 12.69 7.   mientras   el   máximo   tanto   para   TileCache   como   para  WMSCwrapper está  entre 7 y 8 teselas por segundo para un máximo de 4 usuarios.04 3.24 4.54 16. 53 .91 5.06 6. En el caso de WMSCwrapper y TileCache.el cliente.26 4.04 4.07 En esta gráfica puede verse que el máximo rendimiento para Geowebcache se sitúa en casi 20  teselas   por   segundo   para   15   usuarios. Esto se hace más obvio si analizamos los resultados obtenidos para las tasas o rendimiento de los  tres sistemas: Imagen 5.43 5.81 4.36 3.09 8.54 17.5 16.94 19.

También es interesante analizar el espacio en memoria que ocupa cada una de las cachés para  almacenar las teselas.07 Kb de memoria por cada tesela almacenada.64 elementos por cada tesela mientras que GeowebCache  genera   1. 54 . Esto se debe claramente a  la   forma  de   estructurar   las   memorias   y   al   número   de  archivos   que   genera  cada   una.  Concretamente TileCache genera 1. que ocupa  3.1   y   WMSCwrapper   sólo   uno   (datos   tomados   para   un   total   de   100.745 Kb por  tesela y finalmente WMSCwrapper que tan sólo ocupa 0.   ya  que  TileCache almacena las teselas con un amplio sistema de carpetas que consumen una buena  cantidad de memoria. La implementación menos eficiente es claramente TileCache.000   teselas  almacenadas en cada caché).714 Kb/tesela. seguido por Geowebcache con 0. mientras que las otras dos generan muchos menos.

82 2.­ VELOCIDAD DE ACCESO Quizá  el factor más importante es la velocidad que puede alcanzar cada una de las diferentes  implementaciones a la hora de servir teselas ya cacheadas en memoria.51 4 5.59 31.85 28.02 3.47 2.68 6.03 1.92 44.84 23.37 13.44 7. Los resultados son los siguientes: Imagen 5. Para ello cacheamos en  primer lugar 100.5.2 8.82 14.87 55 .48 7.61 17.96 27.3: Tiempo medio de respuesta en servicio desde cachés threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 1.31 6.56 16.15 13.59 27.69 27.5 3.09 4.53 TileCache 1.88 5.98 GeoWebCache 1.35 16.67 8.17 55.41 15.46 12.61 2.3.000 teselas y posteriormente efectuamos las pruebas para distinto número de  usuarios sin vaciar las memorias.8 11.

43 547.36 669.Como era de esperar en un principio. En cuanto a la tasa o rendimiento.45 475.84 615.63% en  el tiempo de respuesta de cada tesela.12 330.92 353.2 695.3 570. TileCache obtiene los peores resultados con un 63.81 GeoWebCache 494.27 783.38 721.78 56 .53 720.13: Tasa media de respuestas en servicio desde cachés threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 642. lo que da idea  de que el sistema está  trabajando a máximo rendimiento desde el mismo momento en el que  tenemos un sólo usuario.49 599.35 313.29 521.74 443.63 610.65 849.43 317.73 439.52 493.88 TileCache 381.24% de  incremento en sus tiempos medios.45 485. seguido por Geowebcache con una aumento del  9.78 468.3 470.93 709. como es obvio el mejor comportamiento responde exactamente  a los mismos patrones que la gráfica anterior: Imagen 5. el tiempo que tarda cada petición en ser contestada por el  servidor aumenta cuantos más usuarios intentan acceder de manera simultanea.24 867. Los resultados indican que WMSCwrapper es la implementación que  tiene una mayor velocidad de acceso.57 535.73 631.95 605.72 576.33 595.09 424.25 513.01 476.

 por lo que podemos afirmar que todas tienen un  máximo rendimiento para un tráfico generado por entre 2  o 3 usuarios. alcanzando en el caso de  WMSCwrapper tasas de hasta 867 teselas por segundo.   ya que  se puede  observar   que  las  tres  siguen  un  patrón  casi  idéntico  en  la  situación de sus puntos máximos y mínimos.En esta última gráfica queda claro que el rendimiento de las distintas implementaciones sigue las  mismas  normas. 57 . mientras que Geowebcache y TileCache  llegan a 721 y 605 respectivamente.

Imagen 5.42 384.18 2278.14: Tiempo medio de respuesta 75% cacheado threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 232.62 479. mientras que se tengan que obtener del servidor externo un 25%.8 376.57 435.88 221 321.06 450.59 5109.5.5.7 474.99 58 .26 1340.26 1872.3 1048.39 712.4 425.95 565.24 334.43 486.77 1400.73 936. En primer lugar  vamos a probar cómo se comportan en una situación en la cual el 75% de las peticiones se hagan  a las caches internas.08 658.14 321.38 620.32 GeoWebCache 125.2 3084.67 1819.16 889. es importante saber cómo se comporta cada  una de las caches ante distintos escenarios y porcentajes de teselas cacheadas.­ PETICIONES MIXTAS Para dar idea del rendimiento en situaciones reales.65 1520.25 1196.7 537.7 503.55 TileCache 176.35 2756.75 664.9 413.

58 TileCache 5.5 9.75 4.93 36.28 Vemos que Geowebcache puede continuar aumentando su tasa de devolución de peticiones para  mantener aproximadamente constante el tiempo de respuesta de cada tesela.16 15.32 6.67 4.97 GeoWebCache 8.65 5.78 7.85 6. mientras que tanto TileCache  como   WMSCwrapper   se   saturan   y   provocan   un   tiempo   de   respuesta   siempre   creciente.61 5.79 14.48 9.85 16.15: Tasa media de servicio 75% cacheado threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 4. mientras que tanto  TileCache como WMSCwrapper se saturan desde el principio y por tanto no son capaces de ir  aumentando su rendimiento a la par que aumenta el numero de usuarios.71 15.72 30.43 5.39 5.12 6.86 4.7 4.18 22.61 9.54 5.26 8.22 22.6 7.25 5.09 8.En este caso vemos que Geowebcache es el  único que más o menos mantiene unos tiempos  constantes de respuesta a pesar de ir aumentando los usuarios.09 6.84 6.13 4.   Si  analizamos las tasas de cada uno de ellos: Imagen 5.53 3. 59 .9 6.

92 518.75 2575.77 790.16 1205.15 724.3 60 .67 352.26 589.52 1196.97 677.24 1601.24 3861.56 865.79 1038.13 466.33 484.5 2314.76 543.2 566.41 1456.51 451.Analizamos ahora una situación análoga pero con un 50% de respuestas cacheadas.27 533. El resultado  para los tiempos de respuesta por tesela será el siguiente: Imagen 5.21 440.38 584.58 GeoWebCache 169.07 TileCache 294.22 631.54 1594.16: Tiempo medio de respuesta 50% cacheado threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 270.77 2545.5 976.15 549.68 384.38 1643.18 518.63 629.13 731.

54 16. A priori cabria esperar un comportamiento muy similar pero con un aumento  en   los   tiempos   de   respuesta   y   una   disminución   en   las   tasas   efectivas   proporcionales   a   la  disminución de otro 25% en la cantidad de respuestas que van a ser cacheadas.28 4.87 5.01 13.84 4.45 16.21 5.   hacemos   la   misma   prueba   pero   limitando   en   este   caso   el   número   de   respuestas  cacheadas al 25%.22 8. Por   último.88 6.49 4.12 6.53 9.28 5.77 Puede observarse también un patrón idéntico.% 33% y 18% respectivamente para WMSCwrapper  Geowebcache   y   TileCache.3 5.65 7.72 6.98 3.34 5. Los resultados  para los tiempos de respuesta son: 61 . salvo que al tener menos respuestas cacheadas.07 6.Imagen 5.53 7.17: Tasa media de servicio 50% cacheado threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 3.72 11.31 TileCache 3.66 7.94 28.23 8.93 7.05 10.09 12.9 4.98 5.     Este   porcentaje   está   en   consonancia   con   el   25%   de   respuesta  cacheadas que hemos reducido.77 4.  todas las tasas se ven un reducidas en un 27.42 30.49 6.32 3.31 GeoWebCache 5.

72 1426.99 Y en el caso de las tasas: Imagen 5.55 2006.98 697.23 880.27 672.86 TileCache 704.27 548.45 1012.67 1126.29 696.91 1305.6 3003.4 1843.65 595.Imagen 5.25 3384.33 1183.19 984.98 1163.61 616.05 1110.81 1113.12 3631.53 1034.7 623.04 597.19: Tasa media de servicio 25% cacheado 62 .18 1143.64 GeoWebCache 433.81 1099.18: Tiempo medio de respuesta 25% cacheado threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 795.56 584.96 1276.81 1502.96 787.76 507.16 1405.55 1649.

5 2.61 8.87 9.84 6.98 3.   el   comportamiento   de  Geowebcache se mantiene estable dentro dentro del rango de usuarios al que lo hemos sometido.3%.3 Si   calculamos   de   nuevo   la   variación   respecto   al   caso   anterior.4% respectivamente para WMSCwrapper. Esto confirma nuestra idea inicial en la estabilidad del comportamiento  de las distintas cachés.8% y 37.49 1.67 GeoWebCache 2.68 23.  Geowebcache y TileCache. 25.29 4.14 4.48 11.74 3.37 6.39 2.95 11.6 4.11 20.   Para conocer el techo de la tasa de devolución de teselas para Geowebcache realizamos una  prueba extra añadiendo un rango mucho más amplio aunque menos detallado de usuarios.18 6.34 5.68 2.11 5.6 4.24 9.36 5.45 2.49 4.   vemos   que   en   este   caso   la  reducción de las tasas se sitúa en 20.49 10.threads 1 2 3 4 5 6 7 8 9 10 15 20 WMSCWrapper 1.83 4.  mientras   que   TileCache   y   WMSCwrapper   se   saturan   con   un   número   relativamente   bajo   de  usuarios y se mantienen en esas tasas.65 3.22 5.55 TileCache 1.16 8.76 3. Como   puede   observarse   en   el   desarrollo   de   las   pruebas   mixtas. para  una situación de obtención de teselas sin cachear: 63 .27 5.11 3.

Imagen 5.21: Tasa media de servicio Geowebcache Puede   observarse   que   se   mantiene   en   tiempos   de   espera   más   o   menos   estables   hasta   un  máximo de 20 usuarios simultáneos.20: Tiempo medio de respuesta Geowebcache Imagen 5. 64 . llegando en ese momento a la saturación del sistema. Puede   decirse   por   tanto   que   Geowebcache   tiene   una   capacidad   de   admisión   de   teselas  simultáneas muy superior a lo que han demostrado tanto TileCache como WMSCwrapper.

22: Comparativa del tiempo medio de respuesta en función del área de metatiling 65 .6.  Además. el metatiling consiste básicamente en la solicitud  automática de teselas alrededor de la zona indicada por el cliente. por  lo   que   los   resultados   absolutos   no   tienen   por   qué   coincidir   con   otros   tomados   anteriormente. Por otro lado. Por cada petición que realicemos.­ METATILING Como ya se explicó  en apartados anteriores. se viera compensado por el hecho de lograr tener  cacheada un área importante rodeando a dicha zona. 9 0 25  teselas centrada en la deseada. ahorrando por  tanto la realización de más peticiones que acarrearían un retardo mayor. De este modo se logra pre­ cachear áreas de terreno que es probable que el cliente consulte con posterioridad. en realidad realizaremos una consulta a una zona de 1. que por cada tesela  que deseemos solicitar al servidor.  aunque   dado   que   el   objetivo   es   realizar   un   benchmark   comparativo   no   tiene   porqué   afectar. nuestro cliente solicitará  conjuntamente un número de teselas  mayor.5.   cabe   esperar   que   los  retardos disminuyan como consecuencia de la inclusión de mas teselas en las caches: Imagen 5. 3x3 y 5x5. esto es. también sería conveniente que este aumento en el  tiempo de espera por cada tesela solicitada. el estudio se realiza para un único usuario simultaneo y sobre una zona delimitada. En nuestro caso vamos a estudiar un metatiling de  1x1. Este estudio ha sido llevado a cabo en otra máquina distinta. por  lo   que   al   aumentar   el   numero   de   teselas   solicitadas   en   cada   petición. por lo que cabe esperar que los tiempos de espera hasta recibir respuesta del servidor  aumenten considerablemente.

23: Comparativa de la tasa de provisión de teselas en función del área de metatiling Como se puede ver en las imágenes 5.22 y 5.   mientras  que  para  un valor  de 3x3  se  encuentra empatado con TileCache.Imagen 5. la tasa efectiva final aumenta de manera considerable debido a que  cada vez un mayor porcentaje de teselas serán obtenidas de las cachés.23. Este aumento del rendimiento de WMSCwrapper respecto a  sus competidores al aumentar el tamaño de la zona cacheada en cada solicitud se debe al distinto  tratamiento que cada una de las tecnologías hace del metatiling. Si comparamos los resultados de cada una de las distintas caches entre sí. a medida que aumentamos el número de teselas  solicitadas con cada petición. mientras que TileCache y Geowebcache sí pueden repetir solicitudes. 66 . dado que WMSCwrapper trata de  adaptar el contorno de las zonas solicitadas de modo que no se le pida al servidor ninguna tesela  que ya haya sido cacheada. podemos observar  cómo WMSCwrapper proporciona un menor tiempo de espera y por tanto una tasa de transmisión  efectiva  de teselas  superior  para  un metatiling de  5x5.

 Para ello vamos a realizar una medici ón utilizando  la   herramienta  Jmeter. – Imagen 5.7. Un bloque de petición HTTP con los siguientes datos: – – – – – – Nombre de Servidor o IP: localhost Puerto: 8888 Path: /manager/status Será  también necesario mandar un parámetro con la petición con Nombre XML y el valor  true. Geowebcache y WMSCwrapper.5. Obviamente compararemos resultados obtenidos para ambas cachés en las mismas condiciones  de trabajo de la máquina.2. ordenándolas en base al número de usuarios en cada prueba. es decir. obteniendo datos  sólo cada 5000 ms. para no entorpecer la actuación de la aplicación.24: Configuración de Jmeter para la medición del uso de recursos De este modo podemos obtener los datos referentes a las dos implementaciones que trabajan  sobre el gestor de contenedores Apache Tomcat. – Temporizador constante. Un bloque de Resultados del Monitor para visualizar los resultados.­ USO DE RECURSOS Es importante tener también en cuenta el nivel de utilización de los recursos de la CPU que van a  consumir cada una de las diferentes caches  .1 otro grupo de  hilos con los siguientes componentes: Gestor de Autorizaciones HTTP: será necesario introducir user y password del tomcat. Esto se consigue añadiendo a la configuración explicada en el apartado 4. 67 .  configurada   para  calcular   los   parámetros   de   utilización   de  aplicaciones  web.

 por lo que los resultados no podrían ser comparados  con   los   obtenidos   de   este   modo.   Además   en   todos   los   apartados   anteriores. la linea  azul   representa   el   porcentaje   de   la   carga   computacional.La linea roja representa el porcentaje de hilos ocupados respecto al máximo permitido. haciendo un uso de la memoria y  una carga computacional análoga. No se incluyen resultados para TileCache dado que el sistema de medición debería de ser otro  completamente distinto a no estar gestionado por el contenedor de paquetes tomcat de la misma  manera que Geowebcache y WMSCwrapper.25: Comparativa del consumo de recursos para un usuario Los resultados son prácticamente los mismos en ambos casos.   la   linea   amarilla   el   porcentaje   de  memoria utilizada respecto al total. por lo  que su utilización no va a ser en ningún caso la más indicada. El indicador de la salud de la aplicación en ambos caso es del  100%   para   esta   prueba.   Probamos   a   continuación   para   un   número   de   usuarios   de   cinco  simultáneos: 68 . Comenzamos la prueba con un solo usuario : Imagen 5. y la linea verde da una idea de la salud general del sistema  para la prueba concreta.   TileCache   ha  demostrado ser la implementación menos efectiva en todas y cada una de las situaciones.

Imagen 5.27: Comparativa del consumo de recursos para 15 usuarios 69 . Aumentamos ahora el numero de usuarios hasta  los 15: Imagen 5.26: Comparativa del consumo de recursos para 5 usuarios Vemos   que   de   momento   los   resultados   se   siguen   manteniendo   muy   parejos   en   ambas  situaciones. por lo que a estas alturas de la prueba las dos cachés siguen funcionando al mismo  ritmo y sin aparentes problemas de sobrecarga.

 que si bien  se han visto sutilmente incrementadas respecto a los casos anteriores. este alza no llega a afectar  a la salud total de la aplicación. Aumentamos ahora el número de usuarios hasta situarlo en 35.  Donde se podría esperar que la  salud del sistema comenzase a resentirse. Imagen 5.   En   cuanto   a  la   diferencia   entre  ambas caches . si bien pueden observarse unas cargas y unos usos de memoria ligeramente importante. pero todavía no puede decirse  que   la   salud   de   las   aplicaciones   se   encuentre   comprometida.  exactamente del mismo modo que para un numero menor de usuarios. y el uso de la memoria se acerca en algunos puntos al 100%.   esta   diferencia   no   es   sustancialmente  70 . pero no se nota un aumento considerable ni en la carga  computacional que está soportando el sistema ni en la utilización de la memoria total.    inferiores   en   WMSCwrapper   que   en   Geowebcache.28: Comparativa del consumo de recursos para 35 usuarios La carga total que implica el aumento de usuarios supera ahora en algunos momentos el 50% del  total.Se puede observar ahora como es evidente el aumento en el porcentaje de hilos que están siendo  utilizados respecto al máximo permitido. que se mantiene en todo momento al tope de sus posibilidades.

 éstas tienen una duración menor.Aumentamos el número de usuarios hasta 50 simultáneos.29: Comparativa del consumo de recursos para 50 usuarios Por último realizamos las pruebas para 75 usuarios simultáneos: 71 . por lo que ahora si. pero son más acusados  para Geowebcache que para WMSCwrapper.   Estos   efectos   generales   sobre   los   distintos  parámetros que estamos midiendo son compartidos por las dos cachés. que si bien alcanza también cotas igualmente bajas  en el nivel de salud. vemos como el  sistema   empieza   a   resentirse   y  se   alcanzan   puntos   en   los   cuales   la   salud   del   sistema   se   ve  comprometida   y   desciende   hasta   un   65­70%. Imagen 5.

 De  los   distintos  resultados  podemos  concluir   que  para  un  numero  relativamente   bajo  de   usuarios  (hasta 30­35) el sistema mantiene sus parámetro más o menos constantes y parejos para ambas. llegando incluso en a sufrir una caída en el uso efectivo de memoria y en la  carga computacional debido a dicha saturación al alcanzar los 75 usuarios.  mientras que si superamos este umbral Geowebcache degrada sus prestaciones a un mayor ritmo  que WMSCwrapper.30: Comparativa del consumo de recursos para 75 usuarios En estas dos últimas pruebas podemos observar como un exceso de usuarios simultáneos satura  el sistema impidiendo que la aplicación correspondiente responda las peticiones que recibe. 72 .Imagen 5.

5.   siempre   se   va   a   ver   cómo  WMSCwrapper obtiene unos resultados cada vez más distantes de sus competidores debido al  sistema adaptativo de petición de teselas en función de las ya solicitadas. llegándose  a   la   conclusión   de   que   tanto   en   el   caso   de   WMSCwrapper   como   en   el   de   Geowebcache   o  TileCache se produce un retardo por petición similar para una zona de metatiling de 1x1. Por un lado  tenemos   los   resultados   referentes   a   la   capacidad   y   velocidad   de   los   sistemas. que es la que ofrece unos  tiempos   de   espera   mayores. si analizamos situaciones mixtas en las cuales  tengamos un porcentaje de teselas cacheadas y otro de teselas por cachear.  Como consecuencia de estos comportamientos. bastará  que un pequeño porcentaje de teselas  tengan que ser solicitadas al servidor para que los resultados de Geowebcache sean mejores que  los   de   WMSCwrapper. También se ha analizado el efecto del metatiling en cada una de las implementaciones.   mientras   que   WMSCwrapper   es   la   que   obtiene   unas   mayores  tasas de respuestas por segundo.   Por   su   parte   TileCache   obtiene   en   todos   los   estudios   los   peores  comportamientos  en  relación   con  sus   competidores. Debido a la diferencia que existe entre el tiempo de espera  por cada tesela sin cachear y por cada tesela cacheada (entre 500 y 1000 veces superior en el  caso de tener que realizar la petición al servidor).   podemos   concluir   que   Geowebcache   posee   unos   resultados   muy  superiores a sus dos competidores a la hora de pedir teselas y almacenarlas en la memoria local.8.   En   cuanto   al   servicio   de   teselas   ya   cacheadas   TileCache   sigue  manteniendo   el   peor   resultado.   tanto  a  la  hora  de   almacenar   las   teselas  como a la hora de servirlas.­ RESUMEN  De los completos tests que hemos realizado sobre cada una de las tres caches sometidas a estudio   podemos llegar a varias conclusiones generales que se subdividen en dos campos.   mientras   que   si   aumentamos   mas   este   parámetro. 73 . Ciñéndonos a los tiempos de espera y las tasas de provisión de teselas que tienen cada una de  las   tres   implementaciones.   y   por   otro   los  relativos a las cargas y usos de memoria. los resultados de  Geowebcache  y WMSCwrapper  irán  convergiendo  cuanto  mayor  sea  el  ratio  entre  las   teselas  cacheadas y las teselas sin cachear.  muy por encima de los resultados de WMSCwrapper y TileCache. En el  caso   de   extenderla   a   3x3   WMSCwrapper   y   TileCache   obtienen   mejores   resultados   que  Geowebcache.

 nos hemos ceñido solamente a  WMSCwrapper y Geowebcache.En cuanto al estudio de los recurso que consume cada caché. llegando incluso  para Geowebcache a producirse caídas importantes en el uso de memoria y en el porcentaje de  carga. 74 . pero en ambas  caches  se  nota una saturación importante por encima de los 60­75 usuarios simultáneos.  manteniendo   una   salud   general   del   sistema   óptima   y   unos   usos   de   memoria   y   de   carga  computacional que se van incrementando a medida que aumentamos el número de clientes. la salud del sistema se va deteriorando con mayor  velocidad  en  el  caso  de  Geowebcache que en el de WMSCwrapper.  En general los  resultados  obtenidos  son  realmente parejos para uno número de usuarios relativamente bajo (menos de 30­35 usuarios). que son las implementaciones que funcionan de un modo similar  sobre el contenedor  de  aplicaciones Apache Tomcat. A  partir de este umbral en el número de usuarios.

6 CONCLUSIONES Y LÍNEAS FUTURAS .

 si bien no eran predecibles a priori. En cuanto a los objetivos fijados al principio del proyecto puede decirse que se han cumplido todos  y cada uno de ellos. los resultados son claros y. o el manejo de aplicaciones Web.­ CONCLUSIONES A lo largo de este proyecto se ha ilustrado el funcionamiento de los servidores de mapas WMS.  modular  y  de  un  manejo   rápido   y   sencillo.  sí son lo suficientemente sólidos y consistentes como para ser tomados como correctos.   y   que   además   puede   ser   adaptado   para   posteriores   pruebas   en   entornos  similares sin un excesivo trabajo.  También   se   han   descrito   las   distintas   herramientas   que   se   utilizan   en   las   mediciones   y   las  configuraciones que requieren para su correcto funcionamiento. pero también iniciarme en el mundo de  los sistemas geográficos y las tecnologías de los sistemas de mapas.  investigación.   así   como   las   interconexiones   necesarias.1. su  utilización y propiedades.  En lo referente a las pruebas en sí. software. Personalmente. Además  considero   que   hemos   realizado   un   trabajo     que   ha   abarcado   diferentes   cuestiones   (teoría.   ya  que   se   ha   conseguido   alcanzar   los   objetivos   que   se   marcaron   al  comienzo   del   proyecto   de   una   forma   totalmente   satisfactoria. campo de gran auge en la  actualidad debido a multitud de soportes muy populares y muy utilizados hoy en día. ya que se ha conseguido construir un sólido mecanismo de pruebas para las  distintas  caches. 75 . portable  ( al  estar  construido  en  JAVA ).  robusto. así como una descripción de la tecnología WMS­C y en particular de los  distintos sistemas de cacheado de teselas que se implementan. la valoración que hago del trabajo realizado a lo largo del desarrollo del proyecto  es   francamente   positiva.   como   pueda   ser   la  programación en JAVA.6.   permitiéndome   ahondar   en  conocimientos   ya   esbozados   durante   algunas   asignaturas   de   la   carrera.) que me permiten tener ahora una visión general sobre cómo trabajan  y como se desarrollan herramientas orientadas a la gestión de mapas. Se ha establecido un método para  la   comparación   de   tres   de   las   opciones   disponibles   en   el   mercado   y   se   han   construido   las  aplicaciones   necesarias   para   su   correcto   desarrollo. etc.

. Del mismo modo sería interesante conocer cuáles son los tiempos de  latencia de las teselas en las caches que optimizan el gasto de recursos frente  a  la posibilidad de   demandar zonas ya almacenadas. por lo que sería necesario realizar un estudio sobre las mejoras en el rendimiento  general de la aplicación que  va a percibir  el usuario final  del servicio como consecuencia del  sobrecacheado de teselas.   sino   que   se   establezca   un   punto   a   partir   del   cual   se   distribuyan   las  peticiones ya almacenadas a los clientes sin necesidad de consumir los recursos locales.2. de modo que en definitiva sólo  tenemos una idea general de como se comportan las distintas aplicaciones.6..   que   la   tesela   se  encuentre cacheada en la memoria o que ésta tenga que ser solicitada al servidor. Resultaría interesante establecer planes de peticiones en base a consultas reales para conocer  además el verdadero alcance del metatiling. área. En nuestro caso se han establecido  los   rendimientos   estadísticos   basándonos   en   dos   posibles   circunstancias.). pero  no ciñéndose al comportamiento que suele seguir un usuario. capa. 76 . pero en ningún  caso se ha relacionado la petición de una tesela con la siguiente. En este proyecto se ha estudiado solamente el efecto  del metatiling en el retraso que sufre cada petición respecto a una situación análoga pero sin esta  opción activada.  Por otro lado también puede resultar interesante combinar las distintas tecnologías que hemos  probado con otros servidores de mapas o simplemente configurarlas para que no almacenen las  teselas   de   forma   local.­ LÍNEAS FUTURAS El análisis llevado a cabo en este proyecto se ha basado en unas secuencias de peticiones de  teselas aleatorias dentro de unas determinadas condiciones fijadas(resolución.   y   que   arrojarían  resultados mas coherentes a un uso real de estos servicios. Existen estudios que establecen  patrones   de   comportamiento   en   las   peticiones   efectuadas   por   el   cliente.

77 .6. y  por supuesto a todos  los amigos que en estos años me han hecho sentir en casa fuera de mi casa. me gustaría agradecer a toda la gente que me ha apoyado durante la realización de  este proyecto.   así   como   a   mi   familia   por   la   tremenda  paciencia en tantos años de estudio más allá de los éxitos y los fracasos. no habría sido posible su realización sin la colaboración de  sus integrantes.  También agradecer a Cecilia su contribución “artística” y su apoyo absoluto en los buenos. especialmente de Ricardo. malos y  regulares   momentos   a   lo   largo   de   todo   este   tiempo. saber hacer y sobre todo su paciencia. Dado que esta tarea se enmarca dentro de los trabajos del departamento ITNT­ ITAST de la universidad de Valladolid. por su tiempo.3.­ AGRADECIMIENTOS Para acabar.

BIBLIOGRAFÍA

[1] www.abcdatos.com  (última consulta 10/10/09) [2] http://es.wikipedia.org/wiki/Sistema_de_Informaci%C3%B3n_Geogr%C3%A1fica (última  consulta 18/11/09) [3] http://www.opengeospatial.org/standards/wms#schemas (última consulta 07/10/09) [4] en.wikipedia.org/wiki/Web_Map_Service (última consulta 10/12/09) [5] OGC Implementation Specification (http://portal.opengeospatial.org) (última consulta 21/10/09) [6] http://wiki.osgeo.org/wiki/TilingStandard (última consulta 10/10/09) [7] http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification (última consulta 21/12/09) [8] http://wiki.osgeo.org/wiki/WMS_Tiling_Client_Recommendation (última consulta 21/10/09) [9] http://wiki.osgeo.org/wiki/WMS_Tile_Caching (última consulta 21/10/09) [10] http://tilecache.org/ (última consulta 03/10/09) [11] http://geowebcache.org (última consulta 03/10/09) [12] wmsc­wrapper documentation http://localhost:8888/WMS_C_wrapper/ (última consulta  03/01/10) [13] geoserver.org/ (última consulta 19/11/09) [14] www.cartociudad.es (última consulta 01/12/09) [15] http://presentations.opengeo.org/2008_FOSS4G/WebMapServerPerformance­ FOSS4G2008.pdf (última consulta 10/12/09) [16]  poi.apache.org/ (última consulta 1/11/09)

APÉNDICE I

INSTALACIÓN DE LAS CACHÉS

4 hardy haeron. Se instalará de la misma  forma que el anterior.1. a partir de los repositorios oficiales disponibles para Ubuntu y haciendo uso  del gestor de paquetes por defecto Synaptic. es necesario la instalación y configuración  de  ciertos  elementos que  se  encuentran  fácilmente  en  muchas  máquinas  sin   los   cuales  sería  imposible   llegar   a   los   resultados   deseados.   ya   que   algunas   de   ellas  necesitan de otras para su correcta implantación y/o configuración.   ni   de   instalación. 1. 1. En nuestro caso se instalará  a partir de los repositorios oficiales  de Ubuntu y mediante el uso del gestor de paquetes Synaptic Java runtime enviroment: permite la ejecución de programas en Java.   En   este   primer   apartado   de   requisitos   previos   se  enumeran los distintos componentes necesarios para soportar el resto de la estructura que se  creará. 1 .0.­  INSTALACIÓN DE COMPONENTES Para el ensamblaje de los distintos elementos que van a ser necesarios en el correcto desarrollo  del proyecto.   se   hará   un   breve   comentario   sin   entrar   a   detallarlos   en  profundidad. se hace necesario la instalación tanto del Java development kit como del  Java runtime enviroment.   Dado   que   en  muchos  casos   son  bastante   comunes   y   no  requieren  un   esfuerzo  ni  de  configuración. Java   development   kit(jdk):  es   un   software   que   provee   herramientas   de   desarrollo   para   la  creación de programas en java. Por lo tanto aquí  se exponen  en el orden y con el método con el cual fueron instaladas.­ JAVA Dado   que   tanto   la   aplicación   que   vamos   a   crear   como   muchas   otras   ya   existentes   está   programadas en Java. es necesario seguir unas ciertas instrucciones proporcionadas por los distribuidores  de   las   distintas   herramientas   e   instalarlas   en   el   orden   apropiado.1.­ REQUISITOS PREVIOS Dada la naturaleza del proyecto que se va a desarrollar. Todos los trabajos y pruebas efectuados  en   este   proyecto   fueron   realizados   en   una   máquina   Compaq   C700   bajo   un   sistema   operativo  Ubuntu 8.1.1.

org). A continuación se detalla el método de instalación: 2 .0. está desarrollado por la Apache Software Foundation. como en nuestro caso Apache. En nuestro proyecto se hace necesaria la presencia de un servidor web dado que las pruebas de  los distintos modelos de caché se realizan mediante peticiones HTTP dirigidas al servidor a través  de cada una de las tecnologías. 1.).  estando escrita en Java. Esta herramienta está  desarrollada bajo el proyecto Jakarta en la Apache Software Foundation.1. Windows.apache. Macintosh.­ APACHE WEB SERVER Este servidor web HTTP de código abierto escrito en C. se considera que se optimizan sus prestaciones si se  combina con otro servidor mas potente. En nuestro caso se ha instalado la versión 6.2.3. lo que permite su funcionamiento en cualquier máquina que contenga la  maquina virtual Java. por lo que la descarga. Aunque puede funcionar de forma  autónoma como servidor web por si mismo. por lo que es indispensable un servidor de este tipo que las  gestione. cuyo código fuente se encuentra disponible en su  página web oficial (http://tomcat.. y diseñado para casi cualquier plataforma  (Unix.­ APACHE TOMCAT Apache Tomcat funciona como un contenedor de servlets (programas ejecutados en un servidor) y  de Java Server Pages (desarrolladas por Sun Microsistems).. siendo en la  actualidad el mas utilizado en el mundo debido principalmente a su gran capacidad de adaptarse a  múltiples entornos debido a que es fácilmente configurable. instalación y  configuración se realizaron de forma casi automática.1. si bien carece de interfaz gráfica que  facilite este proceso. En nuestro caso se instaló  la versión Apache2 directamente desde los repositorios oficiales de  Ubuntu y mediante el uso del gestor de paquetes Synaptic.1.

0.18.   las   siguientes   lineas   se  agregan al final de archivo: #vim .06 Entonces la variable de entorno JAVA_HOME debe apuntar a usr/lib/jvm/java­6­sun. si no nos sale esto.tomcat-6.gz Entramos a nuestro directorio hogar en nuestro caso /home/pablo/ #cd /home/pablo Ahora.0.6.18.0.tar. debemos buscar la ruta en donde  se instalo java Ahora   agregamos   la   variables   de   entorno   a   nuestro   archivo   . vamos a configurar las variables de entorno JAVA_HOME y CATALINA_HOME Probamos: #ls /usr/lib/jvm/ Si nos sale: java­6­sun java­6­sun­1.bashrc. Nota: Los números varían según la versión.Nos logeamos como root: su passwd: Copiamos el archivo descargado a /usr/local/ #cp /media/Datos/Software/Sistemas\ Linux/Servidores\ Web/Apache\ Tomcat/ apache.bashrc 3 .gz /usr/local/ Descomprimimos y desempaquetamos: #tar -zxvf apache-tomcat-6.tar.

Si deseamos parar nuestro servidor web: #/usr/local/apache-tomcat-6.18/temp Using JRE_HOME: /usr/lib/jvm/java-6-sun Probamos en un navegador web: http://localhost:8080/ Si nos aparece la página de Apache Tomcat.18/bin/shutdown.0.18 Salimos y guardamos cambios.0.0.18/webapps/ROOT/ El archivo de configuración de Apache Tomcat es: #vim /usr/local//apache-tomcat-6.18/conf/server. todo esta correcto.18 Using CATALINA_HOME: /usr/local/apache-tomcat-6.Agregamos al final: export JAVA_HOME=/usr/lib/jvm/java-6-sun export CATALINA_HOME=/usr/local/apache-tomcat-6.18 Using CATALINA_TMPDIR: /usr/local/apache-tomcat-6.sh Nos muestran los siguientes mensajes: Using CATALINA_BASE: /usr/local/apache-tomcat-6.0.18/bin/startup.0.0. ahora tendremos soporte para  código de jsp y servlets de java.0. Ahora levantamos nuestro servidor Apache Tomcat #/usr/local/apache-tomcat-6.xml 4 .sh El directorio de publicación es: #cd /usr/local/apache-tomcat-6.0.

1.5.gz 1. las aplicaciones basadas en la plataforma Eclipse pueden ser extendidas  fácilmente por otros desarrolladores de software.   una   organización  independiente sin ánimo de lucro que fomenta una comunidad de código abierto y un conjunto de  productos complementarios.2.2.0.  ideada para un fin muy concreto.   Debido   a   que   los   módulos   pueden   ser   desarrollados  independientemente. capacidades y servicios.18. pueda ser extendida para su uso en otros entornos similares al  que nos ocupa.   extendiendo   constantemente   las   áreas   de  aplicación cubiertas.  Eclipse fue desarrollado originalmente por IBM como el sucesor de su familia de herramientas  para   VisualAgel. En cuanto a la instalación en nuestra máquina resulta extremadamente sencilla.org (en nuestro caso instalamos la versión 3.   Eclipse   es   ahora   desarrollado   por   la   Fundación   Eclipse.­ ECLIPSE La plataforma Eclipse permite que las aplicaciones sean desarrolladas a partir de un conjunto de  componentes de Software llamados módulos. así  como una guía de cómo han sido instaladas y configuradas en nuestra  máquina. 1. Un módulo es un archivo Java que contiene clases  de java escritas para interactuar con las APIs de Eclipse y un archivo especial (manifest file) que lo  identifica como módulo. Eclipse   es   también   una   comunidad   de   usuarios. ya que no es  necesario mas que bajarse el instalador de la versión deseada directamente desde su página web  http://eclipse. la última disponible hasta la fecha de  5 .tar.­ COMPONENTES ESPECÍFICOS En este apartado se incluirán descripciones mas detalladas de las herramientas utilizadas a lo  largo del proyecto. logrando así  que aplicaciones como la nuestra. Las aplicaciones construidas a partir de módulos pueden ser extendidas  agregándole   nuevos   módulos.Podemos eliminar el fichero descargado  al terminar la instalación: #rm -r /usr/local/apache-tomcat-6..

 y el orden de construcción de los  elementos. sino  también para subir artefactos al repositorio al final de la construcción de la aplicación.  sus dependencias de otros módulos y componentes externos.   será  necesario instalar un gestor  de proyectos. ejecutar el archivo del instalador y seguir  los  pasos  indicados por el  mismo para su configuración.   para   cualquier   otro   lenguaje. pero su adopción  ha sido muy lenta. Maven utiliza un Project Object Model (POM) para describir el proyecto de software a construir. Maven provee soporte no sólo para obtener archivos de su repositorio. el repositorio Maven  . Este repositorio y su sucesor reorganizado. Dado   que   también   serán   necesarios   otros   componentes   que   interactúan   con   Eclipse. dejándola al  acceso de todos los usuarios. Una caché  local de artefactos actúa como la primera fuente para  sincronizar la salida de los proyectos a un sistema local.  En teoría. en nuestro caso nos hemos decantados por utilizar  Maven. 6 . pugnan por ser el mecanismo de facto de distribución de aplicaciones en Java. Una característica clave de Maven es que está  listo para usar en red. el soporte y uso de lenguajes distintos de Java es mínimo. esto podría permitir a cualquiera escribir plugins para su interfaz con herramientas como  compiladores. de Apache y otras  organizaciones y desarrolladores.   etcétera.   en  nuestro caso  Subversion  (SVN)   para   poder   actualizar   los   distintos   repositorios   creados   a   medida   que   vayan   siendo  modificados. Actualmente existe un plugin  para . Maven   está   construido   usando   una   arquitectura   basada   en   plugins   que   permite   que   utilice  cualquier aplicación controlable a través de la entrada estándar.Net Framework y es mantenido. El motor incluido en su  núcleo puede dinámicamente descargar plugins de un repositorio.[1] y un plugin nativo para C/C++ fue alguna vez mantenido  por Maven. Además  se utilizará   también  un  sistema  de  control  de  versiones.realización del proyecto).   herramientas   de   pruebas   unitarias. Viene con objetivos predefinidos para realizar ciertas tareas claramente especificadas  como la compilación del código y su empaquetado. el mismo repositorio que provee  acceso a muchas versiones de diferentes proyectos Open Source en Java.   En  realidad.

  requisiciones   FTP   y  prácticamente cualquier otro medio.  siendo capaz de manipular resultados en determinada petición y reutilizarlos para ser empleados  en una nueva secuencia. 7 .Para la instalación tanto de Maven como de SVN basta con abrir el Eclipse.2.   ya   que   basta   con   descargar   el  programa desde su página web oficial (en nuestro caso la versión elegida es la 2.  En   el   siguiente   paso   se   seleccionan   los   paquetes   que   van   a   ser   descargados   e   instalados   y  finalmente se reinicia Eclipse.   posee   la   capacidad   de   realizar   desde   una   solicitud   sencilla   hasta   secuencias   de  peticiones   que   permiten   diagnosticar   el   comportamiento   de   una   aplicación   en   condiciones   de  producción.   programas   en   Perl. ir a Help – Install New  Software – Add.org/JMeter  .   hoy   en   día.  Inicialmente   diseñada   para   pruebas   de   estrés   en   aplicaciones   web.  descomprimir el fichero y ejecutar el archivo JMeter situado en la carpeta bin.   su  arquitectura ha evolucionado no sólo para llevar acabo pruebas en componentes habilitados en  Internet   (HTTP).6.   sino   además   en   Bases   de   datos.  En nuestro caso utilizaremos esta aplicación para simular el tráfico que genera un visor de mapas  hacia el servidor en las peticiones de información y para interpretar las respuestas que produzca  este.­ JMETER JMeter  es una herramienta de carga para llevar acabo simulaciones sobre cualquier recurso de  Software. o de cualquier otro cliente.org/  para   Maven).org/update_1.x  para   SVN   y  http://m2eclipse.codehaus.4. la mas  reciente   hasta   el   momento   de   la   realización   del   proyecto)  http://jakarta. Además.   ya   sean   en   forma   de   imágenes   (resultado   deseado)   o   en   forma   de   mensajes   de   error  debidos a cualquier causa.3.   En este sentido. simula todas las funcionalidades de un Navegador. 1.tigris. La   instalación   nuevamente   resulta   extremadamente   sencilla.2.apache. Y especificar la dirección de cada uno de los recurso que se desean solicitar  (http://subclipse.

Para   comprobar   la   correcta   instalación   y   activación   bastará   con   acceder   a   través   de  http://localhost:8080/geoserver.org)  y  descomprimirlos. y esta desarrollado testado y mantenido  por   diversos   grupos   y   organizaciones   de   todo   el   mundo.org/display/GEOS/Stable)..3. 1. De modo que la instalación quedará como sigue: $ sudo easy_install TileCache .  Una vez hecho esto. bastará  con instalar el archivo de configuración de TileCache.1. descomprimir en la  ubicación deseada y arrancarlo mediante el ejecutable startup. De este modo  sólo tendremos que escribir: type easy_install TileCache.­ GEOSERVER GeoServer es un software de código abierto escrito en java que permite a los usuarios compartir y  editar datos geoespaciales. Para realizar  esta acción bastara con hacer uso de la herramienta llamada TileCache_install_config.  aunque  en  ocasiones   si  se  desea  una  instalación  mas  rápida y completa. Se trata de un proyecto dirigido de manera comunitaria.   Geoserver   es   la   implementación   de  referencia de los estándares WFS (Web Feature Service) y WCS (Web Coverage Service) del  Open Geospatial Consortium (OGC).. publica datos de cualquier fuente de  datos espaciales que utilice estándares abiertos.py que se  habrá instalado por defecto.sh situado dentro de la carpeta bin.2. Diseñado para ser interoperable.2. Installed 8 . es posible usar el Python Package Index (pypi o Cheeseshop).4.tilecache..­ TILECACHE Para su instalación debemos descargar los archivos binarios desde la pagina web del proyecto  (www.  En nuestro caso este servidor ha sido  desplegado en en la carpeta local  dado que no ha de  funcionar como servidor de mapas fuera de este ámbito. así como del sistema WMS utilizado en este proyecto Para la instalación basta con descargarse la última versión disponible desde la página web oficial  para nuestra distribución Ubuntu (http://geoserver.

 indicando la url de procedencia. Al momento de la realización del proyecto. lo que implica que ante una petición de  una tesela concreta.5.egg/TileCache/tilecache.   Esta   opción   falsearía   los   resultados   obtenidos   dado   que   en   nuestro   protocolo   de  pruebas  no  es  necesario   que   las  teselas   demandadas   al  servidor   sean  contiguas.py Successfully copied file /usr/lib/python2.10-py2.cfg to /etc/tilecache.cfg. tilecache efectuara una petición de AxB teselas alrededor de la deseada con  el objetivo de dinamizar las búsquedas para el usuario final cargando las teselas contiguas a la  consultada. el tipo y el formato del archivo de salida. incluyéndolas en el archivo Tilecache.   Para   desactivar   esta  funcionalidad  basta con editar el archivo de configuración Tilecache. Tilecache implementa por defecto opciones de metatiling. TileCache está también disponible como un paquete Debian directamente desde el homepage del  proyecto. las teselas cacheadas serán almacenadas en la carpeta /tmp/tilecache.cfg y establecer  la opción  metatile a 1x1 9 . bastará con cargar las capas que van a ser utilizadas a los largo  del proyecto. el nombre  de la capa.5.10py2. En el siguiente ejemplo se carga una capa  contenida en el servidor local geoserver. [topp:hidrografia] type=WMS url=http://localhost:8080/geoserver/wms extension=png En nuestro caso./usr/lib/python2.egg $ sudo tilecache_install_config.5/site-packages/TileCache-2.cfg. Una vez realizada la instalación. por lo  que será  esta carpeta la que es necesario vaciar para limpiar la cache a la hora de realizar las  pruebas. existen paquetes para distribución Feisty o  Gutsy.5/site-packages/TileCache-2.   por   lo   que  aumentaría   de   manera   innecesaria   el   tráfico   y   por   tanto   la   eficiencia.

 en nuestro caso tomcat.es/wms/CARTOCIUDAD/CARTOCIUDAD</string > </wmsUrl> <wmsLayers>DivisionTerritorial</wmsLayers> </wmsLayer> Al igual que sucedió  con tilecache.2.   Tomcat   tiene   una   funcionalidad   que   permite   desplegar   de   manera   muy   simple  archivos . proporcionándole solamente la ubicación del archivo.xml. seleccionamos  la   pestaña   Tomcat   Manager   y   tras   introducir   loggin   y   password   accedemos   al   gestor   de   las  aplicaciones. será  necesario deshabilitar la opción de metatiling.war desarrollado para contenedores de  aplicaciones.cartociudad.1. Una vez desplegado el archivo sólo resta configurarlo para obtener los resultados que buscamos  para nuestro proyecto.  pero en nuestro caso hemos optado por  instalar otra de manera independiente al servidor. Será  necesario cargar la capa sobre la que vamos a trabajar editando el  archivo geowebcache. En este punto ya podemos probar si hemos instalado y configurado correctamente la aplicación  accediendo a través del mánager de tomcat. A continuación iniciamos el apache tomcat.­ GEOWEBCACHE Geoserver ya incluye una versión  de GeowebCache. accediendo a la opción Dinamically generated list of  layers y seleccionando la capa cartociudad.war.xml introduciendo una capa mas: </wmsLayer> <wmsLayer> <name>cartociudad</name> <wmsUrl> <string>http://www.   modificando   la   opción  metatiling a 1x1.5. Para la instalación bastará  con descargarnos el archivo . En este  caso   el   archivo   que   es   necesario   editar   es   geowebcache­servlet. 10 .

 en nuestro caso Tomcat.6. Dado que por defecto ya está  configurada la capa de  cartociudad no será necesario añadirla como en los casos anteriores.   con   las   tres  tecnologías   obteniendo   las   teselas   de   un   mismo   servidor   en   paralelo   y   con   la   aplicación   que  generaremos realizando las peticiones http: 11 .   por   lo   que   para   su   instalación   sólo   será   necesario   descargarse   los   archivos   correspondientes   y   desplegarlos   en   un   contenedor   de  aplicaciones java.­ WMSCWRAPPER Al   igual   que   Geowebcache   esta   construido   en   java.2.2. 1.7.­ RESUMEN La   idea   global   del   montaje   final   del   proyecto   quedaría   como   indica   la   imagen.1. Podemos comprobar si hemos realizado correctamente la instalación accediendo a la aplicación a  través del tomcat manager y probando las distintas funcionalidades disponibles.

APÉNDICE II MANUAL DE USO DE LA APLICACIÓN .

jar   puede   colocarse   indistintamente   en   cualquier   ubicación  dado que en su interfaz puede indicarsele la ruta exacta donde crear el archivo . En el script bench_start. pudiéndose establecer las conexiones entre todos ellos mediante  sus respectivos modos de configuración. Dentro de estos scripts.sh también se ha de indicar la ruta hasta JMeterReports. De todos modos aquí  se va a detallar como han sido  dispuestos en nuestro caso.   En  nuestro   caso  y  dada  la  instalaci ón   y  configuración de ellas que se hizo en el Apéndice I estas corresponden a /tmp/tiilecache  para   tilecache. También  se indicará  en este archivo las direcciones a través de las cuales accedemos a cada una  de   las   tres   implementaciones   (en   nuestro   caso   /tilecache/tilecache.   /tmp/cache   para   WMSCwrapper   y   /usr/local/apache­ tomcat/temp/geowebcache en el caso de Geowebcache. ● ● El   ejecutable   JMeterReports.2.jar así   como   la   ruta   hasta   los   archivos   .   Una   vez   en   este   punto   podemos  proceder   a   colocar   las   distintas   aplicaciones   y   archivos   que   vamos   a   necesitar   de   manera  adecuada.   con   el   fin   de   poder  eliminarlos antes de realizar otra. ● 1 .­  INSTALACIÓN Para su instalación en cualquier máquina.sh también habrá que indicar la ruta hasta el ejecutable de Jmeter y  hasta el archivo que hemos generado (apartado 4.   éstos   pueden   ser   colocados   casi   en   cualquier  ubicación dentro del disco duro. Dada   la   flexibilidad   de   todos   los   componentes.py  /geowebcache/service/wms   /WMS_C_wrapper/wms   para   TileCache.csv con los  distintos Bboxes.jar   ha   sido   colocado   directamente   dentro   de   la   carpeta  principal de instalación. En esa misma carpeta se incluyen los tres scripts. será necesario  especificar   las   rutas   tanto  a   JmeterReports. es preciso contar con todos los componentes que se  detallan   en   el   Apéndice   I   configurados   de   forma   correcta.csv   generados   en   cada   prueba. El   ejecutable   Bboxgenerator.1) para realizar las peticiones.   GeowebCache   y  WMSCwrapper respectivamente). En el script benchmark.1.jar   como   a   las   distintas   ubicaciones   de   las  distintas caches  que  van  a   ser  utilizadas.

 Como ya se dijo con anterioridad. aunque su gran flexibilidad le permite  adaptarse a otras formas de actuación: 1.jar la dirección donde se almacenan los distintos archivos .properties  dentro  del  archivador  JMeterReports. En   nuestro   caso   esta   tarea   se   puede   efectuar   en   tres   simples   ordenes   en   linea   de  comandos: $ sudo /etc/init.properties que se adjunta con BboxGeneratos. y se puede resumir en 3 pasos. si se desea hacer uso de la opción que implementa BboxGenerator. Será  necesario arrancar tanto el servidor apache y el apache tomcat como el servidor de  mapas geoserver.5/bin/startup.7.jar y elegimos las opciones que se desean. será  imprescindible haber configurado anteriormente el acceso a la misma. si se desea utilizar la opción  BBDD para obtener los datos directamente desde la base de datos de cartociudad.­  UTILIZACIÓN El uso es bastante sencillo.csv con los datos  de cada prueba y donde se desea colocar los archivos de salida. De manera adicional. pudiendo visualizar  la   zona   sobre   la   que   queremos   trabajar   con   la   opción   BUILD.sh   para el tomcat $ sudo /usr/local/geoserver­1.   Una   vez   elegidos   los  parámetros.   seleccionamos   un   nombre   y   una   ubicación   para   el   archivo   resultante   y  pulsamos el botón de OK. mediante el archivo  config.d/apache2 start       para arrancar el servidor apache2 $ sudo /usr/local/apache­tomcat­6.  será   necesario  indicar   en  el  archivo  config. 2.jar para  obtener los distintos Bboxes a partir de una base de datos.0.● Finalmente. 2 .jar en la sección resources.sh   para  geoserver 2. habrá que indicarle también dónde se  encuentra la base de datos y el usuario y password para poder acceder a ella.20/bin/startup. Ejecutamos BboxGenerator.

 ya  sólo resta ejecutar el script Bench_start.   tendremos   un   archivo   results.sh con las opciones que se deseen.xls   con   una   visualización  gráfica de los resultados y otro archivo store. La ubicación de estos archivos dependerá  de lo que le hayamos indicado a  cada uno de los archivos de configuración. Una   vez   realizados   estos   tres   pasos. 3 . Una vez generado el archivo con los datos de los Bboxes que vamos a pedir al servidor. La dos opciones configuradas  en nuestro caso han sido la opción de indicarle el número de threads en cada iteración y la  posibilidad   en   el   momento   que   se   desee   de   vaciar   las   caches   mediante   el   comando  cleancache. Cabe recordar  en   este   punto   que   es   preciso   tener   bien   configurado   las   distintas   rutas   dentro   de   los  archivos de configuración para evitar errores no deseados.3.xls con todos los resultados obtenidos en cada una  de las iteraciones.

En primer lugar estos son los distinto parámetros que hemos colocado en los distintos archivos de  configuración: ● BboxGenerator.­  EJEMPLO Como complemento a la explicación anterior.properties tenemos lo siguiente: #template template = /template.jar: es su archiv config.properties tenemos lo siguiente: #user user=postgres #password password=navarrete #connectstring connectstring=jdbc:postgresql:test #driver driver=org. vamos a concretar los pasos que hemos dado y el  modo en que tenemos configurados nuestro archivos en un ejemplo.xls #outfilename outfilename = /home/pablo/proyecto/resultados/results.xls #path csv files csvpath = /home/pablo/proyecto/resultados/files/ 4 .postgresql.jar : en su archivo config.Driver #BBDDName bbddname=cartociudad #outfilepath outfilepath=/home/pablo/proyecto/resultados/bboxes/ ● JmeterReports.3.

jar  Una vez que tenemos esto configurado.sh tenemos lo siguiente en el inicio del archivo: JMETER="/home/pablo/proyecto/jakarta­jmeter­2. bastará con escribir: JMeterReportspath=/home/pablo/proyecto/resultados/app/JMeterReports.20/temp/geowebcache/cartociudad"  CACHE_WMSCWRAPPER="/tmp/cache/cartociudad/"  CSV_FILE="/home/pablo/proyecto/resultados/bboxes/bboxes.sh"  JTL2CSV="/home/pablo/proyecto/resultados/files/jtl2csv.#store file path storepath = /home/pablo/proyecto/resultados/files/store.3.py"  JMX_FILE="/home/pablo/proyecto/resultados/files/Non­GUI­Test.py"  PATH_GEOWEBCACHE="/geowebcache/service/wms"  PATH_WMSCWRAPPER="/WMS_C_wrapper/wms"  CACHE_TILECACHE="/tmp/tilecache/"  CACHE_GEOWEBCACHE="/usr/local/apache­ tomcat­6.4/bin/jmeter.jmx"  PATH_TILECACHE="/tilecache/tilecache.jar  Seleccionamos las opciones que indica la imagen y pulsamos BUILD ● 5 .jar: $ java ­jar /home/pablo/proyecto/resultados/app/BboxGenerator.0. abrimos un terminal y ejecutamos BboxGenerator.sh.csv" Y en el script Bench_start.xls ● En el script benchmark.

1: interfar gráfica del generador de BBoxes El area de la petición.Imagen A2.2: Representación visual de la zona de trabajo 6 . dibujado en un mapa será el siguiente: Imagen A2.

 2 y 3.sh con las opciones cleancache. Los resultados al final de la ejecución... visualizados en el mismo terminal serán los siguientes: pablo@laptop:~/proyecto/resultados$ /home/pablo/proyecto/resultados/bench_start. Ahora ejecutamos en un terminal la siguiente orden: $ /home/pablo/proyecto/resultados/bench_start.   luego   vacia   las  caches   de   nuevo.sh   para   thread=1. lo que implica que el 50% de las peticiones  estará cacheadas a la hora de ser emitidas.  o  lo   que   es   lo   mismo.sh cleancache 1 cleancache  2 3  ­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+  Deleting csv files. 1. cleancache. Si todo es correcto nos saldrá el siguiente mensaje: Imagen A2.csv ubicado en la carpeta /home/pablo/proyecto/resultados/bboxes/.A continuación cerramos el mapa pulsando OK y pulsamos de nuevo OK en la ventana de las  opciones.sh para thread=3. con el nombre bboxes.   ejecuta   benchmark.sh   para   thread=2   y   finalmente   ejecuta   de   nuevo  benchmark. en  el cual cada bbox tiene un 100% de repetirse una vez.3: Mensaje de información Con estos datos habremos creado un archivo con diez Bboxes de una resolución entre 5 y 10 cada  una.sh cleancache 1 cleancache 2 3 Esta orden ejecuta el script bench_start.   ejecuta   benchmark.   limpia   las   caches.  ­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+  7 .

..4/s Avg:   222 Min:     2 Max:   610 Err:     0 (0..7/s Avg:   209 Min:     2 Max:   552 Err:     0 (0..0s =    4.00%)  Results Summary +     5 in   1. ***  will remove 0 tiles in the cache  \n\n*** Removing WMSCWrapper's cache.  ­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+  *********************************  *     Benchmarking TileCache    *  *********************************  :> 0 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test.6s =    3.8s =    3.6s =    1.00%)  Results Summary +     9 in   2.  \n\n*** Removing GeoWebCache's cache.jmx  Starting the test @ Thu Nov 26 12:23:58 CET 2009 (1259234638015)  Waiting for possible shutdown message on port 4445  Results Summary +     5 in   1.00%)  8 .8s =    2.jmx  Starting the test @ Thu Nov 26 12:24:02 CET 2009 (1259234642565)  Waiting for possible shutdown message on port 4445  Results Summary +     1 in   0.. ***  will remove 64 tiles in the cache  Cache entries found: 64  Removed 64 files.\n\n*** Removing TileCache's cache..00%)  Tidying up ..7/s Avg:   590 Min:   590 Max:   590 Err:     0 (0..00%)  Results Summary =    10 in   2.5/s Avg:   277 Min:     2 Max:   670 Err:     0 (0... end of run  :> 5 tiles in the cache after execution  *********************************  *     Benchmarking GeoWebCache  *  *********************************  :> 0 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test.00%)  Results Summary =    10 in   2. ***  will remove 0 tiles in the cache  number of command line argument are 1  ­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+  1 users running simultaneously.8/s Avg:   346 Min:     4 Max:   670 Err:     0 (0.    @ Thu Nov 26 12:24:01 CET 2009 (1259234641170)  .1s =    4.8/s Avg:   258 Min:     2 Max:   610 Err:     0 (0.

 ***  will remove 5 tiles in the cache  number of command line argument are 1  ­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+  2 users running simultaneously... ***  will remove 5 tiles in the cache  \n\n*** Removing WMSCWrapper's cache..  \n\n*** Removing GeoWebCache's cache...00%)  Tidying up .7/s Avg:   616 Min:     2 Max:  3764 Err:     0 (0.0/s Avg:   136 Min:     2 Max:   383 Err:     0 (0......8s =    2.Tidying up ..jmx  Starting the test @ Thu Nov 26 12:24:06 CET 2009 (1259234646950)  Waiting for possible shutdown message on port 4445  Results Summary =    10 in   1.jmx  Starting the test @ Thu Nov 26 12:24:11 CET 2009 (1259234651076)  Waiting for possible shutdown message on port 4445  Results Summary =    10 in   3. end of run  :> 5 tiles in the cache after execution  \n\n*** Removing TileCache's cache.    @ Thu Nov 26 12:24:08 CET 2009 (1259234648709)  ...    @ Thu Nov 26 12:24:05 CET 2009 (1259234645511)  ..  ­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+  *********************************  *     Benchmarking TileCache    *  *********************************  :> 0 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test.00%)  Tidying up . ***  will remove 5 tiles in the cache  Cache entries found: 5  Removed 5 files.4s =    7..    @ Thu Nov 26 12:24:15 CET 2009 (1259234655158)  9 .. end of run  :> 5 tiles in the cache after execution  *********************************  *   Benchmarking WMS_C_Wrapper  *  *********************************  :> 0 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test.

.. end of run  :> 5 tiles in the cache after execution  *********************************  *   Benchmarking WMS_C_Wrapper  *  *********************************  :> 0 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test. end of run  :> 5 tiles in the cache after execution  *********************************  *     Benchmarking GeoWebCache  *  *********************************  :> 0 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test..  ­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+  *********************************  *     Benchmarking TileCache    *  *********************************  10 . end of run  :> 5 tiles in the cache after execution  number of command line argument are 1  ­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+­+  3 users running simultaneously....00%)  Tidying up ..2s =    8.    @ Thu Nov 26 12:24:21 CET 2009 (1259234661491)  .00%)  Tidying up .6s =    6..jmx  Starting the test @ Thu Nov 26 12:24:16 CET 2009 (1259234656609)  Waiting for possible shutdown message on port 4445  Results Summary =    10 in   1..3/s Avg:   300 Min:     3 Max:   513 Err:     0 (0.1/s Avg:   239 Min:   172 Max:   383 Err:     0 (0..    @ Thu Nov 26 12:24:18 CET 2009 (1259234658154)  ..jmx  Starting the test @ Thu Nov 26 12:24:19 CET 2009 (1259234659544)  Waiting for possible shutdown message on port 4445  Results Summary =    10 in   1.

.jmx  Starting the test @ Thu Nov 26 12:24:23 CET 2009 (1259234663847)  Waiting for possible shutdown message on port 4445  Results Summary =    10 in   0.00%)  Tidying up .    @ Thu Nov 26 12:24:24 CET 2009 (1259234664258)  .5/s Avg:    14 Min:     2 Max:    35 Err:     0 (0.jmx  Starting the test @ Thu Nov 26 12:24:27 CET 2009 (1259234667522)  Waiting for possible shutdown message on port 4445  Results Summary =    10 in   0..00%)  Tidying up .    @ Thu Nov 26 12:24:27 CET 2009 (1259234667920)  ..1s =   94.. end of run  :> 5 tiles in the cache after execution  *********************************  *     Benchmarking GeoWebCache  *  *********************************  :> 5 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test..jmx  Starting the test @ Thu Nov 26 12:24:25 CET 2009 (1259234665660)  Waiting for possible shutdown message on port 4445  Results Summary =    10 in   0.1s =  114.. end of run  :> 5 tiles in the cache after execution  *********************************  *   Benchmarking WMS_C_Wrapper  *  *********************************   :> 5 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test.. end of run  :> 5 tiles in the cache after execution  Finalmente se nos mostrará una tabla con el resumen de todo los datos como la que sigue: 11 ..9/s Avg:    18 Min:     3 Max:    46 Err:     0 (0.:> 5 tiles in the cache before execution  Created the tree successfully using /home/pablo/proyecto/resultados/files/Non­GUI­Test...1s =  120.3/s Avg:    23 Min:     2 Max:    73 Err:     0 (0.00%)  Tidying up .    @ Thu Nov 26 12:24:26 CET 2009 (1259234666060)  ...

79794910748196     |3.5161744022503516 |  |2.656748140276302   |  |3.csv como fuente de Bboxes.3            |6.0               |136.33962264150944  |   _______________________________________________________________________________________________ En   la   ubicación   indicada. 12 .94252873563218|94.7           |277.   se   encuentra   el  archivo   results.   y   en   la   carpeta  /home/pablo/proyecto/resultados/files/   encontramos   store.48192771084338|114.333122229259025 |8.xls  con todos los datos de cada iteración (en este caso esos datos son coincidentes dado que no  hemos realizado ninguna ejecución con un numero de hilos repetida).8               |18. _______________________________________________________________________________________________ |                                                          Results Summary                                                                                                       |   _______________________________________________________________________________________________ |                  |                        AVG_TIME                        |                        AVG_RATE                        |   _______________________________________________________________________________________________ |Threads           |WMS­C­Wrapper     |GeoWebCache       |TileCache         |WMS­C­Wrapper     |GeoWebCache       | TileCache         |   _______________________________________________________________________________________________ |1.027406886858749 |3.0              |120.6             |7. Si ahora se desease otra ejecución con el mismo archivo bboxes.8           |616.8             |239.2             |23.  habría que tener en cuenta que los datos de la anterior prueba van a ser eliminados y sustituidos  por los de la siguiente.0               |300.   en   nuestro   caso   /home/pablo/proyecto/resultados/.8             |258.123476848090982  |2.0               |13.xls.

ANEXOS .

wmsc.crsMaxX = crsMaxX.crsMinY = crsMinY. double crsMinY.benchmarking.java package org.­ Client. double crsMaxX. this. } } 1.benchmarking.crsMaxY = crsMaxY.1.wmsc.­ BBOXGENERATOR 1. private double crsMaxY. this. } 1 . } public void setCrsMinX(double crsMinX) { this. private double crsMinY. GraphInterface gi = new GraphInterface(ts).2. this. public BBox(double crsMinX.setVisible(true).crsMinX = crsMinX.uva. double crsMaxY) { this.java package org.uva. } public double getCrsMinX() { return crsMinX. public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub TileScheme ts = new TileScheme(). gi. private double crsMaxX. public class BBox { private double crsMinX.crsMinX = crsMinX.­ Bbox.1.

crsMaxX = crsMaxX. private int numberofbbox. } } 1. private double tileMatrixMaxYr. private double tileMatrixMinXr. private int prob1.crsMaxY = crsMaxY.benchmarking. private double tileMatrixMinY.public double getCrsMinY() { return crsMinY. private int prob3. private double tileMatrixMaxX.java package org.3.wmsc. private int prob2. 2 .uva. } public void setCrsMinY(double crsMinY) { this. private int prob4. private double tileMatrixMinYr.crsMinY = crsMinY. } public void setCrsMaxX(double crsMaxX) { this. } public double getCrsMaxY() { return crsMaxY. private double tileMatrixMaxY. private double tileMatrixMaxXr. private int counter. private int maxresolution. private int minresolution. public class TileScheme { // Maximal extent private static TileScheme ts. } public double getCrsMaxX() { return crsMaxX. private double tileMatrixMinX. } public void setCrsMaxY(double crsMaxY) { this.­ TileScheme.

int colmax = -(int) ((maxX / tileSpanX) + 0. if (maxX < -180) { maxX = -180. 0. 0.00002145767211914060. 0. if (maxX >= 0) { int colmax = (int) (maxX / tileSpanX). 0. 0.99999). double minXr. } } if (maxY >= 0) { int rowmax = (int) (maxY / tileSpanY).getHeight(). 0. double maxXr. // tile height double resmat[] = { 0. 0.getTileMatrixMaxX(). 0.17578125000000000000. int resolution = ts. double maxY = ts. 0. 0. // tile width private int height = 256. private int width = 256.getTileMatrixMinX().08789062500000000000. 0. 0. double tileSpanY = ts.00034332275390625000.getWidth().resmat[resolution] * ts.01098632812500000000. double minX = ts. } } else { maxX = -maxX.00000536441802978516.00008583068847656250. 0.00068664550781250000. public void Test() { // // Test and correct bbox // TileScheme ts = TileScheme.resmat[resolution] * ts.getMinresolution().04394531250000000000.getTs().00000134110450744629 }. 0.getTileMatrixMaxY(). double tileSpanX = ts.00000268220901489258. 0.00137329101562500000. maxX = colmax * tileSpanX. 0. if (maxX > 180) { maxX = 180.00549316406250000000.35156250000000000000. double maxX = ts.private String csvfilename. double maxYr.00004291534423828120. 0.02197265625000000000.getTileMatrixMinY().00001072883605957030.00274658203125000000. 0.70312500000000000000. 3 . double minY = ts. double minYr. 0.00017166137695312500. maxX = colmax * tileSpanX. private String numberofbboxstr.

int rowmax = -(int) ((maxY / tileSpanY) + 0. minX = colmin * tileSpanX.maxY = rowmax * tileSpanY. minX = colmin * tileSpanX. if (minX < -180) { minX = -180. if (maxY < -90) { maxY = -90. minY = -90.99999). } } else { minX = -minX. int rowmin = -(int) ((minY / tileSpanY)). int colmin = -(int) ((minX / tileSpanX)). if (minX > 180) { minX = 180. maxY = rowmax * tileSpanY. } if ((maxX > minX && maxY > minY)) { maxXr = maxX. 4 . } } if (minY >= 0) { int rowmin = (int) ((minY / tileSpanY) + 0. } } if (minX >= 0) { int colmin = (int) ((minX / tileSpanX) + 0.99999). if (minY < -90) { minY = -90. if (minY > 90) { minY = 90. minY = rowmin * tileSpanY. } } else { minY = -minY. } } else { maxY = -maxY. } } if ((maxY >= 90 && minY <= -90 && resolution == 0)) { maxY = 90. minY = rowmin * tileSpanY. if (maxY > 90) { maxY = 90.99999).

maxYr = maxY; minXr = minX; minYr = minY; } else { maxXr = 180; maxYr = 90; minXr = -180; minYr = -90; GraphInterface.Warning(); } ts.setTileMatrixMaxXr(maxXr); ts.setTileMatrixMinXr(minXr); ts.setTileMatrixMaxYr(maxYr); ts.setTileMatrixMinYr(minYr); TileScheme.setTs(ts); } public double getTileMatrixMaxX() { return tileMatrixMaxX; } public void setTileMatrixMaxX(double TileMatrixMaxX) { tileMatrixMaxX = TileMatrixMaxX; } public double getTileMatrixMinX() { return tileMatrixMinX; } public void setTileMatrixMinX(double TileMatrixMinX) { tileMatrixMinX = TileMatrixMinX; } public double getTileMatrixMaxY() { return tileMatrixMaxY; } public void setTileMatrixMaxY(double TileMatrixMaxY) { tileMatrixMaxY = TileMatrixMaxY; } public double getTileMatrixMinY() { return tileMatrixMinY; } public void setTileMatrixMinY(double TileMatrixMinY) { tileMatrixMinY = TileMatrixMinY; }

5

public double getTileMatrixMaxXr() { return tileMatrixMaxXr; } public void setTileMatrixMaxXr(double TileMatrixMaxXr) { tileMatrixMaxXr = TileMatrixMaxXr; } public double getTileMatrixMinXr() { return tileMatrixMinXr; } public void setTileMatrixMinXr(double TileMatrixMinXr) { tileMatrixMinXr = TileMatrixMinXr; } public double getTileMatrixMaxYr() { return tileMatrixMaxYr; } public void setTileMatrixMaxYr(double TileMatrixMaxYr) { tileMatrixMaxYr = TileMatrixMaxYr; } public double getTileMatrixMinYr() { return tileMatrixMinYr; } public void setTileMatrixMinYr(double TileMatrixMinYr) { tileMatrixMinYr = TileMatrixMinYr; } public int getNumberofbbox() { return numberofbbox; } public void setNumberofbbox(int Numberofbbox) { numberofbbox = Numberofbbox; } public int getProb1() { return prob1; } public void setProb1(int Prob1) { prob1 = Prob1; } public int getProb2() {

6

return prob2; } public void setProb2(int Prob2) { prob2 = Prob2; } public int getProb3() { return prob3; } public void setProb3(int Prob3) { prob3 = Prob3; } public int getProb4() { return prob4; } public void setProb4(int Prob4) { prob4 = Prob4; } public int getMinresolution() { return minresolution; } public void setMinresolution(int Minresolution) { minresolution = Minresolution; } public int getMaxresolution() { return maxresolution; } public void setMaxresolution(int Maxresolution) { maxresolution = Maxresolution; } public int getCounter() { return counter; } public void setCounter(int Counter) { counter = Counter; } public String getCsvfilename() { return csvfilename; }

7

} public void setWidth(int Width) { width = Width.properties". } public void setHeight(int Height) { height = Height.ts = ts. } public int getHeight() { return height.public void setCsvfilename(String Csvfilename) { csvfilename = Csvfilename.uva.4.util.­ Configuration.java package org. 8 .Properties. } public void setNumberofbboxstr(String Numberofbboxstr) { numberofbboxstr = Numberofbboxstr. } public String getNumberofbboxstr() { return numberofbboxstr. import java. } public int getWidth() { return width. } public static void setTs(TileScheme ts) { TileScheme.benchmarking. } } 1.wmsc. } public static TileScheme getTs() { return ts. public class Configuration { private static final String CONFIGURATION_FILE = "/config. private static Properties properties.

} return user.class . outfilepath = properties.getProperty("connectstring"). properties. } return connectstring.load(Configuration.getProperty("bbddname").getMessage()).private static String driver. } catch (Exception e) { System. password = properties. } 9 . private static String password.getProperty("user").getProperty("password"). private static void init() { try { properties = new Properties(). } public static String getUser() { if (user == null) { init().out. bbddname = properties. } } public static String getDriver() { if (driver == null) { init(). } return driver.getResourceAsStream(CONFIGURATION_FILE)). private static String outfilepath.println(e. private static String bbddname. connectstring = properties. private static String user.getProperty("outfilepath"). driver = properties.getProperty("driver"). } public static String getConnectString() { if (connectstring == null) { init(). user = properties. } public static String getPassword() { if (password == null) { init(). private static String connectstring.

java package org. private static WMSCBBddBBoxGenerator wmscbbddbboxgenerator = new WMSCBBddBBoxGenerator( TileScheme.JButton.getTs()). import java.swing. import javax.swing.wmsc. import javax. initComponents().AbstractButton.swing.SwingConstants.benchmarking. } return bbddname.ImageIcon. import javax.IOException.­ GraphInterface.Font.swing. } public static String getBbddName() { if (bbddname == null) { init().setTs(ts).JLabel.JFrame { TileScheme ts = new TileScheme().JFrame. import javax. private static WMSCRandomBBoxGenerator wmscrandombboxgenerator = new WMSCRandomBBoxGenerator( TileScheme. } public static String getOutFilePath() { if (outfilepath == null) { init(). public class GraphInterface extends javax. import java. import javax. } private void initComponents() {} 10 .getTs()).5.swing. import javax. private static final long serialVersionUID = 1L.return password. } return outfilepath. } } 1.swing.awt.swing.io.uva. public GraphInterface(TileScheme ts) { TileScheme.

} ConfirmWindow().parseInt(jTextField28. if (jTextField20.getText().trim()) .parseInt(jTextField32.setNumberofbboxstr(jTextField33.Test().setMaxresolution(Integer. try { wmscrandombboxgenerator.getText().setProb4(Integer.trim())).parseInt(jTextField29.getText()).setNumberofbboxstr(jTextField33.getText().awt.setCsvfilename(jTextField16. ts. ts.setProb2(Integer.setProb1(Integer.valueOf(jTextField22. } ConfirmWindow().event.private void jButton2ActionPerformed(java. ts. ts.trim())).getText().getText()).valueOf(jTextField20. } else { TileScheme. ts.csvwrite().getText(). ts.getText().parseInt(jTextField19. ts. } catch (IOException e) { e.valueOf(jTextField23.trim())).setTileMatrixMinX(Double.setTs(ts).getText(). } catch (IOException e) { e.getText().trim()) .setTileMatrixMinY(Double.parseInt(jTextField30.trim())).doubleValue()).getTs(). ts. } } 11 .printStackTrace(). TileScheme.doubleValue()). try { wmscbbddbboxgenerator.printStackTrace().setTs(ts).getText(). ts.getText().parseInt(jTextField33.getText().doubleValue()).setTileMatrixMaxX(Double.csvwrite().setTileMatrixMaxY(Double. ts.setNumberofbbox(Integer.trim())). ts.setMinresolution(Integer.trim())).trim()) . ts.trim())). ts.getText().valueOf(jTextField21.getText()).setProb3(Integer.parseInt(jTextField31. ts.doubleValue()).ActionEvent evt) { ts = TileScheme.trim()) .equals("bbdd") == false) { ts.

ts.valueOf(TileScheme.setTs(ts). ts.valueOf(jTextField21. jTextField25.ActionEvent evt) { System.awt.setTileMatrixMaxX(Double. } public static void main(String args[]) { java.setText("bbdd").getTs()).getTileMatrixMaxXr())).setTileMatrixMinX(Double.doubleValue()).awt.doubleValue()).awt.awt.event.event. } private void jButton8ActionPerformed(java. jTextField24.event.valueOf(TileScheme. jTextField21.valueOf(jTextField20. ts. jTextField27.getTs() .invokeLater(new Runnable() { public void run() { new GraphInterface(TileScheme.trim()) .getText().trim()) .trim()) .valueOf(jTextField22.setText("bbdd"). MapWindow().valueOf(TileScheme.getText().awt. jTextField23.valueOf(jTextField23.getTs() .exit(0).getText().setVisible(true).doubleValue()). } private void jMenuItem1ActionPerformed(java.getTs() .getTileMatrixMaxYr())).getTileMatrixMinYr())). ts.setText(String. TileScheme.ActionEvent evt) { System.getText().event. jTextField22.getTs().ActionEvent evt) { jTextField20.ActionEvent evt) { ts = TileScheme. ts.doubleValue()).valueOf(TileScheme.parseInt(jTextField19. } private void jButton9ActionPerformed(java.setText(String.Test(). 12 .getTileMatrixMinXr())).setText("bbdd"). ts. jTextField26.setTileMatrixMinY(Double.setTileMatrixMaxY(Double.exit(0).EventQueue.trim())).setText(String.private void jButton1ActionPerformed(java.getText().getTs() .setText(String.setText("bbdd").setMinresolution(Integer.trim()) .

swing. private javax.JTextField jTextField21. private javax. private javax. private java.swing. private java. private javax. } private javax.swing.JButton jButton2.awt.awt.swing. private java. private javax.JMenuItem jMenuItem1.JTextField jTextField31.JTextField jTextField27.JTextField jTextField19.awt. private javax. 200). private javax. private javax. 100. private javax.JMenu jMenu2. private javax.JButton jButton8.JTextField jTextField23. private java. private javax.JButton jButton1. private java.swing.JTextField jTextField33.swing.JTextField jTextField25.Label label21. nuevoFrame. private javax.awt.JButton jButton9.awt.swing.Label label23.awt. nuevoFrame.awt.Label label20.swing. private java. private javax.JTextField jTextField16.JTextField jTextField26.Label label25. nuevoFrame. private java. 13 .swing.awt.swing.Label label22.swing. private javax. 400.setVisible(true). private javax.swing.PopupMenu popupMenu1.Label label27.swing.JTextField jTextField22.swing.Label label28. private javax.pack().swing. private java. private java.JTextField jTextField24. private javax. private javax.swing. private javax.setBounds(300.swing.JMenuBar jMenuBar1.swing.swing.swing.swing.} }).JMenu jMenu1.JTextField jTextField20.awt.JTextField jTextField32.JTextField jTextField30. private java. private javax.Label label26. public static void Warning() { // // Error window (out of bounds) // final JFrame nuevoFrame = new JFrame().Label label24. private javax.JTextField jTextField29.JTextField jTextField28.swing.swing.swing. private javax. private javax.awt.

getTileMatrixMaxY(). Font. newFrame.CENTER). 50. 650). } }).setVerticalTextPosition(AbstractButton. 94. double MinX = ts.getTileMatrixMinXr(). double MaxXr = ts. nuevoFrame. 14 .getTileMatrixMaxX(). textLabel10. JButton12.PLAIN.add(JButton12).pack().setBounds(90.getTileMatrixMinY(). newFrame. double MinY = ts. nuevoFrame.setFont(new Font("error\n impossible borders".setLayout(null). final JFrame newFrame = new JFrame().setText("OK").getTileMatrixMaxXr(). double MinXr = ts. SwingConstants.event. JButton JButtonok = new JButton(). 1110. 16)). 29).BOTTOM). textLabel10.ActionEvent evt) { nuevoFrame.setHorizontalTextPosition(AbstractButton.getTs().awt. 29). double MaxY = ts.setBounds(150. 210. } public void MapWindow() { ts = TileScheme. JButton12. JButton12. JButton12.getTileMatrixMinYr(). 100. double MinYr = ts.add(textLabel10).setName("OKbutton").setVisible(false).addActionListener(new java. nuevoFrame.getContentPane().CENTER).event.awt.getContentPane().setBounds(100.JLabel textLabel10 = new JLabel("error impossible borders". JButton12.getTileMatrixMinX(). JButton12. 120. double MaxX = ts. JButton JButton12 = new JButton().ActionListener() { public void actionPerformed(java. double MaxYr = ts.getTileMatrixMaxYr().

(int) ((MaxY . 1.swing.MinXr) * 3) + 2. (int) ((MaxX .(int) MinY) * 3) + 10.(int) MinYr) * 3) + 10. JLabel map1lab = new javax. ((90 .add(JButtonok).JLabel(). 540). newFrame.JLabel(). (int) ((MaxYr . JLabel LabelMinY = new javax.setBounds((int) ((MaxXr + 180) * 3) + 10.setBounds((int) ((MaxX + 180) * 3) + 10. 4.JLabel().setBounds((((int) MinX + 180) * 3) + 6. 1.JLabel().MaxY) * 3 + 6. 580.swing.swing. (int) (90 .setBounds((((int) MinX + 180) * 3) + 6.MaxY) * 3 + 6. ImageIcon red = new ImageIcon().setBounds((((int) MinXr + 180) * 3) + 9.MinX) * 3) + 8.JLabel().JButtonok.setBounds((((int) MinX + 180) * 3) + 6. ImageIcon map0img = new ImageIcon().setHorizontalTextPosition(AbstractButton. LabelMaxXr. LabelMaxX.setVerticalTextPosition(AbstractButton.swing.CENTER).JLabel().setBounds(500. LabelMinXr.MinY) * 3) + 8). 100. JLabel LabelMaxX = new javax. 1).setText("OK"). 1). JButtonok. (int) (90 . LabelMinYr. 4).MaxY) * 3 + 6.getContentPane().setName("OKbutton"). JButtonok. (int) (90 . JLabel map0lab = new javax. (int) (90 .MinY) * 3) + 8). (int) ((MaxXr . (int) ((MaxXr .swing.JLabel().MinYr) * 3) + 2).setBounds(10.setBounds((((int) MinXr + 180) * 3) + 9. JLabel LabelMinXr = new javax.MinX) * 3) + 8.MinYr) * 3) + 2). 540). map0lab. (int) ((MaxX .JLabel(). ((90 .JLabel(). JButtonok.setBounds((((int) MinXr + 180) * 3) + 9.MaxYr) * 3 + 9. (int) ((MaxY .setBounds(550. 10.MinXr) * 3) + 2.setLayout(null). JButtonok.swing. 10. JLabel LabelMaxY = new javax. JLabel LabelMinX = new javax.MaxYr) * 3 + 9.MaxYr) * 3 + 9. newFrame. LabelMinX. 4.swing. (int) (90 . 30). JLabel LabelMinYr = new javax. LabelMaxY. ImageIcon black = new ImageIcon(). LabelMinY.JLabel().swing. JLabel LabelMaxYr = new javax. 540.swing. 540. (int) ((MaxYr . 4). LabelMaxYr. (int) (90 . 15 .BOTTOM). JLabel LabelMaxXr = new javax. map1lab.swing. ImageIcon map1img = new ImageIcon().

textLabel10. 29).event. newFrame.getContentPane().addActionListener(new java. 50. newFrame. map0img = new ImageIcon(GraphInterface.class .setIcon(black). LabelMaxY.event.setIcon(map1img). newFrame. newFrame.ActionListener() { public void actionPerformed(java.add(map0lab). map1img = new ImageIcon(GraphInterface.jpeg")).getContentPane().class.jpeg")).getContentPane().add(LabelMaxXr).add(LabelMinXr). LabelMaxXr. map0lab.getContentPane().setIcon(black).setBounds(135.getResource("/mundi1. nuevoFrame. LabelMaxX.jpeg")).getContentPane().add(LabelMinY). nuevoFrame.jpeg")). LabelMinXr.setBounds(300.setVisible(true).setIcon(black). newFrame.CENTER).awt. newFrame. 400. } }).add(LabelMaxYr).awt.setIcon(black).ActionEvent evt) { newFrame. LabelMaxYr.class .getContentPane().setVisible(true). LabelMinX.add(LabelMinYr). newFrame.add(map1lab). 200).add(LabelMaxX). } public static void ConfirmWindow() { final JFrame nuevoFrame = new JFrame().getResource("/red. LabelMinYr.getContentPane().getResource("/black.setIcon(red).setIcon(map0img). 124. LabelMinY.setVisible(false).class. map1lab.getContentPane(). if ((MaxX > MinX && MaxY > MinY)) { newFrame. black = new ImageIcon(GraphInterface. 16 .pack(). newFrame.setIcon(red).getContentPane(). newFrame. JLabel textLabel10 = new JLabel("file created". } JButtonok.getResource("/mundi0. newFrame.getContentPane().add(LabelMaxY).setIcon(red). 100.setIcon(red).add(LabelMinX).red = new ImageIcon(GraphInterface. nuevoFrame. SwingConstants.

event. 17 . 120. JButton12.benchmarking.BOTTOM).wmsc.ActionEvent evt) { nuevoFrame. JButton12.6.FileWriter.io. double MinX = ts.event.util.uva.getTileMatrixMaxXr().setText("OK"). } } 1.io.­ WMSCRandomBBoxGenerator.setLayout(null). nuevoFrame.setName("OKbutton").PLAIN.BufferedWriter. JButton JButton12 = new JButton(). JButton12. public class WMSCRandomBBoxGenerator { private TileScheme ts = null. JButton12.getContentPane().setBounds(150.ts = ts.add(JButton12).getContentPane().java package org. 94. JButton12. import java.textLabel10.IOException.setFont(new Font("File Created".awt. import java. 16)). public WMSCRandomBBoxGenerator(TileScheme ts) { this. } public BBox getRandomWMSCTileBBox() { double MaxX = ts. nuevoFrame.io.setHorizontalTextPosition(AbstractButton.awt.Random.setVerticalTextPosition(AbstractButton. nuevoFrame. JButton12. import java.add(textLabel10).getTileMatrixMinXr(). 29).addActionListener(new java. } }). Font.ActionListener() { public void actionPerformed(java.setVisible(false).CENTER). import java.

int tileCol = (int) Math. double diffMatrixY = MaxY . Random funcrand = new Random(). double BBox3 = (tileCol + 1) * tileSpanX + MinX.MinY.getTileMatrixMinYr(). int tileMaxCol = (int) Math.getMaxresolution().nextInt(100).round(diffMatrixX / (ts.resmat[funcrandint]. Random prob3rand = new Random().nextDouble().getTileMatrixMaxYr(). Random funcrand2 = new Random(). double tileSpanY = ts.getMinresolution(). 18 .minresolution + 1). BBox bbox = new BBox(BBox1.getWidth() * ts.getTs().(tileRow + 1) * tileSpanY.nextInt(100). int prob3randint = prob3rand. BBox4). BBox2. double BBox1 = tileCol * tileSpanX + MinX. int minresolution = ts. return (bbox). int maxresolution = ts.getHeight())).getHeight() * ts.floor(tileMaxCol * funcranddouble).getCsvfilename() + ". double tileSpanX = ts. Random prob2rand = new Random(). double BBox2 = MaxY . int funcrandint = minresolution + funcrand3.resmat[funcrandint] * ts.csv")).resmat[funcrandint] * ts. BBox3. Random funcrand3 = new Random(). Random prob1rand = new Random().tileRow * tileSpanY. double BBox4 = MaxY .nextInt(100). int tileMaxRow = (int) Math. double funcranddouble = funcrand.nextDouble().resmat[funcrandint]. double MinY = ts.getOutFilePath() + ts. } public void csvwrite() throws IOException { ts = TileScheme. BufferedWriter out = new BufferedWriter(new FileWriter(Configuration .double MaxY = ts. double diffMatrixX = MaxX .round(diffMatrixY / (ts.getWidth())). int tileRow = (int) Math. int prob2randint = prob2rand.nextInt(maxresolution .floor(tileMaxRow * funcranddouble2). double funcranddouble2 = funcrand2.MinX. BBox bbox = null. int prob1randint = prob1rand.

} } 19 . if (prob3randint < ts.) { bbox = getRandomWMSCTileBBox()." + bbox." + bbox.write(bbox.getCrsMaxX() + ".write(bbox.getCrsMinX() + ".getCrsMinY() + ".getCrsMaxY() + "\n"). if (prob4randint < ts.getProb3() & i < ts. for (int i = 0. i++.getNumberofbbox()." + bbox.getCrsMinX() + ". i++.write(bbox.nextInt(100).getCrsMinY() + ". if (prob2randint < ts.Random prob4rand = new Random(). i++.getCrsMaxX() + ".getCrsMaxX() + "." + bbox.getCrsMinX() + ".getCrsMaxX() + ".getNumberofbbox()) { out. i++.getCrsMaxY() + "\n").getCrsMinY() + ". if (prob1randint < ts.getCrsMaxY() + "\n").getProb1() & i < ts." + bbox.write(bbox.getProb2() & i < ts.getCrsMinX() + ".getProb4() & i < ts.write(bbox. i < ts." + bbox.getCrsMinY() + ".getCrsMaxY() + "\n")." + bbox.getCrsMaxY() + "\n").getNumberofbbox()) { out. } } } } } out." + bbox.close(). out.getCrsMinY() + ".getCrsMaxX() + "." + bbox.getNumberofbbox()) { out." + bbox." + bbox." + bbox. i++." + bbox." + bbox." + bbox.getCrsMinX() + ".getNumberofbbox()) { out. int prob4randint = prob4rand.

nextToken().Connection.sql.io.next()) { String bboxstr = rs. public class WMSCBBddBBoxGenerator { private TileScheme ts = null. import java. Configuration. 20 .sql.sql. String strb = stbbox. Configuration . Connection con = DriverManager.getDriver()). ". " ")."). String stra = stbbox. final StringTokenizer stCad = new StringTokenizer(bboxstr.IOException.createStatement().getNumberofbbox()].getBbddName() + " limit " + ts.StringTokenizer.nextToken(). } public BBox[] getBBddbboxes() { String[][] bbox = new String[10][ts.nextToken().getConnectString(). public WMSCBBddBBoxGenerator(TileScheme ts) { this. import java.­ WMSCBBddBBoxGenerator.forName(Configuration.java package org. ResultSet rs = stmt. BBox[] bboxes = new BBox[ts.1. import java.getNumberofbbox() + ""). while (stCad.getUser(). import java. bbox[j * 2][i] = stra.BufferedWriter. import java.uva.getNumberofbbox()]. Statement stmt = con.io.FileWriter.6.util.benchmarking.hasMoreTokens()) { final StringTokenizer stbbox = new StringTokenizer(stCad . while (rs. int i = 0.wmsc.getPassword()).ResultSet. try { Class. import java. import java.Statement. int j = 0.ts = ts.getConnection(Configuration . import java.getString(1).DriverManager.sql.io.executeQuery("SELECT asText(bbox) FROM " + Configuration.substring(9).

} out. j++.getCrsMinX() + ".out. } stmt." + bboxes[i].getTs().getCrsMaxY() + "\n"). con.println(e. Double . } public void csvwrite() throws IOException { ts = TileScheme." + bboxes[i].getCrsMaxX() + ".parseDouble(bbox[4][i]).length.parseDouble(bbox[1][i])).csv")).write(bboxes[i].close(). BufferedWriter out = new BufferedWriter(new FileWriter(Configuration . } } 21 .bbox[(j * 2) + 1][i] = strb. } return bboxes.close(). Double . for (int i = 0.getOutFilePath() + ts. } bboxes[i] = new BBox(Double." + bboxes[i]. i++.close().getCsvfilename() + ". i < bboxes. BBox[] bboxes = getBBddbboxes(). Double . } catch (Exception e) { System.parseDouble(bbox[3][i]). i++) { out.getMessage()).parseDouble(bbox[0][i]).getCrsMinY() + ".

// skip headers while ((str = in. public class Constants { public static String AVG_RATE = "AVG_RATE". import java.benchmarking. long sum = 0.readLine()) != null) { data_entry = str. j++."). public static final String AVG_TIME = "AVG_TIME". sum += Long.io.1. } } 2.java package es. String str = null.­ Constants.uva.idelab.BufferedReader.FileReader.uva. try { BufferedReader in = new BufferedReader(new FileReader(csvFile)). } public String getAvgTime(){ return AVG_TIME. public String getAvgRate(){ return AVG_RATE.io. str = in.2.2. } 22 .IOException. import java.java package es. double avg_time = 0.benchmarking.valueOf(data_entry[11]).idelab.readLine().­ JMeterReports 2. public class Stats { public static double getAvgTime(String csvFile) { String[] data_entry = null. int j = 0.longValue().io.split(". import java.­ Stats.

double avg_rate = 0.valueOf(data_entry[1]).longValue() + elapsed.valueOf(data_entry[0]). long end = 0. try { BufferedReader in = new BufferedReader(new FileReader(csvFile)).").longValue(). start_temp = Long. end_temp = Long. } if ((end_temp + elapsed) > end) { end = end_temp + elapsed. // skip header // labels str = in.longValue().longValue().split(".valueOf(data_entry[1]). long elapsed = 0. data_entry = str. long end_temp = 0.close().longValue().in.valueOf(data_entry[0]). return avg_time. elapsed = Long. data_entry = str. end = Long.valueOf(data_entry[0])."). str = in.split(". elapsed = Long.readLine(). } catch (IOException e) { } avg_time = (double) sum / j. while ((str = in. String str = null.readLine(). } } 23 . start = Long.longValue().readLine()) != null) { j++. long start_temp = 0. } public static double getAvgRate(String csvFile) { String[] data_entry = null. if (start_temp < start) { start = start_temp. int j = 1.valueOf(data_entry[0]). long start = 0.

apache.getMessage()). import java.close().properties". } } private void generateReport(String[] argthreads) throws IOException { 24 .3.io.Properties. private static double maxthread = 1.logging.generateReport(args).io. import java. import org. } catch (IOException e) { } avg_rate = (double) 1000 * (j) / (end .benchmarking.HSSFWorkbook.File.idelab.java package es.in.apache.util.hssf.poi.usermodel. import org. public class ReportGenerator { private static double numrow.uva.hssf.poi.println(e. try { rg.apache.poi. import java. import java. private static final String CONFIGURATION_FILE = "/config. import java.Logger.­ ReportGenerator. import java. return avg_rate.HSSFRow.Level.util.usermodel.start).IOException. } } 2.out.util.logging. private static double minthread = 1.FileInputStream.io.io. import java.FileOutputStream. } catch (IOException e) { System. import org.HSSFSheet. /** * @param args */ public static void main(String[] args) { ReportGenerator rg = new ReportGenerator().hssf.usermodel.

HSSFRow row = sheet.getSheetAt(1). row.createCell(4). try { Properties properties = new Properties().equals("store") == true) { String thread = argthreads[1].createRow(numrow). File outFile = new File(properties.getProperty("storepath")).getProperty("storepath")).getProperty("csvpath").createCell(3). row.createCell(0).properties")).class .setCellValue( Stats .createCell(5). int numrow = 0. row.createCell(6). 25 .csv")). properties.setCellValue(Double.getAvgRate(path + "geowebcache" + thread + ".getResourceAsStream("/config. row.createCell(2).parseDouble(thread)).csv")).getAvgRate(path + "wmscwrapper" + thread + ".setCellValue( Stats.setCellValue( Stats . row. FileInputStream store = new FileInputStream(properties .setCellValue( Stats .csv")).setCellValue( Stats .getAvgTime(path + "tilecache" + thread + ". HSSFSheet sheet = wb.getAvgTime(path + "geowebcache" + thread + ".load(ReportGenerator. HSSFWorkbook wb = new HSSFWorkbook(store).String summary = "".csv")).getAvgRate(path + "tilecache" + thread + ".setCellValue( Stats. if (argthreads[0].csv")). row.getRow(numrow) != null) { numrow++.createCell(1).getAvgTime(path + "wmscwrapper" + thread + ". row. FileOutputStream outputFile = new FileOutputStream(outFile). while (sheet. } String path = properties.csv")).

HSSFWorkbook databook = new HSSFWorkbook(storefile). HSSFWorkbook libro = new HSSFWorkbook(archivo).getResourceAsStream(CONFIGURATION_FILE)). double sumwmsrate = 0.getProperty("template")).equals("0") == true) { int numrows = 0. FileInputStream storefile = new FileInputStream(properties . try { Properties properties = new Properties(). double threads = 0.getProperty("storepath")).getSheetAt(1).write(outputFile). properties. HSSFSheet sheet = libro. double sumwmsctime = 0.wb.getRow(numrows) != null) { numrows++. int j = 0. 26 . HSSFRow[] rows = new HSSFRow[numrows]. } catch (Exception e) { } } if (argthreads[0]. HSSFRow[] rowsord = new HSSFRow[numrows]. while (datasheet.load(ReportGenerator. double threshold = 0. double sumgwcrate = 0. double sumtcrate = 0. } setNumRow(numrows). FileInputStream archivo = new FileInputStream(properties . HSSFSheet datasheet = databook. double sumgwctime = 0.class . double sumtctime = 0. outputFile.getSheet("hoja1").close(). double sumthreads = 0.

j++. for (int i = 0. } } int cont2 = 0. i++) { if (rows[i].getCell(1). i < numrows. rows).getCell(0). rows). sumwmsctime = rowsord[i].getNumericCellValue() <= getMinThread() && rows[i].getRow(i). i < getNumRow() . int cont1 = 1.getNumericCellValue() == getMaxThread()) { rowsord[j] = rows[i]. i++) { threads = rowsord[i]. while (getMinThread() < getMaxThread()) { for (int i = 2. setMinThread(getMinThread(). i++) { rows[i] = datasheet. 27 . } for (int i = 2.getCell(0).getNumericCellValue().getNumericCellValue() .threshold > 0) { rowsord[j] = rows[i]. i < numrows. setMinThread(0. } setMaxThread(rows).for (int i = 2. sumthreads = threads.getCell(0).2. j++. i < numrows. i++) { if (rows[i].getCell(0). } } threshold = getMinThread().getNumericCellValue().

setCellValue((sumgwctime / cont1)).getNumericCellValue().getCell(4).getCell(5).getNumericCellValue(). cont1 = 1.setCellValue((sumwmsrate / cont1)).getCell(6). k < getNumRow() . cont1++. sumtctime += rowsord[k]. Row. sumwmsrate = rowsord[i]. Row.createCell(0).getNumericCellValue(). sumtcrate += rowsord[k].getNumericCellValue(). k++) { if (threads == rowsord[k].getNumericCellValue().createCell(2). sumtctime = rowsord[i].getNumericCellValue(). cont2++. Row.getCell(3). 28 .getNumericCellValue(). } } if(cont2==0){ Row=sheet. Row.setCellValue((sumthreads / cont1)).createCell(1).setCellValue((sumwmsctime / cont1)). Row=sheet.getNumericCellValue().getCell(6) . i++.setCellValue((sumtctime / cont1)).getNumericCellValue().createCell(18).getNumericCellValue().getCell(2). sumgwcrate = rowsord[i]. sumgwcrate += rowsord[k]. Row. sumwmsctime += rowsord[k].createCell(3). HSSFRow Row = null.createCell(19).getCell(5) . sumtcrate = rowsord[i]. sumgwctime += rowsord[k].getCell(4) .createCell(17). for (int k = i + 1.getCell(2) .createCell(16).getCell(3) .getRow(28).2.setCellValue((sumtcrate / cont1)).getCell(0) .setCellValue((sumthreads / cont1)).getRow(1). Row.getNumericCellValue()) { sumthreads += rowsord[k].getNumericCellValue().getCell(0) . Row.sumgwctime = rowsord[i].getNumericCellValue(). sumwmsrate += rowsord[k]. Row.setCellValue((sumgwcrate / cont1)).getCell(1) .

Row. Row. 29 .".setCellValue((sumwmsctime / cont1)).createCell(0). null. i < numrows.createRow(cont2+28). } } } public static void setMinThread(double threshold. Row = sheet. File objFile = new File(strNombreArchivo). cont2++.class.getName()).close().removeSheetAt(1).createCell(18). } catch (IOException ex) { Logger.createCell(19).createRow(cont2 + 1). Row. Row.} else{ Row = sheet. FileOutputStream archivoSalida = new FileOutputStream(objFile).setCellValue((sumgwctime / cont1)).createCell(3). k < 7. } } for (int i = 2. archivoSalida. Row.getCell(k). HSSFRow[] rows) { double minthreads = getMaxThread(). Row.getLogger(ReportGenerator. k++) { summary += rows[i].createCell(1).createCell(17). PrintableTable.log( Level.write(archivoSalida). ex).getNumericCellValue() + " ".getProperty("outfilename"). i++) { for (int k = 0.setCellValue((sumtcrate / cont1)).setCellValue((sumtctime / cont1)).setCellValue((sumgwcrate / cont1)).setCellValue((sumthreads / cont1)).main(summary). libro. } summary += ".createCell(2). String strNombreArchivo = properties.SEVERE. } libro. Row.createCell(16).setCellValue((sumthreads / cont1)). Row.setCellValue((sumwmsrate / cont1)).

} public static double getMinThread() { 30 . } public static void setMaxThread(HSSFRow[] rows) { for (int i = 2.getNumericCellValue() .getCell(0).getNumericCellValue(). for (int i = 2.getCell(0). i < getNumRow(). i++) { threads = rows[i]. i < getNumRow(). } public static double getNumRow() { return numrow. if (threads > getMaxThread()) { maxthread = threads.threshold. i++) { double threads = rows[i]. } } minthread = minthreads. } public static double getMaxThread() { return maxthread. } public static void setNumRow(double numrows) { numrow = numrows. if (threads > 0 && threads < minthreads .threshold) { minthreads = threads + threshold.double threads = 0. } } } public static double getMaxThreads() { return maxthread.

public Constants cs = new Constants().length. int rowNumber = rowstr. } public void setTitle(String title) { this.title = title.benchmarking. row++) { String[] colstr = rowstr[row].split(" ").colNumber = colNumber. String summary) { String[] rowstr = summary.rowNumber = rowNumber. public class PrintableTable { private String title. if (colstr.title = title.uva. data = new String[rowNumber + 1][colNumber].java package es.length. } } this. this. } public String getTitle() { return title. int colNumber = 0."). private String[][] data. } } 2. private int rowNumber. for (int row = 0.return minthread.idelab.4.­ PrintableTable. row < rowstr. public PrintableTable(String title.length. private int colNumber.split(". } 31 . this.length > colNumber) { colNumber = colstr.

row++) { colstr = rowstr[row].data[0][0] = "Threads". } } } public String toString() { int colWidth = getColWidth().1) + "\n". this.colNumber.title. row < this.data[row + 1][col] = colstr[col]. (colNumber * (colWidth + 1) . for (int row = 0.split(" "). String line = " " + getRepeated("_".data[0][1] = "WMS-C-Wrapper". this.title.data[0][6] = "TileCache".split(". this. this. this. col < this.data[0][2] = "GeoWebCache".data[0][3] = "TileCache".length() + 0. (int) ((colNumber * (colWidth + 1) . table += "|" + getRepeated(" ".rowNumber. colNumber * (colWidth + 1) .length() .data[0][4] = "WMS-C-Wrapper". this. table += line.public String[][] getData() { return data.7) / 2)) + "|\n".1) / 2) + title + getRepeated(" ".data = data. } public void setData(String[][] data) { this. String[] colstr. } public void setData(String summary) { String[] rowstr = summary.data[0][5] = "GeoWebCache". 32 . col++) { this. this."). for (int col = 0. String table = "".

i++) { chain += s. } } return width. } return chain. table += line. return table.toString().getAvgRate()+getRepeated(" ".getAvgRate().(int) (3 * (colWidth + 1) . col < colNumber. } table += "|\n". for (int row = 0. if (row == 0) { table += line.getAvgTime(). row++) { for (int col = 0.toString(). } private int getColWidth() { int width = 0. table += getRepeated(" ".length()). (3 * (colWidth + 1) .length()) / 2)+cs. } private String getRepeated(String s.length() + 1)) / 2) + "|".getAvgTime()+ getRepeated(" ". row < rowNumber + 1. col++) { if (data[row][col]. table += data[row][col]. col < colNumber.data[row][col]. int n) { String chain = "".length()) / 2)+cs.table += line.length(). table += "|"+ getRepeated(" ". for (int i = 0.setData(summary). row++) { for (int col = 0. 33 . (3 * (colWidth + 1) cs. } } table += line. row < rowNumber + 1. i < n.toString().getAvgRate().cs. tbl.length() > width) width = data[row][col].length() + 1)) / 2) + "|\n".toString() + getRepeated(" ". } public static void main(String summary) { PrintableTable tbl = new PrintableTable("Results Summary". col++) { table += "|".getAvgTime(). for (int row = 0. summary).(int) (3 * (colWidth + 1) (cs.(cs. colWidth)+"|"+getRepeated(" ". colWidth .

out.println(tbl).System. } } 34 .