Deferred Evaluation of Arguments

We have used a Logger (I think it was Log4J) which claimed to work fast but the main performance fault was composition of messages. It would be useful to evaluate a message only if it will be logged and omit the construction if severity level is set low. What would be a simple synthax to organize this? In my example, there is a multiplexer which mimics a ternary operator. Only that value of the MUX is evaluated which passes to the output.

1. Is there a simple construction cos writing new Expr() {public Object eval() {procedure text}} every time is bulky.

2. How do the classes nested into a method are impemented? Particularily, how do theeval methods ofnew Expr() see the local variablei? Do they have a reference tomain's stack frame? I'm considering application of this technique in Delphi.

publicclass DeferredEvaluator{

interface Expr{

public Object eval();

}

static Object mux(boolean sel, Expr i0, Expr i1){

return sel ? i1.eval() : i0.eval();

}

publicstaticvoid main(String[] args){

finalint i = 0;

final BufferedReader br =new BufferedReader(new InputStreamReader(System.in));

System.out.println(

mux(true,new Expr(){public Object eval(){return"abc";}},new Expr(){public Object eval(){

try{

return br.readLine() +", i = " + i;

}catch(IOException e){return e +", i = " + i;}

}

}));

}

}

[2875 byte] By [valjok] at [2007-9-30 22:13:12]
# 1
I'm sure it is a simple question. Anybody knows of the nested method implementation details?
valjok at 2007-7-7 11:26:20 > top of Java-index,Java Essentials,Java Programming...
# 2

Hi,

Why don't use the isXXXXEnabled methods in the logger? They are there just for this kind of situations.. I always use them if I'm about to log something that is expensive to evaluate:

if (logger.isDebugEnabled()) {

logger.debug(expressionThatIsExpensiveToEvaluate);

}

/Kaj

kajbj at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 3

ifs impley redundancy as you see. You have every time to write if shmth then rather just calling a function which automates the task of checking the condition. So, I'm looking for something better than macros (asking for them I will be immediately kicked off this forum, I suppose) that would do the trick. My example above suffers from the same problem -- the Expr object permanent construction pattern is repeatedly Copy&Pasted allover the text aggraved by fact that the instantiation per se has a performance penaly.

As I have refreshed my knowledge on the nested classes instantion, I remembered the answer on the second question.

valjok at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 4
The if statements are not macros, they are called every time.Do a profile of your application. You should find the if statements don't significantly add to your CPU. No point worring about a problem which does not exist.
Peter-Lawrey at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 5
I'm not sure how the Expr interface is preferrable. Using an if statement gives the exact result required and is simple enough.
dubwai at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 6

I repeat. Repeatedly writing if allover the text is redundant, hence bulky. Programming is automation and reuse as I understand it. For the same reason, I do not like Copy&Paste in my programming practice. I've never told that the macros generated ifs are faster at runtime or allow for smaller memory footprint as they automate code generation and code is inlined before compilation but the unrolling is automatic Copy&Paste which saves my time, minimizes my mistakes and makes the code more transparent. I know about debugging troubles caused by the macros and interested to find a technique which whould enable the feature without the macros-inherent drawbacks.

valjok at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 7

If you have loads of ifs all over your code then you have too many log lines. If you cannot stand them in you code are you going to read the output it generates.

If you keep the logs to a minimum and use if's you won't have a problem. If you need debugging you should try to use the debugger more.

Peter-Lawrey at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 8

> I repeat. Repeatedly writing if allover the

> text is redundant, hence bulky.

How is 'if (LOGGER.isXXXEnabled())' more bulky and redundant than creating inner classes all over the place?

> Programming is

> automation and reuse as I understand it. For the same

> reason, I do not like Copy&Paste in my programming

> practice.

If I have to use your Expr interface, I would copy and paste. I don't copy and paste 'if (LOGGER.isDebugEnabled())' I type it with the help of auto-complete.

> I've never told that the macros generated

> ifs are faster at runtime or allow for smaller

> memory footprint as they automate code generation and

> code is inlined before compilation but the unrolling

> is automatic Copy&Paste which saves my time, minimizes

> my mistakes and makes the code more transparent.

You think that the copd you've posted above is more transparent than an if statement?

> I know about debugging troubles caused by the macros and

> interested to find a technique which whould enable the

> feature without the macros-inherent drawbacks.

What feature are you looking for, exactly?

dubwai at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 9
> What feature are you looking for, exactly?Deferred evaluation of arguments. Typically, all the arguments are evaluated before passed to a function. Sometimes they are ignored. I wonder why the programming languages do have another mechanism for parameter passing.
valjok at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 10

Presumably the OP wants something like printf, where the logger would actually build the string, so that

a) you don't build the string if you're not going to log

and

b) you don't have to put an explicit if in your code to accomplish the above.

I've occasionally wished for the same thing. I hate having those explicit ifs in the code. However, once I came to my senses, I realized that the number of cases where building the string really makes a performance difference are few and far between (for me anyway) so it wasn't a big deal to throw in the handful of ifs needed.

I believe that 5.0 supports printf or something like it, and if not, then I'm pretty sure there are 3rd party packages out there. Use a Decorator Pattern. Create your own logger that does the if test and then either parses the format & strings, and then delegates to the real logger, or else just returns if the threshold isn't met.

jverd at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 11

yep, indeed version 1.5 has a printf style string formatting. It is possible because of the varargs

sugar that was added to 1.5. However if you look under the hood varargs is implemented using an object array. You can do this yourself if you wish.

myLogger.log(new Object[] = {"hello", "there", variable,"etc"});

Not particularly nasty.

matfud

matfud at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 12

