Adobe Flash: The misunderstood ugly guy

Almost everyone hates Flash, and the discontinuation of it’s mobile version was seen by many as a triumph.

Being a GNU/Linux user myself, I also suffered all those crappy versions, late releases and crazy development cycles. But, looking back and trying to be fair, I must acknowledge that the availability of a Flash player for the major operating systems has lowered the barrier for multiplatform development for many people, specially for independent companies. And I’m not talking only about embedded videos on websites, but also videogames (like Machinarium or VVVVVV) and applications. In some sense, Flash was more successful than Java at building bridges between platforms.

That said, the failure of Flash on mobile platforms is not surprising at all. Pride seems to be the favorite sin for Adobe. They were barely able to produce decent quality versions for non-mobile platforms, so it was pretty clear their development work force wasn’t strong enough to provide properly optimized versions for the more complex Android ecosystem.

Adobe rejected the option of freeing its Flash Player, while keeping Adobe Flash (the content creator) as a commercial product. Apparently, they feared publishing the source code of its player would make easier for its competitors to provide alternative editors. But competition is not a bad thing, as it usually enriches the ecosystem and increases the popularity of a product. And opening the player would have extended Flash to newer platforms, improved the quality of non-Windows versions, and reduced total development cost, giving them more chances to success on mobile platforms. Perhaps they would even won the favor of some other companies (namely Google), which would in turn embed support for Flash on their own products by themselves.

Adobe lost their big chance. Not even them understood the truly potential of their own product.

How Intel/AMD (inadvertently) fixed GNU Hurd

Last Friday, on Hurd’s IRC channel at freenode, we’ve accidentally noticed some machines were able to run certain operations on Hurd as KVM guest up to 10x faster than others. As antrik correctly guessed, this is the effect of Intel’s Extended Page Tables, which allow the guest operating system to deal with it’s own page faults. I suppose AMD’s Rapid Virtualization Indexing could have a similar effect, but I don’t have the hardware to be able to test it (please write to the mailing lists if you’ve been able to check it).

Since most people (including myself) are running Hurd in a virtualized environment, having the ability of taking advantage of this circumstance by moving to hardware with this technology supposes a great improvement, heavily reducing compilation times and increasing the interactivity of the entire system.

Let’s see an small example of the difference between running with and without EPT.

Running without EPT (modprove kvm-intel ept=0):
root@debian:~# dd if=/dev/zero of=/dev/null bs=256k count=1000
1000+0 records in
1000+0 records out
262144000 bytes (262 MB) copied, 2.08 s, 126 MB/s

And with EPT:
root@debian:~# dd if=/dev/zero of=/dev/null bs=256k count=1000
1000+0 records in
1000+0 records out
262144000 bytes (262 MB) copied, 0.23 s, 1.1 GB/s

I think there will be interesting times for GNU Hurd.

Sometimes, swap space still matters

Most modern, general purpose Operating Systems (OS), come with a full-fledged Virtual Memory (VM) system that generates the illusion of having more memory than the real amount installed in the machine. Whether this virtual memory is backed by real RAM, disk swap or it just isn’t backed by any physical device, is something up to the OS.
This way, you can reserve (though the man page of malloc() says allocate, when you know how it works behind the scenes, reserve sounds better) 2 GB of memory in a machine with only 1GB and no swap. Of course, if you try to use that amount memory within your application, the OS will have a hard time trying to make space for it to run (probably reaping file sytem caches and buffers), and at some point it will take the decision of either killing the process (like the OOM Killer of Linux) or refusing to provide more pages to the space of that process, causing this one to die with a segmentation fault.This ability of allowing the processes to reserve more memory than the amount physically available, is possible thanks to on-demand paging. This means that physical resources (in this case, memory pages) are not consumed by a process until it really access them:

#define SIZE 1024*1024*100

int main()
{
int i;
char *buf;

buf = (char *) malloc(SIZE);

/* At this point, memory usage on the OS shouldn't have changed considerably */

for (i=0; i<SIZE; ++i) {
buf[i] = 'A';
}

/* Now, free memory in the OS should have decreased by 100 MB */

free(buf);
}

