Yes, and yes.
On 23-03-2012 12:43, Matthew Toseland wrote:
> On Friday 23 Mar 2012 15:29:44 you wrote:
>> Right now, the map is only used to list class thresholds which are
>> different from the global threshold, which means it is empty 99% of the
>> time. This is the simplest solution, but it also means that the
>> possibility of lock contention is way higher. However, unless this
>> proves to be very bad in a real run, I'll stick with it.
> Sounds like you need to use a volatile.
>
> Also your design implies that the log level details will be changed to not
> support wildcards/prefixes?
>> On 23-03-2012 10:39, Matthew Toseland wrote:
>>> On Friday 23 Mar 2012 00:18:02 Marco Schulze wrote:
>>>> I already have all but log rotation and async ready, and haven't yet
>>>> found a single benchmark supporting the use of a branch as the
>>>> performance holy grail. For example (outputting to /dev/null):
>>>>
>>>> public static void main (String[] args) {
>>>> for (int i = 0; i< 1000000; i++) {
>>>> Log.fatal (Log.class, Log.class, "akd\n\n", i, '\n',
>>>> out, ' ');
>>>> Log.trace (Log.class, Log.class, "akd\n\n", i, '\n',
>>>> out, ' ');
>>>> }
>>>> }
>>>>
>>>> Every call means, minimally, varargs boxing, another call (since fatal()
>>>> and trace() are simple convenience methods) and an isLoggable() check
>>>> composed by a ConcurrentHashMap lookup against the class name and
>>>> (possibly) a synchronized read on the global threshold. trace() is
>>>> filtered but fatal() is not.
>>> Don't do a synchronized read on the global threshold. Don't do synchronized
>>> anything. Just recompute all the classes when the thresholds change.
>>>
>>> However, you still haven't told me how you're going to ensure all classes
>>> are paged in when you do set all the thresholds in the map?
>>>> This snipped ran in an average 6.482 seconds. If the call to trace() is
>>>> commented out (thus removing the filtering overhead), the average falls
>>>> to 6.366 seconds. Disabling JIT, the figures became 1:37.952 and
>>>> 1:35.880, respectively. Over a million calls, checking costs only a few
>>>> milliseconds.
>>>>
>>>> To be sure, this is a fairly simple example: it all runs on a single
>>>> thread, the hash table is empty and the pressure on the GC is low.
>>>> Still, differences are very small. Plus, there's no overhead due to a
>>>> dedicated logging thread.
>>>>
>>>> On 22-03-2012 18:59, Zlatin Balevsky wrote:
>>>>> Double-digit millisecond pauses are not nothing. They may be
>>>>> acceptable right now but unless you can offer a drastically cleaner
>>>>> syntax Fred should stick with predicates as they are handled much
>>>>> better by the hotspot jit.
>>>>>
>>>>> On Mar 22, 2012 5:36 PM, "Ximin Luo"<infinity0 at gmx.com
>>>>> <mailto:infinity0 at gmx.com>> wrote:
>>>>>
>>>>> Lazy evaluation is trivial.
>>>>>
>>>>> Log.info("{1} did {2}",
>>>>> new Object(){ public String toString() { return ITEM_1; } },
>>>>> new Object(){ public String toString() { return ITEM_2; } }
>>>>> );
>>>>>
>>>>> Garbage collection with short-lived objects costs next to nothing.
>>>>>
>>>>> On 22/03/12 21:15, Zlatin Balevsky wrote:
>>>>> > Constructing the logging strings is half of the problem. The
>>>>> amount of garbage
>>>>> > they will generate will result in significantly more time in
>>>>> garbage collection
>>>>> > pauses.
>>>>> >
>>>>> > Unless you figure out a way to mimic lazy evaluation you have to
>>>>> live with the
>>>>> > isLoggable predicates. varargs are not an option either because
>>>>> they also
>>>>> > create garbage.
>>>>> >
>>>>> > On Mar 22, 2012 8:11 AM, "Marco Schulze"
>>>>> <marco.c.schulze at gmail.com<mailto:marco.c.schulze at gmail.com>
>>>>> > <mailto:marco.c.schulze at gmail.com
>>>>> <mailto:marco.c.schulze at gmail.com>>> wrote:
>>>>> >
>>>>> >
>>>>> >
>>>>> > On 22-03-2012 08:50, Matthew Toseland wrote:
>>>>> >
>>>>> > On Wednesday 21 Mar 2012 21:18:37 Marco Schulze wrote:
>>>>> >
>>>>> > There are basically two big concerns regarding
>>>>> logging in fred:
>>>>> >
>>>>> > - Readability and code clutter, which was my
>>>>> original questioning;
>>>>> > - Raw throughput, as raised by toad.
>>>>> >
>>>>> > Point 1 could mostly be solved by removing any
>>>>> traces of logMINOR and
>>>>> > logDEBUG on all but the few places where generating
>>>>> messages to be
>>>>> > logged brings noticeable slowdown. That'd be enough,
>>>>> but, personally,
>>>>> > the mess that the logging backend is does warrant a
>>>>> replacement.
>>>>> > According to toad, the current system needs
>>>>> log{MINOR,DEBUG} to
>>>>> > function
>>>>> > in a timely manner. Based on this, I think we all
>>>>> agree a
>>>>> > replacement is
>>>>> > desirable.
>>>>> >
>>>>> > Logging has a few additional requirements:
>>>>> >
>>>>> > - Log rotation (possibly live);
>>>>> > - Reentrant;
>>>>> > - Per-class filtering;
>>>>> > - Specific information in log (class-name, for
>>>>> example).
>>>>> >
>>>>> > Now, _any_ library which fits would make me happy,
>>>>> as long as they
>>>>> > agree
>>>>> > to two points:
>>>>> >
>>>>> > - Either lightweight or with optional features.
>>>>> Else, it would only
>>>>> > transfer bloat to freenet-ext.jar. For example:
>>>>> log2socket, config
>>>>> > management and multiple logging instances;
>>>>> > - Implementable in a few LoC. Specially, it
>>>>> shouldn't need specialized
>>>>> > Formatter and Writer.
>>>>> >
>>>>> > Plus, it should be fast.
>>>>> >
>>>>> > From the quick research I made (yep, too many
>>>>> lists):
>>>>> >
>>>>> > - SLF4J already fails on point one: it is simply a
>>>>> wrapper;
>>>>> > - The Java logging API fails on point two:
>>>>> specialized classes would
>>>>> > have to be written to deal with log rotation,
>>>>> per-class filtering and
>>>>> > formatting, plus a wrapper for
>>>>> Logger.{info,warning,...}() methods.
>>>>> > Exactly the same as a custom logger, with one more
>>>>> dependency and using
>>>>> > more LoC;
>>>>> >
>>>>> > No dependancies, it's part of the JDK, isn't it?
>>>>> >
>>>>> > More classes need to be loaded at startup. It's just me
>>>>> thinking too much.
>>>>> >
>>>>> >
>>>>> > However, if it's not a clearer/simpler API, it probably
>>>>> doesn't make
>>>>> > much sense.
>>>>> >
>>>>> > - Log4J seems to fail on point one - it only lacks a
>>>>> button that brings
>>>>> > back the dead. It seems interesting, and I haven't
>>>>> dropped this yet.
>>>>> >
>>>>> > In either case (custom or external), log* would be
>>>>> banished. Forever.
>>>>> >
>>>>> > I don't follow. You object to using a separate logs
>>>>> folder?
>>>>> >
>>>>> > log* == log{MINOR,DEBUG}, not the logs folder.
>>