Archivo de la etiqueta: Performance

Herramientas

Habilitar el opcache que viene con php ( >= 5.5 ) en xampp

Ya en el futuro de va a demostrar si este nuevo opcache es mejor que los ya conocidos, pero de momento es el ÚNICO que funciona razonablemente bien en WINDOWS.

Edita tu “php.ini” y pega esto al final del archivo (si tenes configurado xdebug, al opcache ponelo por encima de este)

[Opcache]
; poné el path real donde esté alojado php_opcache.dll
zend_extension = "C:\xampp\php\ext\php_opcache.dll"
opcache.memory_consumption = 500
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=1

Y listo, tenemos un motivo menos de sufrimiento a la hora de programar en este SO.

Chau!

Drupal APC: configuración rápida

Aquí dejo una configuración rápida de APC.

extension=apc.so
apc.shm_segments=1
apc.shm_size=256M

Si están usando Debian o derivados pueden poner la configuración en /etc/php5/conf.d/20-apc.ini (la parte del nombre “20-” puede variar, verifiquenlo antes de editar).

Para mas opciones ver http://www.php.net/manual/es/apc.configuration.php

No olvides reiniciar apache: sudo service apache2 restart

Chau!

performance

Mejorando el rendimiento en Drupal 7: Memcached y Entity cache

En este post vamos a enfocarnos sobre Memcached tratando de mostrar las ventajas a la hora de utilizarlo en Drupal 7.

Memcached para los que no lo conozcan, es un data cache basado en RAM.

Usar Memcached en Drupal tiene un beneficio altísimo tanto para usuarios logueados como para anónimos. ¿Por que?, fácil, Drupal para cachear utiliza la base de datos como almacén para dicho cache, y esto es costoso. Cada vez que guarda algo en cache o lo pide, estamos haciendo una query a la DB, y aunque toda tu DB este cacheada (mysql tiene su propio cache) Drupal siempre va a tener un importante overhead solo por tener que pedir a la DB este cache.

Técnicamente hablando el tema es así: Estés o no logueado, Drupal usa cache_get() y cache_set(). Luego, estas funciones delegan la tarea de cacheo a la clase que se encargue en ese momento de almacenar y devolver los datos cacheados. Una instalación estándar trae una clase llamada “DrupalDatabaseCache” que usa como backend storage la propia DB de Drupal. El módulo Memcache API simplemente proporciona su propia clase (MemCacheDrupal) que hace lo mismo pero mandando el cache a Memcache.

Memcache se presenta como una muy buena solución a este escollo ya que fue diseñado para ser usado como cache, ofreciendo un overhead mínimo y una velocidad de respuesta muy superior.

Bueno, vamos al lío.

Maquina de pruebas:

Para hacer las pruebas he usado la instalación de Drupal “Un mal día para este Drupal“.
Las pruebas las hice sobre usuarios anónimos, logueados y el propio admin que es el que mas suele sufrir en terminos de performance porque ejecuta código extra por los privilegios que conlleva.

Usuarios anónimos:

Pruebas con el cache de Drupal desactivado:

Sin Memcache

  • Executed 2312 queries in 199.42 ms.
  • Page execution time was 4791.87 ms.
  • PHP peak=59.25 MB.

Con Memcache

  • Executed 1226 queries in 71.77 ms.
  • Page execution time was 3892.39 ms.
  • PHP peak=57 MB.

Con Memcache y entity cache:

  • Executed 398 queries in 39.88 ms.
  • Page execution time was 3450.76 ms.
  • PHP peak=56 MB.
Ahora con el cache de Drupal y bloques activado:

Sin Memcache

  • Executed 2312 queries in 167.15 ms.
  • Page execution time was 4037.62 ms.
  • PHP peak=59.25 MB.

Con Memcache

  • Executed 1186 queries in 66 ms.
  • Page execution time was 3927.52 ms.
  • PHP peak=57.75 MB.

Con Memcache y entity cache:

  • Executed 377 queries in 30.31 ms.
  • Page execution time was 3534.07 ms.
  • PHP peak=55.25 MB.

Usuarios logueados

Pruebas con el cache de Drupal desactivado:

