Showing posts with label performance. Show all posts
Showing posts with label performance. Show all posts

2009-02-16

Java is faster than native


There is a myth that native is much faster than java. Lots of frameworks speculate this myth and using lots of native methods from java. But how often they are implementing same functionality and check native against true-java? They are often diving so deep in own fantasies about native performance that it is almost religion, they just don't accept facts. But how much it takes to JVM to invoke method from native library? And how much is it comparing to raw java interpretation?

I don't like to use things that I don't understand. Almost all methods from Math class is native, and I can't see sources of that classes. There are some functions that would be hard to implement, like Math.sin() or Math.cos(), but there are some easy-to-implement methods. This time I need functionality of method Math.pow(). It is not hard to implement it in java:

private double pow(double value, double pow) {
  double result = value;
  for (int i = 1; i < pow; i++) {
    result = result * value;
  }
  return result;
}

And it is not hard to implement some raw test using case from current developed application:

private static final int times = 1000000;
public static void main(String[] args) {
  // running test 10 times to "hotspot" it
  for (int i = 0; i < 10; i++) {
    // I know, I know, you can never
    // preallocate long, but I like it:
    long start = 0;
    long end = 0;
    start = System.currentTimeMillis();
    for (int j = 0; j < times; j++) {
      pow(10, 10);
    }
    end = System.currentTimeMillis();
    System.out.println("pow: " + (end - start));
    // cleaning JVM every time before next cycle:
    System.gc();
    System.runFinalization();
    System.gc();
    start = System.currentTimeMillis();
    for (int j = 0; j < times; j++) {
      Math.pow(10, 10);
    }
    end = System.currentTimeMillis();
    System.out.println("math: " + (end - start));
    System.gc();
    System.runFinalization();
    System.gc();
    // and running once more to be sure in hotspot:
    start = System.currentTimeMillis();
    for (int j = 0; j < times; j++) {
      pow(10, 10);
    }
    end = System.currentTimeMillis();
    System.out.println("pow: " + (end - start));
    System.gc();
    System.runFinalization();
    System.gc();
    start = System.currentTimeMillis();
    for (int j = 0; j < times; j++) {
      Math.pow(10, 10);
    }
    end = System.currentTimeMillis();
    System.out.println("math: " + (end - start));
    System.gc();
    System.runFinalization();
    System.gc();
  }
}


I just wanted to figure out how slow is my implementation, but results were totally unexpected!

run-single:
pow: 63
math: 797
pow: 78
math: 797
pow: 78
math: 781
pow: 78
math: 781
pow: 63
math: 781
pow: 63
math: 781
pow: 63
math: 797
pow: 63
math: 797
pow: 63
math: 797
pow: 63
math: 782

It's 10 times faster than Math.pow() when raising power of 10!!

Think different. Think faster!

2008-10-07

Comparing two collections


There is standard task when you have GUI table and database table, and you need to merge differences.
Most of people I know will do it like this:


Set source; // set of records from UI
Set target; // set of records in database
for (Object o : source) {
    // if we have object in source without
    // same object in target - it was added by user:
    if (!target.contains(o)) {
        target.add(o);
    }
}
Iterator iterator = target.iterator();
while (iterator.hasNext()) {
    Object o = iterator.next();
    // if we have object in target without
    // same object in source - it was removed by user:
    if (!source.contains(o)) {
        iterator.remove();
    }
}


We have 2 full collection iterations. In most cases it will not cause big performance issue. But it looks bad and will cause performance problems with slow Collection implementations or with big amounts of data.

After using my brain few minutes I found the best way of comparing, with only one iteration:


Set source; // set of records from UI
Set target; // set of records in database
// just checking:
if (target.equals(source)) {
    return;
}
Iterator iterator = target.iterator();
while (iterator.hasNext()) {
    Object o = iterator.next();
    if (source.contains(o)) {
        // remove all checked objects for future
        source.remove(o);
    }
    else {
        // if source does not contains object -
        // it was removed by user, removing it from target:
        iterator.remove();
    }
}
// all object left in source are added by user.
// Adding them to target:
target.addAll(source);


Simple enough, isn't it?

2008-03-24

Premature optimization is not THAT root of evil

Sometimes I can see really ugly code from my colleagues. Something like this:

ArrayList checkList = new ArrayList();
for (Item item : allItems) {
    if (item.isModified) {
        checkList.add(item);
    }
}
for (Item item : itemsList) {
    if (checkList.contains(item)) {
        doSomething(item);
    }
}


Yes, there are situations, where you need hacks like this. But why, why are they using ArrayList to perform contains checks? HashSet is created for this job, why not to use it? For 10 items you will not see speed problems. For 100 items speed will lose few millis. For 10000 item you will count seconds!
No! I will not do it like you want! Premature optimization is root of evil!

Do you see premature optimization here? For me it is just making use of proper tool, tool that created for this task. Don't you think so?