Pages

Wednesday, March 5, 2014

Specifying the size for StringBuilder (jmh)

Several years ago I started doing some microbenchmarks. I don't think that I really progressed since than, but at least some errors became obvious. So I decided to take one of my old benchmarks and reimplement it using the JVM library. Here are the results that I got:

Benchmark                                    Mode   Samples         Mean   Mean error    Units
c.s.m.j.StringBuilderSize.expandingSize      avgt        15     7566.477      374.611    ns/op
c.s.m.j.StringBuilderSize.predefinedSize     avgt        15     5640.386      133.672    ns/op


And here is the code for it. (I have also posted some other jmh-based benchmarks in that repo).

Sunday, February 23, 2014

Freemarker loading taglibs from classpath

It is pretty common problem to try using various jsp taglibs from freemarker templates[1][2][3][4]. There is some support for this in freemarker, but this support is a bit ugly - it requires dancing with jar files like placing them in WEB-INF/lib folder and there is no easy way to use taglibs just from the classpath. At least - there was no such an easy way. After a day of debugging and investigation I figured the solution that works pretty good for me. The key is to override just the two methods in the ServletContext that is used by freemarker TagLibFactory. To do this I used standard dynamic proxy, but other solutions are possible two. After this taglibs can be referenced by their paths in the classpath - like:

<#assign security=JspTaglibs["/META-INF/security.tld"] />

for spring-security taglib instead of the usual

<#assign security=JspTaglibs["http://www.springframework.org/security/tags"] />

And the InvocationHandler that can be used to create the proxy for the ServletContext is here:

package com.sopovs.moradanen;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import javax.servlet.ServletContext;


public class ServletContextResourceHandler implements InvocationHandler {
    private final ServletContext target;

    private ServletContextResourceHandler(ServletContext target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("getResourceAsStream".equals(method.getName())) {
            Object result = method.invoke(target, args);
            if (result == null) {
                result = ServletContextResourceHandler.class.getResourceAsStream((String) args[0]);
            }
            return result;
        } else if ("getResource".equals(method.getName())) {
            Object result = method.invoke(target, args);
            if (result == null) {
                result = ServletContextResourceHandler.class.getResource((String) args[0]);
            }
            return result;
        }

        return method.invoke(target, args);
    }
}

And the complete solution can be found in my pet-project here.

Sunday, February 16, 2014

System.arraycopy versus simple copy in a loop

Programming in Java daily I rarely need to use arrays. But sometimes this happens and even more often I trap into reading libraries code that heavily use arrays. So proper working with them is the real question for me. And recently I stumbled upon a code that used plain loops for copying values from one array to the other. So I decided to check whether this is viable option when we have System.arraycopy method. I wrote a simple benchmark using excellent JMH library.

And so what I have got as a result:


Benchmark                        Mode   Samples         Mean   Mean error    Units
c.s.m.j.ArrayCopy.loopcopy       avgt        15        1.463        0.160    ms/op
c.s.m.j.ArrayCopy.systemcopy     avgt        15        1.457        0.112    ms/op
c.s.m.j.ArrayCopy.loopcopy     sample     10322        1.450        0.018    ms/op
c.s.m.j.ArrayCopy.systemcopy   sample     11071        1.351        0.013    ms/op
c.s.m.j.ArrayCopy.loopcopy         ss        15        1.653        0.925       ms
c.s.m.j.ArrayCopy.systemcopy       ss        15        1.657        0.788       ms


So there is no real difference in hand-written loop and using native method. But I really doubt that even with these results we should ever prefer hand-written loop instead of System.arraycopy native method. Here is a short list of ad-hock parameters that may come into play:

  • Different CPU. I used the most powerful current desktop CPU for running by benchmark. Your code may be run on very different CPU with very different result - maybe even on differnt architecture. Who knows - maybe in just several years the major part of java application servers will be run on ARM-servers.
  • Different hardware cache usage. It is no doubt that System.arraycopy is optimized for the proper usage of CPU caches and not interfering with the other code running on the same CPU concurrently. For the loop - you cannot be absolutely sure.
  • Different JVM implementation. With only three major JVM-implementations currently - OpenJDK (but again - I doubt that ARM-version can be called absolutely the same JVM in this specific context), IBM J9 and Dalvik (not a JVM actually, but your library that uses arrays can easily get to running on it) - you cannot be sure in the JIT already. But also there are other JVMs, like Azul Zing, Azul Zuzu, Excelsior JET and many others.
So, nonetheless that I was not able to observe any difference in running hand-written loop and native built-in arraycopy method - I prefer the latter.