Many applications take advantage of this feature, and reserve more memory than they really use in all their lifecycle (if this is a proper behavior or not, is something beyond the scope of this article). You can check this in your own UNIX OS by comparing the columns VIRT and RSS (or RES) of the top utility.

So, how much memory can be reserved?

This is something that depends entirely on the OS you’re running. But most of them calculate a “safe” value determined by the amount of RAM and the size of the disk swap. This is the case for Solaris, which goes even further by strictly limiting the amount of memory to be reserved to the sum of the RAM and the swap minus 1/8 of the first one.

What could happen if you configure a low amount of swap space? (A real world example and the motivation of this article)

This morning, in one of our OpenSolaris servers, we started to receive messages like this one: “WARNING: Sorry, no swap space to grow stack for pid …” In vmstat, theswap column (a misleading name, since it’s the amount of virtual memory available to be reserved, and not something strictly related to physical swap space) showed pretty low numbers (under 50MB) while the free column was telling us that there were over 14 GB of physical RAM available. How can this be possible?

This machine has 32 GB of RAM and only 512 MB of swap (the default size in OpenSolaris, my mistake). This means that the total amount of virtual memory available to be reserved is something around 30 GB. It provides CIFS service to the network with SAMBA, thus there’re lots of “smbd” processes running on it, and each process usually has a VIRT size of 40 MB, and a RSS of 20 MB. With 1000 processes, the required amount of physical memory would be a little under 20 GB (it fits in RAM), but the amount of virtual memory is something near 40 GB.

This way, when our system reached the limit of virtual memory (over 30GB), it still had more than 10 GB of real RAM available, but the OS refused to allow more reservations. And since there’s still plenty of free pages, the kernel doesn’t try to rebalance the size of it’s buffers, leaving you with and exhausted system with lots of free memory.

So, keep in mind: Even with lots of RAM installed in your server, sometimes, swap space still matters.

How device size affects disk performance in Linux (II)

I’ve just noticed that in a virtualized environment, where roundtrips are more expensive, read speed differences between a page-aligned partition and a non page-aligned one are even more noticeable:

Non-aligned partition (size in sectors: (41929649-63)+1=41929587):

none:~# fdisk -l -u /dev/sdb

Disk /dev/sdb: 21.4 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders, total 41943040 sectors
Units = sectors of 1 x 512 = 512 bytes
Disk identifier: 0x93dbf2be

Device Boot Start End Blocks Id System
/dev/sdb1 63 41929649 20964793+ 83 Linux

none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=0
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 3.80593 s, 27.6 MB/s

none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 3.82304 s, 27.4 MB/s

none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=200
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 3.83713 s, 27.3 MB/s

Page-aligned partition (size in sectors: (41929654-63)+1=41929592) :

none:~# fdisk -l -u /dev/sdb

Disk /dev/sdb: 21.4 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders, total 41943040 sectors
Units = sectors of 1 x 512 = 512 bytes
Disk identifier: 0x93dbf2be

Device Boot Start End Blocks Id System
/dev/sdb1 63 41929654 20964796 83 Linux

none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=0
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.618494 s, 170 MB/s

none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.582423 s, 180 MB/s

none:~# dd if=/dev/sdb1 of=/dev/null bs=1M count=100 skip=200
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.589081 s, 178 MB/s

NOTE: In both tests, the data is cached in the host (so there is no real I/O to disks but traffic through virtualization pipes), but clean in the guest.

How device size affects disk performance in Linux

While running some tests in a client’s environment, we’ve noticed reading from a partition of a multipath device was considerably slower than reading from its parent node:

[root@none]# dd if=mpath4 of=/dev/null bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 8.92711 seconds, 120 MB/s

[root@none]# dd if=mpath4p1 of=/dev/null bs=1M count=1024 skip=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 17.5965 seconds, 61.0 MB/s

