URLStreamHandler.getHostAddress() performance

Pavel Rappo pavel.rappo at oracle.com
Tue Nov 25 13:51:09 UTC 2014


Max, this change dates back to 99/06/11. And there's not much info left on it. I suggest changing and running the full test suit.

P.S. I assume the whole synchronization burden in the URL comes from lazy initialization of hostAddress and lazy computation of the hashCode (...and access to shared handlers, but that's guarded by different lock and thus of no interest to us right now). Without the 'hostAddress' the whole object could've been immutable (given the handler code is ALWAYS executed in the same thread as constructor, which is hard natural and it's hard to imagine the opposite).

-Pavel

> On 25 Nov 2014, at 12:58, Wang Weijun <weijun.wang at oracle.com> wrote:
> 
> 
>> On Nov 25, 2014, at 20:25, Pavel Rappo <pavel.rappo at oracle.com> wrote:
>> 
>> Hi Max,
>> 
>> I don't see any particular reason for this. Maybe it's just a "precaution". It seems to me it's the only field
>> of the URL class set directly (without setter) from an outside.
>> 
>> Does it hurt performance a lot? In what cases?
> 
> There is a 7x difference in my experiment on SecureClassLoader.defineClass().
> 
> Or, it can be shown using this benchmark:
> 
> package org.openjdk.bench;
> 
> import org.openjdk.jmh.annotations.*;
> 
> import java.io.IOException;
> import java.net.URL;
> import java.util.*;
> import java.util.concurrent.ConcurrentHashMap;
> 
> @State(Scope.Benchmark)
> public class Weird {
>    final int num = 100;
>    final Object[] urls = new Object[num];
> 
>    public static class CS {
>        private final Object url;
>        public CS(Object url) { this.url = url; }
>        public int hashCode() { return url.hashCode(); }
>        public boolean equals(Object o) { return o instanceof CS && url.equals(((CS)o).url); }
>    }
> 
>    private final Map<Object, Object> pdcacheC = new ConcurrentHashMap<>();
> 
>    @Setup
>    public void init() throws Exception {
>        for (int i=0; i< num; i++) {
>            urls[i] = new URL("file:/tmp/"+i);
>        }
>    }
> 
>    @State(Scope.Thread)
>    public static class ThreadState {
>        final Random rand = new Random();
>    }
> 
> 
>    @Benchmark
>    public void setC(ThreadState state) throws IOException {
>        Object cs = new CS(urls[next(state)]);
>        pdcacheC.computeIfAbsent(cs, x -> "");
>    }
> 
>    private int next(ThreadState state) {
>        return state.rand.nextInt(num);
>    }
> }
> 
> --Max
> 
> 
>> -Pavel
>> 
>>> On 25 Nov 2014, at 12:02, Wang Weijun <weijun.wang at oracle.com> wrote:
>>> 
>>> I am benchmarking security manager and notice this
>>> 
>>> protected synchronized InetAddress getHostAddress(URL u) {
>>>  if (u.hostAddress != null)
>>>      return u.hostAddress;
>>> 
>>>  String host = u.getHost();
>>>  if (host == null || host.equals("")) {
>>>      return null;
>>>  } else {
>>>      try {
>>>          u.hostAddress = InetAddress.getByName(host);
>>>      } catch (UnknownHostException ex) {
>>>          return null;
>>>      } catch (SecurityException se) {
>>>          return null;
>>>      }
>>>  }
>>>  return u.hostAddress;
>>> }
>>> 
>>> Is there any reason why the method is synchronized? Why not simply "synchronized (u)"?
>>> 
>>> Thanks
>>> Max
>>> 
>> 
> 



More information about the net-dev mailing list