Sin Memcache

  • Executed 2324 queries in 162.27 ms.
  • Page execution time was 4033.2 ms.
  • PHP peak=58.75 MB.

Con Memcache

  • Executed 1237 queries in 73.47 ms.
  • Page execution time was 4028.68 ms.
  • PHP peak=56.25 MB.

Con Memcache y entity cache:

  • Executed 396 queries in 26.19 ms.
  • Page execution time was 3530.29 ms.
  • PHP peak=56 MB.
Ahora con el cache de Drupal y bloques activado:

Sin Memcache

  • Executed 2262 queries in 182.59 ms.
  • Page execution time was 4286.79 ms.
  • PHP peak=58 MB.

Con Memcache

  • Executed 1237 queries in 56.45 ms.
  • Page execution time was 3716.37 ms.
  • PHP peak=56.25 MB.

Con Memcache y entity cache:

  • Executed 379 queries in 27.97 ms.
  • Page execution time was 4072.24 ms.
  • PHP peak=55.25 MB.

Usuarios con rol “administrator”

Pruebas con el cache de Drupal desactivado:

Sin Memcache

  • Executed 3106 queries in 231.33 ms.
  • Page execution time was 5588.66 ms.
  • PHP peak=66.75 MB.

Con Memcache

  • Executed 1812 queries in 89.79 ms.
  • Page execution time was 4701.39 ms.
  • PHP peak=64.5 MB.

Con Memcache y entity cache:

  • Executed 1133 queries in 68.43 ms.
  • Page execution time was 4563.24 ms.
  • PHP peak=64.25 MB.
Ahora con el cache de Drupal y bloques activado:

Sin Memcache

  • Executed 3104 queries in 219.49 ms.
  • Page execution time was 5510.96 ms.
  • PHP peak=67 MB.

Con Memcache

  • Executed 1816 queries in 107.06 ms.
  • Page execution time was 4931.99 ms.
  • PHP peak=64.25 MB.

Con Memcache y entity cache:

  • Executed 1133 queries in 71.71 ms.
  • Page execution time was 4641.69 ms.
  • PHP peak=64.25 MB.

Resumiendo:

Gráfica comparativa de Memcache y Entity cache en Drupal

Como podemos ver, cuando usamos Memcache, las queries a la db bajan un nada despreciable 50%. Estas query que ya no están, son “cache” que pasan a ser gestionadas por Memcache, quien como ya comentamos, es mucho mas eficiente a la hora de servir contenidos cacheados (insisto que está diseñado para ello, ergo es muy difícil que mysql lo haga mejor).

Pero para mas inri, al activar Entity cache, automágicamente las query a la DB bajan un 60% mas sobre lo que ya había conseguido Memcache. Esto es gracias a que este modulo implementa una capa de cache a todas las entidades del core de Drupal mas todas las entidades creadas por terceros que implementen la api en entity cache para dejarse cachear.

Conclusiones:

  • Entre Memcache y entity cache hemos logrado una reducción media del 85% de accesos a la DB (awesomeeeee!).
  • El beneficio mas evidente en el uso de Memcache y entity cache juntos es el de una reducción drástica en las
    consultas que se hacen a la DB, lo que viene especialmente bien ya que cuando una pagina en Drupal comienza a
    recibir muchas visitas, la db es lo primero que sufre.
  • Luego de estas pruebas podemos concluir que si usar Memcache es una buena idea, combinarlo con entity cache es
    una excelente idea.
  • Memcache y entity cache funcionan tanto en usuarios logueados como anónimos.
  • Es evidente que mientras mas cosas cacheemos en Drupal, mejor va a funcionar esta solución. En especial me
    refiero a views, y panels. Usen el cache que estos módulos tienen, para que Memcache pueda gestionarlos. En una
    prueba rapida que hice conseguí rebajar aun mas la cantidad de queries a solo 95 contra las 377 que ya
    lográbamos usando Memcache y entity cache
    .

Happy performance!

Drupal scared

Un mal día para este Drupal

Hola, he preparado un Drupal 7 para hacer unas pruebas de rendimiento y me he ensañado todo lo que pude para que vaya lo mas lento posible.