We asked to client support of a well-known GNU+Linux vendor, and they indicated that this behavior was “expected”, since this kind of partitions were created by stacking adm-linear device over the original multipath node. I wasn’t satisfied by this answer, since AFAIK dm-linear only did a simple transposition of the original request over an specified offset (the beginning of the partition), so I decided to investigate a bit further on my own.

The first thing I’ve noticed, was that changing size of the dm-linear device affected the performance of the tests:

[root@none]# echo "0 1870000 linear 8:96 63" | dmsetup create test
[root@none]# dd if=/dev/mapper/test of=/dev/null bs=1M count=100 skip=600
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.906487 seconds, 116 MB/s

[root@none]# dmsetup remove test
[root@none]# echo "0 1870001 linear 8:96 63" | dmsetup create test
[root@none]# dd if=/dev/mapper/test of=/dev/null bs=1M count=100 skip=700
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 1.47716 seconds, 71.0 MB/s

This was something, but then I needed to find the reason of how a simple change in the device size could impact the performance this way. Playing around with kgdb (what a nice tool!), I’ve reached to this piece of code from Linux (drivers/md/dm.c):

static int __split_bio(struct mapped_device md, struct bio bio)
{
struct clone_info ci;
int error = 0;

ci.map = dm_get_table(md);
if (unlikely(!ci.map))
return -EIO;

ci.md = md;
ci.bio = bio;
ci.io = alloc_io(md);
ci.io->error = 0;
atomic_set(&ci.io->io_count, 1);
ci.io->bio = bio;
ci.io->md = md;
ci.sector = bio->bi_sector;
ci.sector_count = bio_sectors(bio);
ci.idx = bio->bi_idx;

start_io_acct(ci.io);
while (ci.sector_count && !error)
error = __clone_and_map(&ci);

dec_pending(ci.io, error);
dm_table_put(ci.map);

return 0;
}

In the debugging session, I’ve noticed that ci.sector_count takes the value ‘1’ for the device with worst performance, while other devices with different sizes and better read speeds could take values in a range from ‘2’ to ‘8’ (being the latter the case with best performance). So, indeed, the size of a device affects how is accessed, and this implies a noticeably difference in performance. But, still, it wasn’t clear for me where is the root of this behavior, so I decided to dig a bit deeper. That took me to this function (fs/block_dev.c):

void bd_set_size(struct block_device bdev, loff_t size)
{
unsigned bsize = bdev_logical_block_size(bdev);

bdev->bd_inode->i_size = size;
while (bsize < PAGE_CACHE_SIZE) {
if (size & bsize)
break;
bsize <<= 1;
}
bdev->bd_block_size = bsize;
bdev->bd_inode->i_blkbits = blksize_bits(bsize);
}

This function searches for the greatest power of 2 which is divisor of the device size in the range of 512 (sector size) to 4096 (the value for PAGE_CACHE_SIZE in x86), and sets it as the internal block size. Further direct requests to the device will be internally divided in chunks of this size, so devices with sizes that are multiple of 4096 will perform better than the ones which are multiple of 2048, 1024 or 512 (the worst case, which every device conforms as its the size of each sector). This is specially important in scenarios in which devices are directly accessed by the application, such as in Oracle’s ASM configurations.

TL;DR: Linux chooses the internal block size that will be used to fulfill page requests by searching the greatest power of 2 which is divisor of the device size in a range from 512 to 4096 (in x86), so creating your partitions with a size which is multiple of 4096 will help to obtain better performance in I/O disk operations.

DRM y Software Privativo van de la mano

Navegando por reddit, me he encontrado con esta entrada en la que un usuario se queja de que no puede reproducir un Blue-Ray legítimamente adquirido, ya que está utilizando como salida de vídeo una TV conectada al puerto HDMI de su portátil (un Macbook Pro).

En dicha entrada se comenta cómo los fabricantes se perjudican a sí mismos con este tipo de prácticas. Ciertamente es un aspecto a destacar, pero también es importante tener en cuenta que dichas prácticas no serían posibles sin que existiese cierto Software Privativo que haga efectivas las limitaciones artificiales impuestas por los fabricantes. Y donde hoy es impedir que se reproduzca un contenido si se visualiza en una TV sin HDCP, mañana podría ser cualquier otra prohibición igualmente ridícula y arbitraria.

