Hi,

I just noticed a small optimization opportunity in URLStreamHandler.parseURL 
for inputs like the following:

        new URL(new URL("file:"), "file:./path/to/some/local.properties");

In those cases there is no authority involved, which makes it possible to 
rewrite URLStreamHandler:L269-270:
     
    String separator = (authority != null) ? "/" : "";
    path = separator + spec.substring(start, limit);

into the following to avoid unnecessary string concatenations with an empty 
string:

     path = spec.substring(start, limit);
     path = (authority != null) ? "/" + path : path;

I've written a small benchmark with two URLStreamHandler variants (one with the 
old parseURL and one with the new):

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {

    @State(Scope.Benchmark)
    public static class ThreadState {

        private URL context;
        private URLStreamHandler newHandler = new NewURLStreamHandler();
        private URLStreamHandler oldHandler = new OldURLStreamHandler();
        private String spec = "file:./path/to/some/application.properties";

        public ThreadState() {
            try {
                context = new URL("file:");
            } catch (MalformedURLException ignored) {

            }
        }
    }

    @Benchmark
    public URL testNew(ThreadState threadState) throws MalformedURLException {
        return new URL(threadState.context, threadState.spec, 
threadState.newHandler);
    }

    @Benchmark
    public URL testOld(ThreadState threadState) throws MalformedURLException {
        return new URL(threadState.context, threadState.spec, 
threadState.oldHandler);
    }

}

The benchmark above yields the following results on my local machine:

Benchmark                                             Mode  Cnt     Score    
Error   Units
MyBenchmark.testNew                                   avgt   10   112,655 ±  
3,494   ns/op
MyBenchmark.testNew:·gc.alloc.rate                    avgt   10  1299,558 ± 
41,238  MB/sec
MyBenchmark.testNew:·gc.alloc.rate.norm               avgt   10   192,015 ±  
0,003    B/op
MyBenchmark.testNew:·gc.count                         avgt   10    98,000       
    counts
MyBenchmark.testNew:·gc.time                          avgt   10   105,000       
        ms
MyBenchmark.testOld                                   avgt   10   128,592 ±  
1,183   ns/op
MyBenchmark.testOld:·gc.alloc.rate                    avgt   10  1612,743 ± 
15,792  MB/sec
MyBenchmark.testOld:·gc.alloc.rate.norm               avgt   10   272,019 ±  
0,001    B/op
MyBenchmark.testOld:·gc.count                         avgt   10   110,000       
    counts
MyBenchmark.testOld:·gc.time                          avgt   10   121,000       
        ms


In case you think this is worthwhile I would need someone to sponsor the 
attached patch for me.
I would highly appreciate that.

Cheers,
Christoph


===== PATCH =====
diff --git a/src/java.base/share/classes/java/net/URLStreamHandler.java 
b/src/java.base/share/classes/java/net/URLStreamHandler.java
--- a/src/java.base/share/classes/java/net/URLStreamHandler.java
+++ b/src/java.base/share/classes/java/net/URLStreamHandler.java
@@ -266,8 +266,8 @@
                          spec.substring(start, limit);

             } else {
-                String separator = (authority != null) ? "/" : "";
-                path = separator + spec.substring(start, limit);
+                path = spec.substring(start, limit);
+                path = (authority != null) ? "/" + path : path;
             }
         } else if (queryOnly && path != null) {
             int ind = path.lastIndexOf('/');


Reply via email to