¿Que le hice?

  • Habilite casi todos los módulos del core y todos los módulos mas usados mas las librerías externas, lo que nos da 202 módulos activos*1.
  • Aplique la traducción de todos los módulos al español (las traducciones son killer)
  • Hice un tipo de contenido con todos los field de los que dispongo (llamado “Full CT”).
  • 10000 nodos del tipo “Full CT”
  • 10000 términos
  • 10000 usuarios
  • 1000 links en main menu
  • Una vista con 100 usuarios por pagina y paginados
  • Una vista con 100 términos por pagina y paginados
  • Una vista con 100 nodos del ct con todos los fields.
  • Un panel con todas las vistas anteriores

Luego agarré todo lo anterior y lo coloqué en la pagina principal.

Para cuando terminé, Drupal estaba por los suelos. No servia, apenas respondía, los tiempos de carga eran penosos, vamos, lo que viene siendo mi entorno ideal para hacer las pruebas.

Lo pongo a vuestra disposición para quien quiera hacer sus propias pruebas.

Descargar

PD: Dentro de drupalbench.tar.gz está la DB, el usuario de Drupal es “admin” pass “admin”. La DB es drupalbench (toquen settings.php para configurar el usuario de mysql)

Referencias:

Módulos habilitados:

  • Aggregator
  • Block
  • Blog
  • Book
  • Color
  • Comment
  • Contact
  • Contextual links
  • Dashboard
  • Database logging
  • Field
  • Field SQL storage
  • List
  • Number
  • Options
  • Text
  • Field UI
  • File
  • Filter
  • Forum
  • Help
  • Image
  • Locale
  • Menu
  • Node
  • OpenID
  • Path
  • PHP filter
  • Poll
  • RDF
  • Search
  • Shortcut
  • Testing
  • Statistics
  • Syslog
  • System
  • Taxonomy
  • Toolbar
  • Tracker
  • Content translation
  • Trigger
  • Update manager
  • User
  • Standard
  • Address Field
  • Administration Development tools
  • Administration menu
  • Administration menu Toolbar style
  • Advanced help
  • Advanced help example
  • Backup and Migrate
  • Calendar
  • CKEditor
  • Coder
  • Coder Review
  • Colorbox
  • Commerce
  • Commerce UI
  • Cart
  • Checkout
  • Customer
  • Customer UI
  • Line Item
  • Line Item UI
  • Order
  • Order UI
  • Payment
  • Payment UI
  • Payment Method Example
  • Price
  • Product
  • Product UI
  • Product Pricing
  • Product Pricing UI
  • Product Reference
  • Tax
  • Tax UI
  • Commerce Features
  • Commerce Order Fieldgroup Panes
  • Context
  • Context layouts
  • Context UI
  • Bulk Export
  • Chaos tools
  • Chaos Tools (CTools) AJAX Example
  • Custom content panes
  • Chaos Tools (CTools) Plugin Example
  • Page manager
  • Stylizer
  • Views content panes
  • Date
  • Date All Day
  • Date API
  • Date Context
  • Date Popup
  • Date Repeat API
  • Date Repeat Field
  • Date Tools
  • Date Views
  • Devel
  • Devel generate
  • Email
  • Enabled modules
  • Entity API
  • Entity tokens
  • Entityforms
  • Entityforms Notifications
  • entityform_test
  • Entity Reference
  • Entity Reference Behavior Example
  • Features
  • Fieldgroup
  • NIF Field
  • Global Redirect
  • Internationalization
  • Block languages
  • Contact translation
  • Field translation
  • Multilingual forum
  • Menu translation
  • Multilingual content
  • Path translation
  • Translation redirect
  • Multilingual select
  • String translation
  • Synchronize translations
  • Taxonomy translation
  • Translation sets
  • User mail translation
  • Variable translation
  • IMCE
  • IMCE Wysiwyg API bridge
  • Interval Field
  • jQuery Update
  • Localization update
  • Libraries
  • Lightbox2
  • Link
  • File entity
  • Media
  • Media Internet Sources
  • Memcache
  • Menu Block
  • Menu Block Export
  • Message
  • Message example
  • Message OG example
  • Migrate
  • Migrate UI
  • Module filter
  • Mollom
  • Nice Menus
  • Organic groups
  • Organic groups context
  • Organic groups register
  • Organic groups UI
  • Page Title
  • Panels
  • Panels In-Place Editor
  • Mini panels
  • Panel nodes
  • Pathauto
  • Profile2 translation
  • Profile2 pages
  • Profile2
  • Node Reference
  • References
  • User Reference
  • Rules
  • Rules UI
  • Rules translation
  • Rules Scheduler
  • Rules Forms Support
  • Special menu items
  • Token
  • Transliteration
  • Variable
  • Variable admin
  • Variable advanced
  • Variable example
  • Variable realm
  • Variable store
  • Variable views
  • Variable Email
  • Views
  • Views UI
  • Views Bulk Operations
  • Views Slideshow: Cycle
  • Views Slideshow
  • Views System
  • Webform
  • Wysiwyg
  • XML sitemap
  • XML sitemap custom
  • XML sitemap engines
  • XML sitemap internationalization
  • XML sitemap menu
  • XML sitemap node
  • XML sitemap taxonomy
  • XML sitemap user
  • Memcache Admin