Y es que este es uno de los principales motivos por los que Richard M. Stallman inició el proyecto GNU hace 25 años: impedir que los fabricantes tuvieran la capacidad de decidir sobre lo que el usuario puede o no hacer con su computadora. El Software Libre, como su propio nombre indica (al menos en su denominación castellana, más precisa que la anglosajona), trata sobre la libertad, y no sobre la gratuitidad, matización que con frecuencia se suele pasar por alto.

Si en atención a nuestra comodidad entramos en el jardín vallado que nos presentan y damos por buenas este tipo de prácticas (y entre ellas podemos incluir también modelos de distribución de software como el AppStore), le estamos dando vía libre a los fabricantes para que tomen el control de nuestros dipositivos y decidan por nosotros lo que podemos hacer con ellos. Y los peligros que esto entraña en una sociedad donde las TI están presentes a todos los niveles (y cada días más), son impredecibles.

Webs de administración y puertos redirigidos

Si trabajas administrando sistemas, es posible que te hayas encontrado en la tesitura de tener que acceder a la consola de administración de algún dispositivo a través de un túnel SSH, redirigiendo algún puerto de la máquina de destino a otro local. Al hacer esto, puedes encontrarte con la circunstancia de que la aplicación a la que estás accediendo tiene referencias estáticas a su IP real, lo cual provoca que no puedas acceder correctamente a ella.

Si este es tu caso, y estás utilizando GNU/Linux, puedes hacer uso de iptables para salvar el escollo. Por ejemplo con

iptables -t nat -A OUTPUT -p tcp --dport 9000 -j DNAT --to 127.0.0.1:9000

estaríamos redigiriendo todo el tráfico saliente hacia el puerto 9000, al mismo puerto en nuestra máquina local.

Recuerdos y predicciones

De pura casualidad, he encontrado una bitácora de Blogspot que abandoné a finales de 2005 (entonces tenía 21 años, ¡cómo pasa el tiempo!). Ciertamente, resulta curioso reencontrarse con le pasaba por la cabeza a uno en tiempos pretéritos. Entre las entradas que publiqué, que debo reconocer que no fueron muchas, hay una que me hace especial gracia. Trata sobre la burbuja inmobiliaria alrededor de un año antes de que explotara, por lo que he decidido rescatarla:

Política/Sociedad: Inversión inmobiliaria, un fraude legal

Mucho se ha hablado sobre el precio de la vivienda. Las viviendas de protección oficial, las “actuaciones”, los pisos de 30 metros cuadrados. Pero, esta vez, hablemos directamente sobre el propio negocio inmobiliario.

Veamos, un individuo adquiere un inmueble por una cantidad, y en un tiempo determinado la vende tal y como la compró, sacando un beneficio considerable de dicha operación. Pero para la obtención de ese beneficio, dicho individuo no ha producido, no ha generado nada. No ha utilizado mano de obra (o en todo caso mínima, haciendo un esfuerzo por incluir en este aspecto a las agencias inmobiliarias) ni ha comprado material alguno. El único beneficio que ha devuelto a la comunidad es el correspondiente a los impuestos y canones apropiados, una mínima parte.

Así pues, obtenemos un beneficio que nace de una producción nula. Por tanto, en última instancia, alguien debe sufragar ese gasto. Y creo que es evidente sobre quién recae dicha carga: los jóvenes en busca de su primera vivienda. Pagamos (pagaremos) a lo largo de nuestra vida los réditos obtenidos por los especuladores, mediante unas hipotecas que parecen cadenas perpetuas. Por supuesto los bancos están encantados de tomar parte en este banquete en el que los más pobres pagamos la cuenta.

