viernes, 26 de agosto de 2011

java String.substring() y la memoria perdida

Hay cosas horribles e incomprensibles en java.

La ultima con la que me he topado ha sido un OutOfMemoryException al parsear un archivo de texto...

Me he puesto a analizar el dump de la pila de la JVM con el plugging de eclipse Memory Analizer y que gran sorpresa al ver que había un montón de strings de varios megas de tamaño....

Así que me he dispuesto a mirar el código y por alguna extraña razón me ha olido mal String.substring() y me he puesto a ver si era el problema: Todas mis sospechas, TODAS mis sospechas se han hecho realidad. En resumida cuentas, la documentación oficial de oracle dice:

public String substring(int beginIndex,
int endIndex)

Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.

Examples:

"hamburger".substring(4, 8) returns "urge"
"smiles".substring(1, 5) returns "mile"


Parameters:
beginIndex - the beginning index, inclusive.
endIndex - the ending index, exclusive.
Returns:
the specified substring.

Y 'MIENTE'. Parece ser que String tiene, aparte de la cadena de caracteres, unos índices de inicio y de fin de cadena que inicialmente están a 0 y String.length() respectivamente. El problema es que lo que hace substring NO es devolver un nuevo String sino una copia de el mismo string moviendo los dos indices: el 0 a beginindex y el final a finalindex. Me explico: el objeto en si es nuevo, pero apunta al mismo char[] interno, con lo cual si hacemos un substring de un caracter nos quedamos con TODO el contenido del string original en memoria...

Con lo cual cada vez que haces un String.substring tienes como resultado en memoria de la String original. Esto tal vez no sea mucho problema habitualmente pero si la cadena es larga y tienes que tratarla facilmente te supondrá un programa de memoria y de rendimiento importante.


Por ejemplo, imagina que buscaras una palabra de cada linea de un gran archivo de texto: meterias todas las lineas del archivo en memoria lo cual te puede dar un OutOfMemoryException.

Evitarlo es bastante sencillo, basta con sustituir:

String subs = str.substring(init,end);

Por:

String subs = new String(str.substring(init,end));

De este modo crea una nueva copia del String copiando el texto del substring en un nuevo char[].

Pero bueno, es algo a tener bastante en cuenta porque aparte de con substring también puedes tener problemas cuando la JVM utilice internamente substring lo cual ocurre, por ejemplo, en:

String.split(pattern)

Y al obtener grupos de regex.

Lo dicho: mucho ojo con los Strings.

jueves, 11 de agosto de 2011

Configurando Redmine para usar GMail para enviar y recibir correos

Esto permite que desde redmain se envien notificaciones sobre modificaciones en peticiones y tal.


Para hacerlo primero hay que instalar el plugin Action Mailer.


IMPORTANTE: Se hace desde la consola (desde el directorio de redmine, en mi caso /usr/share/redmine)


ruby script/plugin install http://svn.douglasfshearer.com/rails/plugins/action_mailer_optional_tls

ACT: ese servidor ya no esta, usar este:


sudo ruby script/plugin install git://github.com/collectiveidea/action_mailer_optional_tls.git


En el directorio de instalación de redmine. Es necesario que este GIT instalado, sino dara un error silencioso COMPLICADO de ver.


IMPORTANTE: Luego se crea/modifica un archivo en /etc/redmine/default/email.yml y se le da el siguiente contenido, se han perdido los espacios al escribirlo pero, como en python, smtp_settings es una seccion, a partir de el tiene que llevar todo 2 espacios de tabulacion hasta el siguiente bloque:


production:
delivery_method: :smtp
smtp_settings:
address: "smtp.gmail.com"
port: "587"
domain: "dominio-en-google-apps.com"
authentication: :login
user_name: "usuario@dominio-en-google-apps.com"
password: "contraseña"
tls: true

development:
delivery_method: :smtp
smtp_settings:
  address: 127.0.0.1
  port: 25
  domain: example.net
  authentication: :login
  user_name: redmine@example.net
  password: redmine

Y se configura el redmine desde la administracion- >settings y tal...


Lo de "importante" es pq en todos los manuales que he visto por internet dicen que hay que poner este .yml en [directorio de redmine]/config y a mi no me funciona si lo pongo alli.

Con esto ya esta. Le das a probar o a que mande correitos y veras, como poco, que van apareciendo en tu carpeta de enviados. Para que le lleguen a gente tienen que configurar que les lleguen emails de modificaciones de otros y tal.. ya es tema de gestion... de hacer click y eso es algo que no voy a explicar pq:

Real men don't click

martes, 9 de agosto de 2011

Montando unidad en red en ubuntu

Tenia un disco duro que al que solo se accedia por comparticion de archivos...

He encontrado esta pagina, que copio aqui, con la solucion, por si desaparece.

http://www.ubuntu-es.org/node/129291

Hay que tener en cuenta que al ser // se usa una IP
#Iomega.
//10.0.100.221/alf_data /media/alf_data cifs auto,rw,user=,password=,uid=1000,gid=0 0 0

//10.0.100.221/alf_data ---> IP y carpeta de la unidad que vamos a montar.
/media/alf_data ---> Punto de montaje.
cifs ---> Utilizar este tipo de sistema de archivos, en lugar de smb. Acrónimo de Common Internet File System.
Opciones:
auto ---> Montaje automático en el arranque.
rw ---> Lectura/Escritura.
En mi caso, para acceder a la unidad de red, hay que indicarle un usuario y un password.
user ---> Usuario.
password ---> clave usuario.
uid ---> Poner el UID correspondiente al usuario que queremos que sea el propietario de la unidad montada.
gid ---> Poner el GID correspondiente al grupo que queremos que sea el propietario de la unidad montada.

viernes, 25 de marzo de 2011

Again here

Well, I've been busy with the university (UNED) and I've let the blog dieing  of malnutrition.

Anyhow I've done some interesting things recently:

In my job, I've change a script that I had that did the same basic work that the command 'wget' : downloads something from internet. Now it can send cookies and parameters via GET (and post, but this is untested). It works great to test changes in web applications in IT's... I'll put the code here soon.

In the game: I'm redoing (again) the GUI, now is a more consistent idea and I'm doing a protocol to connect clients to the server.

Soon they'll be news