Druplicon

Instalar y configurar xhprof para que funcione en Drupal.

El modulo Devel nos proporciona una buena forma de integrar xhprof en nuestra instalación de drupal, y vamos a aprovecharla.

Xhprof para quien no lo conozca aun, es un profiler. Principalmente nos permite saber de forma detallada cuanta ram, cpu y tiempo han consumido cada una de las funciones que se utilizan en un request.
De esta forma podemos centrarnos en las funciones mas conflictivas y resolver sus cuellos de botella.

Si se van a la configuración de Devel podemos ver que la opción esta deshabilitada

Y es solo porque no tenemos xhprof  instalado, asi que manos a la obra:

NOTA: Los pasos de instalación los hice en D7 sobre Ubuntu, pero son compatibles con cualquier *nix siempre que se adapten las rutas de las carpetas a las que utilicé el SO sobre el que quieras instalarlo.

Primero instalemos xhprof desde su código fuente. con la consola en mano te vas a tu home (por decir algún lado) y lanzamos:

wget http://pecl.php.net/get/xhprof-0.9.2.tgz
tar xvf xhprof-0.9.2.tgz
cd ./xhprof-0.9.2/extension/
phpize
./configure --with-php-config=/usr/bin/php-config
make
make install

Configuremos PHP para que use xhprof:

nano /etc/php5/conf.d/xhprof.ini

Y pegar esto dentro:

extension=xhprof.so
xhprof.output_dir="/var/tmp/xhprof"

Listo, ya tenemos instalado xhprof.
Ahora creemos el directorio en el que se van a generar los dump (cada request genera un archivo de dump con toda la informacion registrada):

mkdir -p /var/tmp/xhprof
chown www-data. /var/tmp/xhprof

Bien, ahora dentro de la carpeta que contiene el codigo fuente que usamos hace un momento para hacer la instalacion, tenemos que copiar las carpetas “xhprof_html” y “xhprof_lib” en “/usr/share/php/“:

