Java String Parameterization - Performace loss on indirect toString methods

社会主义新天地 提交于 2019-12-24 04:31:05

问题


I've got a method like this:

private String getOrderListAsString() {
    StringBuilder str = new StringBuilder();
    str.append("Sell list:");
    for (Order o : sellOrderList) {
        str.append("\nSale: ").append(o);
    }
    str.append("Buy list:");
    for (Order o : buyOrderList) {
        str.append("\nBuy:  ").append(o);
    }
    return str.toString();
}

It's called with logging parameterization like so: We're using java.util.logging as a logger.

logger.log(Level.INFO, "{0}", getOrderListAsString());

The problem is that the string concatination is still being done even if the logger level is Level.OFF.
To get around this we've added an if statement at the start of the method:

// Declaration:
boolean shouldLog = DebugWriter.getInstance().getLogger().getLevel() != Level.OFF;
// Usage in function:
if(!shouldLog) return null;

But it feels like this could be done in a more clever way. Thanks in advance!


回答1:


If you are using Java 8+, then java.util.Logger has an overload of the log method that takes a Supplier

public void log(Level level,
            Supplier<String> msgSupplier)

Now, you can make the string generated from a supplier like

logger.log(Level.INFO, () -> getOrderListAsString());

or, using method reference

logger.log(Level.INFO, this::getOrderListAsString);

Javadoc




回答2:


java.util.logging has overloads that take Supplier<String> but not in combination with a format string. So you can use it like this:

logger.info(() -> getOrderListAsString());

Or create a new abstraction OrderList that has a toString() method. Then you can simply pass it as a parameter, and the logger will invoke toString(), if needed.




回答3:


Same spirit as Eran's answer, but just wrap the argument rather than change the log implementation

public class LazyToString
{
    private final Supplier<String> stringSupplier;

    public LazyToString(Supplier<String> stringSupplier)
    {
        this.stringSupplier = stringSupplier;
    }

    @Override
    public String toString()
    {
        return stringSupplier.get();
    }
}

Sample usage:

log.info("Something happened {}", new LazyToString(this::getOrderListAsString));

If that's too verbose, you can create a static method call which creates the object rather than using new, maybe would look something like this

log.info("Something happened {}", lazy(this::getOrderListAsString));


来源:https://stackoverflow.com/questions/59284520/java-string-parameterization-performace-loss-on-indirect-tostring-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!