This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 271610 - Offer Supplier overloads for LoggerStringConcat fix
Summary: Offer Supplier overloads for LoggerStringConcat fix
Status: NEW
Alias: None
Product: java
Classification: Unclassified
Component: Hints (show other bugs)
Version: Dev
Hardware: PC Linux
: P3 normal with 1 vote (vote)
Assignee: Svata Dedic
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-10-09 22:19 UTC by Jesse Glick
Modified: 2017-11-23 01:44 UTC (History)
1 user (show)

See Also:
Issue Type: ENHANCEMENT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jesse Glick 2017-10-09 22:19:54 UTC
`LoggerStringConcat` currently offers to convert calls to `Logger` methods with overloads taking message formats. But Java 8 introduces more convenient overloads taking `Supplier<String>`. I tried the following very crude microbenchmark (yes, I know, YMMV and I ought to be using a proper framework):

import java.util.logging.Level;
import java.util.logging.Logger;
public class Demo {
    private static final Logger LOGGER = Logger.getLogger(Demo.class.getName());
    public static void main(String[] args) {
        String x = "whatever";
        int y = 99;
        for (int i = 0; i < 5; i++) {
            System.err.print("naïve 1: ");
            time(() -> LOGGER.fine("blah blah " + x));
            System.err.print("template 1: ");
            time(() -> LOGGER.log(Level.FINE, "blah blah {0}", x));
            System.err.print("supplier 1: ");
            time(() -> LOGGER.fine(() -> "blah blah " + x));
            System.err.print("naïve 2: ");
            time(() -> LOGGER.fine("blah blah " + x + y));
            System.err.print("template 2: ");
            time(() -> LOGGER.log(Level.FINE, "blah blah {0}", new Object[] {x + y}));
            System.err.print("supplier 2: ");
            time(() -> LOGGER.fine(() -> "blah blah " + x + y));
        }
    }
    static void time(Runnable r) {
        doTime(r, false);
        doTime(r, true);
    }
    static void doTime(Runnable r, boolean measure) {
        long start = System.nanoTime();
        for (int i = 0; i < 100_000_000; i++) {
            r.run();
        }
        long end = System.nanoTime();
        if (measure) {
            System.err.printf("took %.3fs%n", (end - start) / 1_000_000_000.0);
        }
    }
}

which for me using JDK 8u131 on Linux produced

naïve 1: took 1.487s
template 1: took 0.043s
supplier 1: took 0.357s
naïve 2: took 2.325s
template 2: took 2.064s
supplier 2: took 0.390s
naïve 1: took 1.615s
template 1: took 0.440s
supplier 1: took 0.362s
naïve 2: took 2.605s
template 2: took 2.020s
supplier 2: took 0.361s
naïve 1: took 1.783s
template 1: took 0.352s
supplier 1: took 0.359s
naïve 2: took 2.508s
template 2: took 2.132s
supplier 2: took 0.365s
naïve 1: took 1.864s
template 1: took 0.413s
supplier 1: took 0.428s
naïve 2: took 2.580s
template 2: took 2.174s
supplier 2: took 0.367s
naïve 1: took 1.854s
template 1: took 0.365s
supplier 1: took 0.368s
naïve 2: took 2.595s
template 2: took 2.154s
supplier 2: took 0.363s

My rough takeaway is that the `Supplier<String>` version is potentially slower on cold code for the one-argument case but may be faster for two (and I suppose more).

At any rate, it would be nice for the hint to offer to use the Java 8 version when the source level is 8+. Sometimes faster than the current fix, and almost always more readable.

If the order of fixes matters, I suppose I would recommend the 8 version first for 2+ args, though I think I have seen the editor just show all available fixes in a random order—perhaps timing-sensitive.
Comment 1 Jesse Glick 2017-10-10 15:29:03 UTC
…though any variables used must be effectively final.