cp -Pr xhprof_html/* /usr/share/php/xhprof_html/
cp -Pr xhprof_lib/* /usr/share/php/xhprof_lib/

Xhprof genera graficos que son de mucha ayuda a la hora de identificar cuellos de botella y para crearlos utiliza las capacidades del programa graphviz. si no lo tenés instalado poder hacerlo lanzando:

apt-get install graphviz

Ok terminamos con la configuracion de xhprof. configuremos el resto del entorno para que pueda hacer uso de el.
Lo siguiente es crear un vhost para poder acceder a la informacion que genere xhprof:

nano /etc/apache2/sites-available/xhprof

Y pegas esto:

<virtualhost localhost:9999>
   DocumentRoot /usr/share/php/xhprof_html
   DirectoryIndex index.php
   <directory /usr/share/php/xhprof_html>
     AllowOverRide all
     Options FollowSymLinks
   </directory>
</virtualhost>

Nuestro vhost corre en el puerto 9999 asi que tenemos que agregarlo a apache:

nano /etc/apache2/ports.conf

debajo de “Listen 80” agrega:

Listen 9999

Estamos por teninar. Habilita el vhost que hemos creado con el comando “a2ensite xhprof“, reinicia apache con “service apache2 restart” y en nuestra instalación de Drupal 7 vayamos a “admin/config/development/devel” para configurarlo:

Ahora ves que ya podes marcar la opcion “Enable profiling of all page views and drush requests.


Cuando la marques vas a tener que rellenar:
xhprof directory:” ponele “/usr/share/php” (sin comillas)
XHProf URL:” ponele “http://localhost:9999” (sin comillas)

Y listo. ya lo tenes integrado en drupal. si miras en la parte inferior izquierda de cualquier pagina de la instalacion de tu drupal vas a ver que aparece un link llamado “XHProf output que te va a llevar a la pagina informativa del perfilado que se hiso.

 

 

Bonus!:

Nota: solo por cuestiones de mantenimiento te comento que los dump que genera xhprof en la carpeta “/var/tmp/xhprof” tienden a comerse el disco en cuestion de dias. la solucion que uso es lanzar un cron que limpia todos los dump que tengan mas de un dia.

El cron es un archivo con permisos de ejecucion y el siguiente contenido

#!/bin/bash
#Elimina todos los perfilados que tengan mas de 1 día
find /var/tmp/xhprof -type f -mtime +1 -exec rm -f {} \;

Guardalo en /etc/cron.daily/xhprof_cleaner.sh y listo.

Una nota final. La configuracion que explique no tiene en cuenta la seguridad. esto quiere decir que no deberias utilizarla en produccion salvo que sepas lo que haces.

Druplicon

Benchmark Drupal 7 + APC + Memcached + Varnish sobre usuarios anónimos

Vamos a hacer algunos testeos para ver lo que podemos llegar a ganar en performance al implementar una serie de tecnologías sobre Drupal 7.

Las pruebas las realizare sobre una instalación LAMP estándar de Ubuntu (Linux Mint en realidad):

  • mysql 5.1.58 (Con su configuración por defecto)
  • php 5.3.6 (Con su configuración por defecto)

El software para mejorar la performance que usé y las versiones de cada uno son:

  • APC-3.1.9
  • memcached 1.4.7
  • Varnish 3.0.4

Esta prueba es solo para que nos demos una idea de lo que podría llegar a implicar el aplicar estas tecnologías en nuestro sitio de Drupal 7, por lo que he dejado fuera cualquier explicación técnica.

Las pruebas las hice en un core2Duo @ 2.2ghz de 2 núcleos en un Linux Mint de 64bits y 8gb de ram.

La idea es ir agregando tecnologías e ir viendo el teórico beneficio que esta aporta aplicadas a la practica.

Lo primero es lo primero. vamos a hacer un bench de Drupal 7.10 en sobre nuestro LAMP sin haber tocado su configuración inicial.

Utilice Apache benchmark (ab) para todos los testeos variando la concurrencia y cantidad de request para aprovechar al máximo los recursos de los que disponía en cada testeo que hice.

Primera ronda. Estableciendo un punto de referencia.

Test 1: Drupal 7 sin cache de ningún tipo.

Resultados:
Requests per second: 5.71 [#/sec] (mean)
Transfer rate: 45.35 [Kbytes/sec] received

Test 2: Drupal 7 marcandole las opciones “Aggregate and compress CSS files.” y “Aggregate JavaScript files.” en “admin/config/development/performance”

Resultados:
Requests per second: 6.38 [#/sec] (mean)
Transfer rate: 46.27 [Kbytes/sec] received

Podemos apreciar que no hay cambios. nada que comentar.

Test 3: La configuración del testeo anterior + “Cache blocks” en “admin/config/development/performance”

Resultados:
Requests per second: 5.18 [#/sec] (mean)
Transfer rate: 37.54 [Kbytes/sec] received

Pasados los tes primeros test ya no quedan dudas que el cuello de botella de los procesadores son los limitantes. Apenas si pudimos conseguir que varíe el resultado.

——————————————————————

Hasta acá fue lo aburrido, porque en realidad lo anterior no tiene ninguna magia, pero nos da una buena idea de desde que base estamos partiendo. Nuestro objetivo es subir grotescamente la media de request por segundo partiendo de los aproximadamente 6 que hemos conseguido hasta ahora.

Test 4: La configuración del test anterior + “Cache pages for anonymous users” (El cache normal de Drupal).

Resultados:
Requests per second: 127.22 [#/sec] (mean)
Transfer rate: 921.83 [Kbytes/sec] received

Bueno bueno bueno, esto ya es otra cosa. El cache de Drupal por si solo incrementa los request de una forma brutal, pero no nos quedamos ahí ni en broma, vamos a por mas RPS (request por segundo)

——————————————————————

Segunda ronda. tecnologías y configuraciones foráneas:

Test 5: La configuración del test anterior + APC.

Este es uno de los cambios mas recomendados siempre que queramos obtener un incremento de performance (y mejor aprovechamiento de la ram disponible) sin tener que tocar ni una sola linea de código de nuestro Drupal.

Resultados:
Requests per second: 440.43 [#/sec] (mean)
Transfer rate: 3191.39 [Kbytes/sec] received

Boom! performance X4!. Vamos por buen camino. Agreguemos mas de esas cosas que recomiendan los que saben…

Test 6: La configuración del test anterior + Memcached

Para esta prueba instalé el modulo memcache (http://drupal.org/project/memcache) en su versión 7.x-1.0-rc2 y lo configuré en su forma mas básica según las instrucciones de su configuración.

Resultados:
Requests per second: 397.38 [#/sec] (mean)
Transfer rate: 2734.53 [Kbytes/sec] received

No hemos visto mejora alguna pero no porque Memcache no sirva, al contrario, en futuros bench les voy a mostrar como si que ayuda, pero bajo este entorno poco sirve ya que es una capa intermedia con la DB y estamos usando el cache de Drupal que apenas si la toca… en fin, en el próximo bench les muestro, paciencia.

Hasta ahora hemos conseguido mejorar los iniciales 6 RPS del principio por fabulosos 400 RPS de media, pero aun nos queda un paso mas para mejorar los request para usuarios anónimos, y ese es Varnish

Test 7: La configuración del test anterior + Varnish

Resultados:
Requests per second: 6166.57 [#/sec] (mean)
Transfer rate: 45075.00 [Kbytes/sec] received

Acaso hay algo que añadir?

Conclusiones:

Hemos visto como Drupal 7 sin ningún tipo de cache activo es una muy mala idea a la hora de ponerlo en producción.
El cache que trae de serie no es opcional, sino que es mandatorio. No activar como mínimo esta capa de cache en Drupal derivaría automáticamente en un uso elevadisimo de los recursos disponibles, esto acompañado de tiempos de entrega mucho mas largos y por consiguiente la insatisfacción de nuestros clientes.
APC es una excelente adición a nuestro servidor en general ya que agiliza el procesamiento de cualquier pagina escrita en PHP y particularmente en Drupal es un beneficio directo tanto para usuarios anónimos como para usuarios logueados. Recomiendo su uso sin dudarlo aunque hay que hacerlo con cabeza, documentación y alguien que sepa lo que hace si no quieren volver inestable vuestro sistema.

Memcache es una herramienta que no puede faltar en un buen servidor y es harto eficiente para usuarios no logueados en el terreno de Drupal, pero en una instalación en la que casi todos los visitantes sean anónimos, apenas van a sentir la mejora.

Por ultimo y el mas importante, Varnish, que demostró el salto ABISMAL que puede llegar a proporcionar en velocidad cuando lo ponemos a trabajar con una instalación de Drupal. Sin duda pues, esta es la herramienta mas potente de las que hemos utilizado en este bench, pero a su vez, la mas complicada de configurar.

Resumiendo la mejor combinación para usuarios anónimos:
Cache de Drupal = performance decente / Configuración… bueno no lleva configuracion XD. (ganancia de 21x con con respecto a los 6 de media iniciales)
Cache de Drupal + APC = Muy buena performance / Configuración media. (ganancia de 73x con con respecto a los 6 de media iniciales)
Cache de Drupal + APC + Varnish = Bruta performance / Configuración avanzada. (ganancia de 1027x con con respecto a los 6 de media iniciales)

Disclaimer:
No son ni de lejos las mejores versiones ni servidores los que he usado, pero procuré enfocarme en estos debido a que son los mas extendidos/populares en nuestro creciente mundo llamado Drupal.

Saludos.

Opciones de esquinas redondeadas para internet explorer 6, 7 y 8

Hace casi un año me vi en la tarea de investigar una vez mas cual era la mejor forma de obtener bordes redondeados para estos navegadores pero esta vez teniendo en cuenta la velocidad de desarrollo.

Las opciones que tenia a mano eran:

La mas tradicional, anidar divs hasta el cuatro niveles para poder colocar imágenes en cada una de las esquinas:

<div class="redondeo">
    <div>
        <div>
            <div>
                <h2>Lorem ipsum dolor</h2>
                <div class="contenido">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit...
                </div>
            </div>
        </div>
    </div>
</div>
* {
    font-family: Verdana;
}
.redondeo {
    background: url("images/esq_sup_2-1.png") no-repeat scroll 100% 100% transparent;
    width: 300px;
}
.redondeo div {
    background: url("images/esq_sup_1-1.png") no-repeat scroll 0 100% transparent;
}
.redondeo div div {
    background: url("images/esq_sup_2.png") no-repeat scroll 100% 0 transparent;
}
.redondeo div div div {
    background: url("images/esq_sup_1.png") no-repeat scroll 0 0 transparent;
}
.contenido {
    background: none repeat scroll 0 0 transparent !important;
    padding: 0 15px 15px;
    text-align: center;
}
h2 {
    color: #fff;
    text-align: center;
}

Ver ejemplo | Descargar

Este método tiene sus pro y sus contras.
Lo que tiene de bueno es que esta técnica es compatible con todos los internet explorer partiendo de la versión 5 y que la velocidad de renderizado es instantánea.

Lo malo es que es poco mantenible. Lo digo por lo siguiente: pensemos por un momento que tenemos que cambiar el color de la cabecera de la caja de ejemplo. El primer problema es que al ser una imagen que tiene los bordes creados con algún editor de imágenes como Photoshop, Gimp o Paint.NET, para cambiar el color deberíamos recurrir a estas herramientas. Si quisiéramos ponerle un borde de color lo mismo., y ni hablar si queremos remaquetar el site entero.
Y lo anterior es por decir alguno de los casos mas normales, pero hay mas, y quien haya usado esta técnica sabe de lo que hablo.

La segunda opción DD_roundies:

Es la que estuve usando intensamente hasta hace poco. Se trata de una librería JavaScript llamada DD_roundies.
Esta librería redondea cualquier elemento HTML de tipo bloque usando VML para conseguirlo.
Es realmente notable el resultado que se consigue con esta librería. De hecho por un buen tiempo la consideré la solución mas acertada ya que es realmente fácil de usar:

<!-- Agregamos el JS--> <script src="DD_roundies.js"></script> 
//Agregamos el JS
/* 
Ahora solo necesitamos decirle a ddroundies sobre que 
class o id debe redondear y de cuanto es el radio de 
redondeo que debe aplicar */
/**
 * Un redondeo de todos los bordes a 10 pixeles para todos 
 * los elementos HTML que lleven definida esta clase
 * */