> Deferred evaluation of arguments. Typically, all the

> arguments are evaluated before passed to a function.

> Sometimes they are ignored. I wonder why the

> programming languages do have another mechanism for

> parameter passing.

Defered evaluation is usually more expensive in overhead than the time it saves. It often adds complexity in a way which is poorly understood by more programmers and thus is not easy to maintain.

I like lazy evaluation personally, but unless you are dealing with an operation with a very significant overhead you battling to come up with a good real world example of when to use this technique.

Peter-Lawrey at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 13

In addition I have often noticed that a poorly configured logger causes more performance impact

then evaluating the parameters. Be very careful about the way you configure your logger or each

time you call the log method the logger will throw an exception, catch it and determine the location it was called from by parsing the resulting stack trace. This is horendously expensive.

matfud at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 14

Actaully it creates a Throwable and then converts it to a string without actaully throw/catching it.

I use this trick from time to time my self.

LOG.log("here", new Throwable());

prints out a full stack dump of where it is. An Exception does not need to be thrown to be useful.

Peter-Lawrey at 2007-7-7 11:26:21 > top of Java-index,Java Essentials,Java Programming...
# 15

> yep, indeed version 1.5 has a printf style string

> formatting. It is possible because of the varargs

> sugar that was added to 1.5. However if you look under

> the hood varargs is implemented using an object array.

> You can do this yourself if you wish.

I was going to suggest the same thing to the OP but if you look at his original example, he's doing more than just concatenating strings.

I just realized that the OP can really get what he wants without creating any new classes.

The debug (etc.) method takes an Object as a parameter. This means that it calls the toString method on that Object at some point. So if you create a toString method for your class, you can just pass in a reference to this and viola! the expression will not be evaluated unless debugging is turned on.

If that's not good enough, you can simply create an inner class that has a toString method and does the evaluation. This is similar to the OPs original idea and has the same problems (though these can be mitigated) but requires no new interface and is easily understood.

dubwaia at 2007-7-20 0:55:02 > top of Java-index,Java Essentials,Java Programming...
# 16

> I just realized that the OP can really get what he

> wants without creating any new classes.

>

> The debug (etc.) method takes an Object as a

> parameter. This means that it calls the toString

> method on that Object at some point. So if you create

> a toString method for your class, you can just pass in

> a reference to this and viola! the expression will not

> be evaluated unless debugging is turned on.

I've mentioned 3 problems:

- the local variables cannot be accesses from within toString()

- toString() is only one to share between its primary purpose and all the debugs

- the solution is too logging-specific and not suitable for wide range of tasks which can benefit of the lazy evaluation.

Could be the problem is not very sharp but it does exist. I have just pointed out that some routine automation (programming) taks are not possible in Java.

valjoka at 2007-7-20 0:55:02 > top of Java-index,Java Essentials,Java Programming...
# 17

> Could be the problem is not very sharp but it does

> exist. I have just pointed out that some routine

> automation (programming) taks are not possible in

> Java.

It does exist, but there is usually another way around the problem. If you think about what is required in a practical sense many programming models while cool, turn out to be more complex than useful.

While Java does not support a number of programming models, I don't beleieve it is true to say that they are not possible.

Peter-Lawreya at 2007-7-20 0:55:02 > top of Java-index,Java Essentials,Java Programming...
# 18

> I've mentioned 3 problems:

> - the local variables cannot be accesses from within

> toString()

How are they available in a new instance you create in your class?

> - toString() is only one to share between its primary

> purpose and all the debugs

Create an inner class as in your solution. I already mentioned this.

> - the solution is too logging-specific and not

> suitable for wide range of tasks which can benefit of

> the lazy evaluation.

Such as?

dubwaia at 2007-7-20 0:55:02 > top of Java-index,Java Essentials,Java Programming...
# 19

I invite you to look at the discussion influenced me to start this one:

http://groups.google.com/group/borland.public.delphi.language.delphi.general/browse_frm/thread/0701d9c307bc6228/a4050b62afd14c08#a4050b62afd14c08 The last message by Avatar emphasizing the danger of eager evaluation - the information merely can be not available in the case it is not going to be used. In the past, I used to beleive that every programming duty can be solved by functions wondering why do the C programmers need macros. Later, I have discovered that the macros are code generators; in othr words, they are inline functions. Therefore, they naturally cover the lazy evaluation problem. I have just realized a neat way the macros could be implemented -using some modifier on method call. Like:

String ifThen(boolean c, String a, String b) {

return c ? b : a;

}

Form f = null;

String s1 = ifThen(f == null, "", f.name); // fail

String s2l = inline ifThen(f == null, "", f.name); // proposal

The instruction to unroll forces the compiler to make a copy of the function, look into its body and optimize out (trim) in the usual way the unused brances. This should prevent the nasty hazards as well as solvers the problem of argument preparation discussed here. Nothing besides used arguments will be computed.

Actually, as I see it, the example's injected error is of if (false && new Exception("")==null) kind, the one pecular to the notorious Basic. Once one of the conditions in the if statement is evaluated to false, the normal program will resume from the else statement; however, the Basic goes on evaluating other conditions; therefore, programmers like me hate this "feature". Theoretically, I beleive, the proposed 'inline' statement can be redundant and compiler can optimize out unused parameters in the same way as processes if-statement conditions. Today, the unroll of a method is the compiler's decision. The problem of polymorphism intervenes here; however, the macros in principle are not designed to serve as public/heritable routines. Do you think is it feasible task for the compiler to prevent us from redundant evaluation and their conjugate hazards?

valjoka at 2007-7-20 0:55:02 > top of Java-index,Java Essentials,Java Programming...