Blog jubilado de Paco Ros

Fue bonito mientras duró

Archive for the ‘Java’ Category

Concatenando Strings en Java

Posted by Paco Ros en 4 \04\UTC marzo \04\UTC 2007

Es un truco muy conocido y lo recuerdan en esta entrada de javaHispano.

Cuando se usa el operador “+” con dos instancias de String, el compilador, lo que hace es sustituir la operación por la creación de un StringBuffer.

En el ejemplo del artículo aparecen estos dos fragmentos de código:

// Caso ineficiente (pero típico)
long start = System.currentTimeMillis();
String str = "";
for(int i = 0; i < 10000; i++)
str += i;
System.out.println((System.currentTimeMillis() - start) / 1000.0d);

// Caso eficiente
start = System.currentTimeMillis();
StringBuffer strb = new StringBuffer();
for(int i = 0; i < 10000; i++)
strb.append( i );
System.out.println((System.currentTimeMillis() - start) / 1000.0d);

En el primer fragmento de código, el compilador sustituye el contenido del bucle con un código similar al siguiente:

for (int i=0; i<10000; i++){
    StringBuffer sb = new StringBuffer(str);
    sb.append(i);
    String straux = sb.toString();
    str = sb.toString();
}

A cada iteración se debe ubicar en memoria un nuevo objeto y ese objeto tiene un tamaño cada vez mayor.
La creación dinámica de memoria es una de las operaciones más costosas en Java (y en la mayoría de lenguajes que conozco) y la creación de 10000 instancias de StringBuffer hace que el mismo código resulte mucho más lento.

Ejecutando el código comparativo en mi portátil obtengo 3.277s para ejecutar el bucle con la versión ineficiente y 0.004s en la versión eficiente.

Podéis comprobarlo personalmente copiando y pegando este codigo:

public class Test{
        public static void main(String[] args){
                long start;
                String str;
                StringBuffer strb;

                // Usando el operador "+"
                str = "";
                start = System.currentTimeMillis();
                for(int i = 0; i < 10000; i++) str += i;
                System.out.println((System.currentTimeMillis() - start) / 1000.0d);

                // Usando una instancia de StringBuffer y el método append()
                strb = new StringBuffer();
                start = System.currentTimeMillis();
                for(int i = 0; i < 10000; i++) strb.append(i);
                System.out.println((System.currentTimeMillis() - start) / 1000.0d);

                // Reroducción de lo que hace el compilador en el caso 1
                str = "";
                start = System.currentTimeMillis();
                for (int i=0; i<10000; i++){
                        StringBuffer sbaux = new StringBuffer();
                        sbaux.append(str);
                        sbaux.append(i);
                        String straux = sbaux.toString();
                        str = straux;
                }
                System.out.println((System.currentTimeMillis() - start) / 1000.0d);
        }
}

Posted in Java | 4 Comments »

JSR-310 Date and Time aprobado

Posted by Paco Ros en 16 \16\UTC febrero \16\UTC 2007

Lo veo en javaHispano y en theServerSide. Parece que por fin se incluirá en la JDK una manera correcta y a la vez cómoda de trabajar con fechas.

La clase GregorianCalendar es extremadamente potente, pero inicializar una instancia correctamente, puede necesitar hasta unas 10 líneas de código. Ni que decir tiene que una aplicación (como la última en la que estoy trabajando) que haga un uso intensivo de fechas y horas así como incrementos y comparaciones sobre los mismos, se puede volver muy pesada.

El hecho de que se vaya o no a incluir una nueva feature en la próxima (o ya veremos cuál) JDK no me preocupa demasiado. Lo que sí que me ha gustado y mucho es el enlace a JodaTime. Una API para trabajar con fechas y horas en Java que tiene cosas tan chulas como esta:

public boolean isAfterPayDay(DateTime datetime) {
  if (datetime.getMonthOfYear() == 2) {
    return datetime.getDayOfMonth() > 26;
  }
  return datetime.getDayOfMonth() > 28;
}

public Days daysToNewYear(LocalDate fromDate) {
  LocalDate newYear = fromDate.plusYears(1).withDayOfYear(1);
  return Days.daysBetween(fromDate, newYear);
}

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = new Period().withDays(2).withHours(12);
  return datetimeRented.plus(rentalPeriod).isBeforeNow();
}

public String getBirthMonthText(LocalDate dateOfBirth) {
  return dateOfBirth.monthOfYear().getAsText(Locale.ENGLISH);
}

Si tenéis que programar algo que haga uso de fechas y horas más allá del new Timestamp() os recomiendo que no os perdáis JodaTime.

Por cierto, inauguré hace poco la sección Java. Llevo como 8 años trabajando en Java y JEE y hasta ahora no había escrito prácticamente nada sobre java principalmente por su licencia. Ahora, GPL, me ha animado a publicar alguna que otra cosilla :-)

Si tenéis alguna curiosidad al respecto u os interesa un artículo sobre algún tema pedid y me lo planteo.

Posted in Java, Software | 2 Comments »

Benchmark Java (JDBC) contra varios gestores de bases de datos

Posted by Paco Ros en 15 \15\UTC febrero \15\UTC 2007

Los chicos de devloop se han trabajado un extenso y detallado benchmark de varias bases de datos accedidas desde Java vía JDBC.

Además, han probado con varias VMs y con multitud de casos posibles: tablas llenas, vacías, threads, sin threads, threads con delay…

Los claros vencedores son MySQL y PostgreSQL y no han incluido Oracle porque, según explican, tiene problemas para conseguir una instalación limpia en la Fedora x86-64 que usan.

Llaman la atención algunos casos atípicos y situaciones inexplicables que tienen muy mal rendimiento en general, como por ejemplo que un select count(*) sobre una tabla vacía es más lento que sobre una llena.

También es relevante la diferencia entre el uso de Statement y PreparedStatement y cómo algunos gestores mejoran dramáticamente su rendimiento.
Por último, las mejoras (¡por fin!) de JDBC en la versión 6 de la JDK pasan factura a la hora de evaluar el rendimiento.

De lectura obligatoria si desarrollais usando JDBC ;-)

Posted in Java, Software | 3 Comments »