DD_roundies.addRule('.redondeado-10px', '30px');
/*
 Tambien se puede especificar un redondeo para cada 
 una de las esquinas
 
 5px para la esquina superior izquierda
 10px para la esquina superior derecha
 15px para la esquina inferior derecha
 20px para la esquina inferior izquierda
 */
DD_roundies.addRule('.redondeado-popurri', '5px 10px 15px 30px');
/*
Es opcional definir los css, pero
aca los defino para darles un color
*/
.redondeado-10px {
    background-color: #336699;
}
.redondeado-popurri {
    background-color: #ff0000;
}
<div class="redondeado-10px">
    <br />
    <br />
    Lorem ipsum dolor sit amet, consectetur adipiscing elit...
    <br />
    <br />
</div>
<br />
<div class="redondeado-popurri">
    <br />
    <br />
    Lorem ipsum dolor sit amet, consectetur adipiscing elit...
    <br />
    <br />
</div>

Ver ejemplo | Descargar

Como ven el uso es simple, PEEEERO la gran pega que tiene esta técnica es el hambre voraz de procesador para renderizar las esquinas, brutal, y en un principio para hacer cosas chicas como una o dos cajas redondeadas va de maravilla, pero haganlo con 20 o 30… Mejor NO LO HAGAN, ya les puedo adelantar que la pagina va a quedar congelada varios segundos hasta que termine de dibujar todas las esquinas.

