Esto es un espacio para hablar de programación, algoritmos y tecnología. Aquí trato de publicar artículos que contengan un valor adicional y (ojalá) de utilidad para todos lo que los lean.

Después de hacer la comparación entre mi implementación chafa y la de Java, me quedé pensando como hacerle para reducir un poco la diferencia sin quitarle la simplicidad (más bien sin tener que aprender un QuickSort optimizado, jaja).

Entonces se me ocurrió que podría aprovechar las bondades de los, cada vez más comunes, procesadores con HT o doble núcleo. La solución es muy sencilla, solo hay que poner la mitad del arreglo en un hilo y la otra mitad, pues en otro hilo.

Pero me di cuenta de que este enfoque también es aplicable a código que utilice las librerías de Java. Solo hay que usar el método sort(int[] a, int fromIndex, int toIndex) en lugar de sort(int[] a).

De esta forma quedaría algo así para dos hilos:

new Thread() {
	public void run() {
		 Arrays.sort(arr, 0, arr.length / 2);
	}
}.start();

new Thread() {
	public void run() {
		 Arrays.sort(arr, arr.length / 2, arr.length);
	}
}.start();

Sin embargo, este código tiene un pequeño problema; cada hilo ordenará una mitad del arreglo independientemente, así que al final nuestro arreglo no estará globalmente ordenado. Por lo cual recurrí al principio del MergeSort, que se basa en combinar dos arreglos ordenados para tener como resultado un arreglo más grande tabién ordenado. Solamente necesitamos una iteración del Merge y saber donde se hizo el corte del arreglo original y todo quedará resuelto. A continuación, una versión del merge:

merge(int arr[], cuts[]) {
	int index1 = cuts[0];
	int index2 = cuts[1];
	int src[] = arr.clone();

	for (int i = 0; i < src.length; i++) {
 		if (index1 >= cuts[1]) {
 			arr[i] = src[index2++];
 		}
 		else if (index2 >= cuts[2]) {
 			arr[i] = src[index1++];
 		}
 		else {
 			if (src[index1] < src[index2]) {
 				arr[i] = src[index1++];
 			}
 			else {
 				arr[i] = src[index2++];
 			}
 		}
	}
}

NOTA: El arreglo cuts contiene estos valores {0, arr.length / 2}.

Mientras estaba programando este algoritmo pensé de repente: ya que ando en esto, ¿por qué parar aquí? Debería programar algo que sirva para más que solo enteros. Así que le puse genéricos y ahora se puede ordenar cualquier colección de objetos que implementen la interfaz Comparable. Quedó un poco más lento; porque ahora se manejan colecciones y no arreglos, objetos y no tipos de datos primitivos. Pero bueno, todo sea por la cohesión balanceada.

Ya que me sentía tan espléndido, pensé: los procesadores de doble núcleo van a pasar de moda el próximo año, ¿por qué no hacemos el asunto escalable? La solución más obvia para el número de hilos que manejaría es la tendencia del número de núcleos que tienen los procesadores: 2, 4, 8, … Pero, después pensé: ¿qué tal si alguien que tiene un servidor con un montón de núcleos quiere usar mi clase? La tarea de ordenamiento consumiría todos los recursos disponibles o una fracción tal vez inadecuada. Si tengo 8 núcleos ¿qué tal si me da la gana tener a 5 ordenando, 1 para el servidor de aplicaciones, 1 para el servidor de bases de datos y otro para ver una película?

Decidí entonces hacer que aceptara cualquier número de hilos para realizar el ordenamiento. Sin embargo, esto introduce otro problema; el Merge clásico trabaja uniendo pares de arreglos. Lo cual fue resuelto ideando un Merge ad-hoc que juntase cualquier cantidad de arreglos. Lo cual tiene un poquito de overhead, pero realmente no resulta muy grave.

Finalmente, hice alguas pruebas de desempeño. Puse a ordenar 1,000 veces un Vector con 1,000,000 de objetos Integer; todo esto sobre un procesador Intel Core Duo a 1.66 Ghz. A continuación está el tiempo promedio que tardó cada implementación. Cada liga lleva al código fuente en Java.

