Número 29
12 de outubro de 2022

A optimización prematura

Dános moita rabia cando utilizamos un ordenador e o programa vai lento ou ocupa moita memoria ou moito espazo no disco. Naturalmente, cando escribimos os nosos propios programas, seguimos pensando o mesmo e non queremos que estes programas convertan o ordenador nunha tartaruga xigante.

Querer que os nosos programas vaian lixeiros é unha posición digna de louvanza, pero é moi doado que o noso afán por optimizar nos cause problemas. Cando tratamos de optimizar o noso software hai que ter moito tino — e uso esta expresión da que gosto tan pouco para que vos quede claro o importante que é.

Debuxo dun home montado nun monociclo dotado dun parasol e moitos adornos e repinicos.

Para optimizar un programa, normalmente é necesario utilizar algoritmos e estruturas de datos máis complicados que nun programa “normal”. Ao aumentar o nivel de complicación, faise máis difícil entender como funciona o programa e é máis probable introducir un erro sen se decatar un.

Unha consecuencia relacionada con isto é que cando temos que facer cambios nun programa optimizado case sempre resulta ser máis difícil que nun programa sen optimizar. Ademais, moitas optimizacións dependen de que se cumpran certas suposicións; se esas suposicións cambian ou están erradas, pode ser moi difícil corrixir o programa. Pensade en toda esa xente que tivo que modificar case todo o software do mundo cando resultou que os anos precisaban de máis de dúas cifras.

Donald Knuth dixo unha vez que “a optimización prematura é a raíz de todos os males”. É unha frase un pouco dramática, pero no fondo tiña razón. Non tentedes escribir o programa óptimo de boas a primeiras. Comezade cun programa “normal”, doado de escribir e de entender, e mirade se vai ben dabondo para as vosas necesidades. Se tedes sorte, xa podedes parar aí. Se non, estudade en que partes do programa ides sacar os maiores beneficios ao optimizalas e concentrade o voso esforzo aí.

O principal á hora de facer optimizacións é medir, medir e medir outra vez. Non fagades optimizacións guiados só pola vosa intuición, senón polos fríos números. Usade “profilers” para saber en que partes do programa se usa máis tempo, máis memoria e máis disco, e con iso saberedes onde concentrarvos: optimizade a función que se executa durante 3 horas, non a que se executa durante 3 milisegundos.

A outra razón para medir é saber se o voso esforzo está a dar o resultado que esperades. Podedes pasar o día enteiro substituíndo algoritmos O(n²) por algoritmos O(1) a cegas e acabar cun programa que funciona moitísimo peor. Incluso se reducides o número de instrucións máquina no programa compilado non ides ter nin idea, sen o medir, de se o programa funciona máis rápido ou máis lento.

(Nos anos 80, os microprocesadores tiñan táboas co número de ciclos nos que se executaba cada instrución. Os programadores podían facer unha suma e saber canto tempo ía tardar o seu código en executarse. Hoxe en día, o número de ciclos de cada instrución pode variar dependendo de onde están os datos na memoria ou que outros programas se están a executar ao mesmo tempo.)

Polo tanto, cando optimicedes, medide. Despois facede un cambio e medide outra vez. E seguide así ata que alcancedes o resultado que buscabades. E, xa que estamos, outro consello: conservade unha versión do voso código sen optimizar. Se precisades de facer cambios, moitas veces é máis doado facer os cambios na versión “limpa” e despois optimizala outra vez que tratar de facer cambios na versión xa optimizada.

A ilustración desta Folla procede da patente estadounidense número 325548.