La tercera, curved-corner:

Basada también en VML, es “curved-corner” y Alexis de Eliseos.net ha dedicado un post hace unas semanas.

Esta implementacion fue de las primeras alternativas que conoci hace un tiempo ya, y la usé y deje de usar con la misma rapidez porque tiene dos flaquezas inaceptables y que al dia de hoy no se han solucionado:
La mas importante es que despues de redondear una X cantidad de div o lo que sea, va a fallar y dejar de redondear el resto.
La segunda es que esta solucion a diferencia de la segunda propuesta, solo permite aplicar un redondeo completo al div, dejando fuera la porsibilidad de hacer un redondeo solo a una esquina.

Las otras soluciones:

¿Hay mas? si claro, un millón de soluciones. Las que mas han prosperado son sobre todo las basadas en frameworks js. Un ejemplo es

http://www.malsup.com/jquery/corner/

Pero ni vale la pena ponerse a hablar este tipo de soluciones porque no alcanzan a crear unos bordes tan perfectos como los que logran las anteriores soluciones ya citadas.

Conclusion:

De estas tres tecnicas la mas reocmendable de todas es la de DD_roundies, que mas alla de tener inconvenientes como las otras dos, es la que mas compensa la relacion velocidad de desarrollo – calidad. Lo unico en lo que hay que tener un muy especial cuidado es en no llenar la pagina de bordes redondeados por medio de este metodo porque insisto, van a tener un increible problema de performance.
De hecho, para cerrar este post puedo proponer una solucion hibrida entre la solucion de redondeo por medio de imagenes y la de DD_roundies, usando la primera para cualquier lista de elementos HTML que se repitan contantemente y sean iguales claro, dejando la opcion de DD_roundies para situaciones mas complicadas de solucionar con lo que a diseño respecta.

