Maxime Janvier
-
Content Count
5 -
Joined
-
Last visited
Posts posted by Maxime Janvier
-
-
29 minutes ago, Vandrovnik said:In a loop, I would store the result of CanLog to a local boolean variable and then use "if StoredValueOfCanLog>=..." and direct call to your Log procedure (without anonymous function).
That's actually good!
I think that I'll normally use the Log(LogLevel, MyString), but when obvious optimizations appear, I could add a CanLog to avoid evals in loops...
In that way, I can have a proper balance between code cleanliness/ease of reading and performances.
-
28 minutes ago, Kas Ob. said:There is few ways i can think of like these 2 approaches
type TLogLevel = (llInfo, llTrace, llError); procedure Log(LogLevel: TLogLevel; const LogText: string); overload; begin end; procedure Log(LogLevel: TLogLevel; const Text: array of string); overload; var Count: Integer; begin Count := Length(Text); case LogLevel of llInfo: ; llTrace: begin if Count > 0 then begin end; end; llError: ; end; end; procedure Log(LogLevel: TLogLevel; const LogText: string = ''; const Error: string = ''; const Additional: string = ''); overload; begin end; procedure Log(LogLevel: TLogLevel; const LogText: string = ''; ErrorCode: Integer = 0; const Additional: string = ''); overload; begin end; procedure TForm10.FormCreate(Sender: TObject); var BuildStringFromContext: string; begin Log(llTrace, ['Test', IntToStr(GetLastError), BuildStringFromContext]); Log(llError, 'Test', GetLastError, BuildStringFromContext); Log(llError, 'Simple Text', 0); Log(llInfo, 'Simple Text', 0, 'Additional Info'); Log(llInfo, 'Simple Text', ''); end;
Just food for thoughts for you, using array of string is easy and will make you life easier, but you should remember the order, while the overloaded versions with default empty values, are more readable and harder to confuse.
Each had its own shortcoming, like i had to add 0 do the ambiguity, but if you make you mind you can build them right and remove the need for these extra 0 or ''.
It is up to your need to think of a solution that you are comfortable with.
Thanks for these approaches!
Unfortunately, the strings (or the functions that'll generate the strings) will still be individually evaluated, if I call Log(ttTrace, [SysErrorMessage(GetLastError)]);, the SysErrorMessage function will still be called.
-
That would be a solution indeed.
But performance-wise, I don't know the cost of anonymous functions.. What if that's called in a loop?
Even if it' not called, some memory has to be dynamically allocated for the function code + the captured variables + the cost of capturing those variables...
I might do a benchmark for that...
-
Hi,
I have quite a tricky problem, and can't figure out a proper solution.
You see, I want to log debug strings in my application, so I wrote a module where the only entry point is a pure method "procedure Log(const LogLevel: TLogLevel; const Str: String);".
So the goal would be to only log strings if the logger is set to log at least that log level. That way, I can easily change the logger to only log error strings for example.
So far so good.
Problem is, when I write things like "Log(llTrace, 'Test ' + GetLastError + BuildStringFromContext); for example, the string will be evaluated wether I log it or not, because the log filter is done inside the function.
I was wandering if there was a way to avoid the evaluation of the string when I know I won't log it?
Of course the obvious solution would be to write
"if CanLog(llTrace) then Log('Test ' + GetLastError + BuildStringFromContext);"
But that would be tedious to write, and make the code harder to read.
So I though of two possibilities:
- First: Using inline function, to replace at compile time the first Log line by the if/then statement. Unfortunately, even with inline function, the arguments are fully eveluated when the function is called (tested). So it's a dead end.
- I also though to use a preprocessor macro, to replace at compile time the fist line by the if/then statement, but Delphi doesn't support C/C++ like defines, it can only set/evaluate booleans.So do you think of a solution i could've overlooked?
Without any solution, I'll stick to my first Log version, as I value code cleanliness over performance, but it's still a bit frustrating knowing my code will execute instructions for nothing at all if I disable my log....
Regards,
Avoid parameter evaluation
in RTL and Delphi Object Pascal
Posted
Good points!
That would require a bit of work, but might worth it!
Thank you very much for your time and thoughts, much appreciated! :)