DualSort (usa dos hilos y el Merge clásico).
ScalableSort (usando dos hilos y el Merge ad-hoc).
Collections.sort (usa un hilo, implementación de Java).

Desempeño de ScalableSort

También puedes descargar un archivo JAR y usar las clases como librerías.

No tiene mucho que decidí (por n-ésima vez) adoptar Ubuntu como mi sistema operativo primario. Lo bueno es que lo he estado logrando (no he tenido mucha necesidad de los juegos últimamente).

El único problema que realmente me molestó fue enterarme de que no podía reproducir DVDs encriptados, es decir, la mayoría de los DVDs comerciales. Ubunto no viene con soporte para DVD por controversias legales. ¡Carajo! ¿A caso no somos libres de elegir un sistema operativo sin que los productos por los que pagamos dejen de funcionar?

Bueno, después de hacer corajes durante varios días me encontré con que hay que bajar unas librerías para poder decodificar el video en DVD. La librería se llama libdvdcss. De su página puedes bajar las fuentes compilables, el paquete en formato DEB o RPM.

Ahora, para ver las películas yo usé el Kaffeine, que es un reproductor multimedia muy bueno. Ese si está en los repositorios oficiales (al menos de Ubuntu); así que se puede instalar fácilmente desde tu manejador de paquetes favorito. Si prefieres instalarlo manualmente entra a la página de descargas.

Google Gears

June 3rd, 2007

Hace unos días fue lanzada esta nueva tecnología de Google. Se trata de una extensión para navegadores que permite a los desarrolladores crear aplicaciones Web que puedan funcionar sin una conexión a Internet.

Google Gears está compuesto de tres módulos que, si bien, logran que una aplicación funcione offline; también sería interesante usar estos módulos por separado.

  • Módulo de LocalServer: Permite guardar contenidos de forma local para después hacerlos disponibles cuando no se cuente con una conexión a Internet.
  • Módulo de Base de Datos: Es un manejador de bases de datos relacional que funciona localmente. Para esto Google usa el sistema SQLite.
  • Módulo WorkerPool: Permite tener una colección de procesos de JavaScript corriendo simultáneamente para no bloquear el flujo del navegador.

A continuación se muestra un diagrama muy ilustrativo de la forma en que se puede sincronizar el contenido de una applicación que usa Google Gears:

Arquitectura de Google Gears

Existen dos formas para sincronizar los datos que hay en la aplicación. La sincronización Manual: el usuario decide cuando sincronizar el contenido; y la Sincronización “en el fondo”: que se ejecuta continuamente sin que el usuario se entere.

Aunque a primera vista no parece una tecnología muy atractiva, ofrecerá muchas ventajas, sobre todo para mejorar los tiempos de respuesta y optimizar el uso del ancho de banda de las aplicaciones que manejan contenidos multimedia intensivamente. Sin duda veremos algunas aplicaciones interesantes muy pronto.

El único problema que le veo para que sea aceptado masivamente es que (obviamente) hay que descargar un paquete del lado del cliente. Lo cual (desafortunadamente) ha sido un gran obstáculo para muchos proyectos muy buenos.

Si quieres saber más sobre Google Gears, haz clic aquí para ir a la página del proyecto y aquí para ver un tutorial.

Lo Nuevo de Java SE 6

June 1st, 2007

Hace algo así como seis meses desde que fue liberado el más reciente JDK, pero realmente no sabía todo lo nuevo que trae; lo que es peor, aún no conozco muchas de las mejoras que introdujo Java 5. Así que se me ocurrió que escribiría sobre las características nuevas más interesantes. Primero de manera general (en este post) y después entrar en detalle con algunos ejemplos (en posts subsiguientes).