internet-explorer-logo

Problemas de performance con flash en Internet Explorer

Como viene siendo habitual en los desarrollos en los que participo, cuando todo anda como un reloj suizo en los navegadores de verdad, en Internet Explorer simplemente falla todo. Y falla de formas muy raras.

Por ejemplo. El otro dia detectamos un problema de performance con Internet Explorer y flash. Todo andaba bien, solo que se tardaba una decada en renderizar el contenido.

Sabiamos que tenia que ver con unos objetos de flash que estabamos cargando, ya que dos desactivabamos y andaba a las mil maravillas.

Le dimos mil vueltas al problema hasta  que una compañera (gracias Ana) encontró que el problema podia ser el siguiente:

Performance Note   Internet Explorer relies on the MIME type of the resource specified in the SRC attribute to ultimately determine which application to use to display the embedded document. If the TYPE attribute has not been specified, a large portion (if not all) of the resource will be downloaded from the server twice; once to determine the MIME type, and again to retrieve the complete item for playback, display, or both. Specify the TYPE attribute to block this duplicate server request.

Extraído de: http://msdn.microsoft.com/es-es/library/ms535245%28en-us,VS.85%29.aspx

Para los legos en ingles dice básicamente que si no le dices que el “typees “application/x-shockwave-flash” dentro del objeto <embed>, Internet Explorer va a bajar todos los flash para analizar de que type se trata y a posteriori los va a bajar otra vez para mostrarlos.

Es ridículo que haga eso. Podría usar el objeto que ya ha descargado.

Entonces ya saben. Si flash les decrecienta el rendimiento de carga en vuestras paginas Web en Internet Explorer casi casi seguro que les este faltando el Type:

<object
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com
/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"
width="400" height="300" id="movie" align="">
<param name="movie" value="movie.swf">
<embed src="movie.swf" quality="high" width="400"
height="300" name="movie" align=""
type="application/x-shockwave-flash"
plug inspage="http://www.macromedia.com/go/getflashplayer">
</object>