Por otra parte, se está estirando mucho de una cuerda, que puede terminar de romperse. El equilibrio entre el poder adquisitivo de los nuevos compradores, y el precio de la vivienda agoniza. Los bancos flexibilizan cada día más la concesión de hipotecas para que el convite no cese (ya hemos dichos que son nuestros comensales, y además tienen un gran apetito), pero puede llegar un momento en que sea imposible financiar unos precios tan altos con unas nóminas tan escasas. Entonces, ¿el problema se solucionará por sí solo? No me atrevería a afirmar tal cosa. En ocasiones, cuando la tendencia del precio de la viviendia está a la baja, pueden producirse situaciones de bloqueo, en las que los especuladores prefieren no vender a perder la inversión. En cualquier caso, y mientras llega ese supuesto, se siguen firmando condenas perpetuas en forma de hipotecas cada día.

Un fraude económico del que miles de jóvenes, han sido, son y seremos víctimas, con la única esperanza (algunos) de aliviar nuestro peso pasando la carga a la siguiente generación de jóvenes.

Nacionalismo de Carril

Señores conciudadanos de Zaragoza,

Como todos sabemos, la ciudad está sufriendo multitud de remodelaciones repartidas por todo el núcleo urbano, que provocan ciertos inconvenientes a la hora de circular por el mismo. Es habitual encontrarse con calles parcial o completamente cortadas. En el segundo caso, hay poco que hacer. En el primero, todos los zaragozanos tenemos una tarea pendiente.

Y es que el hecho de que el carril de una calle se encuentre cortado, no implica que deba abandonarse su uso varios tramos antes del que se encuentra afectado. Por el contrario, aunque algunos no lo crean, es posible distribuirse por todos los carriles de la calle, incluso en el que termina cortado unos metros más adelante, y una vez alcanzado el tramo afectado, ir circulando de uno en uno cediéndonos el paso los unos a los otros, como si fuéramos personas civilizadas (sé que cuesta aparentar lo que uno no es, pero todo es cuestión de intentarlo).

Este método altamente sofisticado (como el sistema de refrigeración autónoma del botijo), permitiría aprovechar mejor los carriles de los tramos en obras, en lugar de la estrategia actual que los infrautiliza y genera colas interminables que se extienden varios cruces más atras (con lo cual entran en juego los semáforos, produciéndose un embotellamiento aún mayor).

Eso sí, queridos amigos, para llegar a este punto, existe una condición previa: abandonar el Nacionalismo de Carril. Y es que, en contra de lo que usted piensa, el carril por donde cirula no es suyo. El hecho de que usted llegara antes no sirve como“precedente histórico” que le otorgue la propiedad del mismo (aunque en vista de lo que sucede con algunos “Estatuts”, poco le falta) ni le permite cerrar sus fronteras a los“inmigrantes” que proceden de carriles fronterizos. Recuerde que, antes o después, será usted el que se desplace a otro carril en busca de reconducir su coche a nuevos destinos, y no deseará que se le trate con semejante desprecio.

Una vez superado este problema, podremos empezar a usar de forma eficiente los carriles y, de esta forma, hacer menos duro el largo periodo de obras que nos espera en Zaragoza. No es tan difícil, varios millones de madrileños lo llevan haciéndo desde hace años.

Linux: Bug in the nozomi driver

If you have a nozomi based 3G PCMCIA modem (like the Option models from Movistar Spain), you’ll probably noticed that, since kernel version 2.6.29, you can no longer establish an Internet connection with it. While it properly answers to AT commands, when the pppd daemon tries to talk to the other side, it simply hangs with no response.

If this is your case, you might be interested in taking a look at this bug (13024). Or, if you’re in a hurry (and somewhat brave ;-), you might want to try something like this:

--- nozomi.c.orig 2009-12-05 22:57:43.000000000 +0100
+++ nozomi.c 2009-12-05 22:57:54.000000000 +0100
@@ -1626,10 +1626,10 @@

dc->open_ttys--;
port->count--;
- tty_port_tty_set(port, NULL);

if (port->count == 0) {
DBG1("close: %d", nport->token_dl);
+ tty_port_tty_set(port, NULL);
spin_lock_irqsave(&dc->spin_mutex, flags);
dc->last_ier &= ~(nport->token_dl);
writew(dc->last_ier, dc->reg_ier);