Bueno, empecemos. He aquí algunas de las nuevas características:

  •  Web Services: Basta agregar una anotación (esas cosas que se ponen antes de la firma del método que comienzan con @) para poder publicar un método como Servicio Web. Con esto nos quitamos de andar configurando los dichosos XMLs.
  • Scripting: Ahora se puede mezclar Java con tu lenguaje de scripting favorito. Antes conocimos algunos productos para combinar Java con otros lenguajes, pero ahora esto está soportado por la nueva plataforma. Podemos usar lenguajes como JavaScript, PHP, Python o Ruby. El objetivo es proveer a los desarrolladores de opciones tal vez más adecuadas para implementar ciertos algoritmos, no olvidemos que otros lenguajes tienen un gran manejo sobre cadenas y arreglos.
  • Base de Datos: El SDK 6 trae su manejador de bases de datos integrado, basado en Apache Derby. Particularmente útil cuando se quieren hacer aplicaciones pequeñas que necesitan una forma de persistencia para sus datos. No más MS Access cuando no se cuenta más que una PC de oficinista.
  • Acceso al Compilador: Ya era hora. Antes había que sufrir con clases y métodos sin documentación y a veces había que recurrir a la poderosa clase Runtime para acceder a javac via la consola.
  • Desempeño: Soy sólo yo, o ¿Java 6 es más rápido y consume menos memoria? Bueno, al menos eso he notado sobre Ubuntu.

Java 6 no trae tantos cambios como los hubo con Java 5, pero sin duda estas nuevas características hacen mejor y más fácil la experiencia de desarrollar con Java. Esperemos que esta lista sea de utilidad y que no me dé flojera con los posts prometidos, ja.

OpenLaszlo

May 24th, 2007

Ya que le di un espacio a JavaFX en mi humilde sitio, creo que lo más justo sería escribir un poco acerca de OpenLaszo. Antes que nada quisiera hacer notar algunas características claves:

  • El objetivo de OpenLaszlo es proveer a las aplicaciones basadas en Web de interfaces con las capacidades de un cliente de PC (aplicaciones standalone).
  • Los programas de OpenLaszlo se escriben en XML y JavaScript. El lenguajes es orientado a objetos, por lo que se pueden manejar bien las aplicaciones complejas.
  • OpenLaszlo provee una plataforma sobre la cual se pueden desarrollar aplicaciones dinámicas compatibles con la mayoría de los navegadores. No más preocupaciones de que IE siempre se sale de los estándares.
  • Por último, pero no menos importante. Los scripts de OpenLaszlo se pueden compilar a animaciones de Flash y, desde la reciente versión 4, a DHTML. Incluso aseguran que el lenguaje está lo suficientemente bien diseñado para generar cualquier tipo de formato como salida. Sólo hay que escribir el traductor (nada más :) ). Leer más »

Actualización: ¿A caso no se han enterado? El proyecto Beryl (como tal) ya está descontinuado, ahora Compiz y Beryl se están fusionando para dar lugar al proyecto Compiz Fusion. Por lo que he preparado un tutorial para instalar Compiz Fusion. Si no te interesa y solo quieres Beryl, este post te servirá

Si tienes una tarjeta gráfica ATI y quieres que tu Ubuntu no le pida nada al Windows Vista, sigue leyendo.

Como ya se habrán enterado después de un intento fallido por instalar Ubuntu Feisty Fawn sobre su potente tarjeta gráfica de penúltima generación, el controlador que el Ubuntu pretende instalar por defecto no funciona; por lo que ni siquiera podrán ver el ambiente gráfico normalito, ni siquiera en el Live CD.

Sin embargo, no todo está perdido. A continuación les presento un tutorial para instalar la última versión de Ubuntu con todo y Beryl.

Siguiendo los pasos de abajo logré instalar Ubuntu Feisty Fawn sobre una laptop Dell 6400 con tarjeta de video ATI X1400.

NOTA IMPORTANTE: Este tutorial fue compilado y traducido de estos sitios con pequeñas modificaciones mías. Todos los créditos se quedan con sus respectivos autores.

  1. Para la instalación usaremos el CD alterno de instalación. Lo puedes encontrar aquí. Bájate el que sea más apropiado de acuerdo al tipo de intalación que deseas tener. Lo más seguro es que necesites la versión Intel x86.
  2. Inicia tu computadora desde el CD que recién bajaste y selecciona la instalación en modo texto (la primera opción). Este modo de instalación es muy parecida a la forma que se usaba en Ubuntu 5.10 y anteriores.
  3. Completa la instalación y reinicia tu computadora. Leer más »