I'm curious, can you share what amount of overhead you saw?
> Our current plan (a) is to disable stats collection by default (making
> Cache.stats() throw), unless CacheBuilder.enableStats() (or something like that)
> is called. Obviously this will break any code that currently calls Cache.stats()
> at upgrade time. We don't like that, but so far we consider it preferable to the
> other options.
One vote from me for this plan.
Blair
--
guava-...@googlegroups.com
Project site: http://guava-libraries.googlecode.com
This group: http://groups.google.com/group/guava-discuss
This list is for general discussion.
To report an issue: http://code.google.com/p/guava-libraries/issues/entry
To get help: http://stackoverflow.com/questions/ask (use the tag "guava")
Gili
Yeah I'm curious too. Guava's Cache stats are pretty much the only
place in my applications that still use AtomicLong for frequently
incremented counters (I use jsr166e's LongAdder everywhere else).
I don't know about the others, but my organization hasn't even started
to evaluate Java 7, and I don't know any other that has (in the Hadoop
/ HBase world), so JDK8 is waaaaaaaays out. I'm not going to wait
years to be able to use some of its library features. So if Guava
could bundle something simple like LongAdder and use it for
CacheStats, that would be a double win and could maybe alleviate (if
not eliminate) your performance concerns. This way stats could be
still enabled by default, and could be disabled through CacheBuilder
if absolutely necessary.
--
Benoit "tsuna" Sigoure
Software Engineer @ www.StumbleUpon.com
Am 03.04.2012 04:30, schrieb Charles Fry:
> We're looking at making some changes to how CacheBuilder-created caches
> collect statistics (a la Cache.stats()).
>
> Specifically, we have hitherto turned on stats collection by default,
> without providing a way to turn it off. As some of you may be aware this
> was requested long ago in Issue 863, and we regretfully ignored it at the
> time. But we've come to realize that stats counting does indeed impose
> undesirable overhead.
>
> Our current plan (a) is to disable stats collection by default (making
> Cache.stats() throw), unless CacheBuilder.enableStats() (or something like
> that) is called. Obviously this will break any code that currently calls
> Cache.stats() at upgrade time. We don't like that, but so far we consider
> it preferable to the other options.
I wouldn't object to that, although it would be better of course if
there was a change which would give a compile-time error. Changing the
result to Optional<CacheStats> might really be an option.
> Other alternatives we've considered are:
>
> (b) don't make stats() throw, but instead turn on stats collection the
> first time stats() is called. This sounds nice, but has the problem of
> potentially generating misleading stats, especially as the cache hit rate
> will be much lower at startup time.
If this solution is adopted, I wouldn't turn on stats collection the
first time stats() is called, which is some unexpected side-effect and
really might give weird results. Instead always return a CacheStats
object with all times etc. set to 0. This would prevent application
crashes, and would show only results which are obviously wrong (and not
wrong in a manner which could remain undetected).
Greetings, Philipp
I can illustrate that: we had a tree of Caches (with 2 levels and a
reasonable fanout) and ended up with 300K AtomicLong (6 per Cache + 6
per Segment) when we switched from Guava r09 to 10.0. That's a fair
amount of memory, and quite a few more objects to scan during the GC.
Tuning the concurrency level on the sub-Caches reduced that, but we
eventually replaced the tree with a single Cache and a complex key, at
the cost of instanciating a key for each cache request.
Frank
> Our current plan (a) is to disable stats collection by default (makingI wouldn't object to that, although it would be better of course if
> Cache.stats() throw), unless CacheBuilder.enableStats() (or something like
> that) is called. Obviously this will break any code that currently calls
> Cache.stats() at upgrade time. We don't like that, but so far we consider
> it preferable to the other options.
there was a change which would give a compile-time error. Changing the
result to Optional<CacheStats> might really be an option.
> (b) don't make stats() throw, but instead turn on stats collection theIf this solution is adopted, I wouldn't turn on stats collection the
> first time stats() is called. This sounds nice, but has the problem of
> potentially generating misleading stats, especially as the cache hit rate
> will be much lower at startup time.
first time stats() is called, which is some unexpected side-effect and
really might give weird results. Instead always return a CacheStats
object with all times etc. set to 0. This would prevent application
crashes, and would show only results which are obviously wrong (and not
wrong in a manner which could remain undetected).
If this solution is adopted, I wouldn't turn on stats collection thefirst time stats() is called, which is some unexpected side-effect and
really might give weird results. Instead always return a CacheStats
object with all times etc. set to 0. This would prevent application
crashes, and would show only results which are obviously wrong (and not
wrong in a manner which could remain undetected).Ah, I hadn't thought of that. That could be better than throwing an exception. Again the question is, would that be a useful behavior even in Guava 19.0? Or: is it worth doing as a onetime transitional measure in 12.0 only, then moving to exceptions after that?
Thinking about it, this is right.
There really needs to be a way to query (without catching an exception)
whether statistics are enabled or not. I for example might also want to
disable statistics in some runs of my application, and have it enabled
in other runs (and then use it).
So either have stats() return null, or an Optional<CacheStats> or have a
method CacheStats.statisticsEnabled(). The null-solution is used in
similar cases in the Java API [1], but I'd like Optional more.
Of the remaining two solutions, the Optional<CacheStats> makes the
"optionallity" more explicit.
When returning a dummy CacheStats object, one could still decide whether
to return a fake value from all getters except "statisticsEnabled()", or
let them throw an exception.
As I prefer to not have fake values (even if they are quite obvious),
and having an object with almost all methods throwing exceptions seems
weird, and the functionality of Optional would just be reimplemented in
CacheStats, I would prefer the Optional<CacheStats> version.
Greetings, Philipp
I don't think that's what Charles was referring to though. In the
issue he referred to [1], the author of elasticsearch is reporting
that the stats add volatile writes to the read path, something that
was otherwise carefully avoided by CHM (the implementation of which is
mostly re-used for LocalCache).
If you wound up with 300K AtomicLong it's because you had either too
many LocalCaches, or you configured them to create too many segments.
But that's not the issue being discussed here.
Anyways, I urge the Guava team to consider adding jsr166e LongAdder to
Guava (it's literally only 2 classes) and then switch the CacheStats
implementation to it. I'm sure that would make Shay happy in [1], and
it would me happy too. And this way we don't have to add a new API or
change the default semantics of the API, and this whole discussion
about whether to return null or 0 or Optional<?> or whatever is moot.
[1] http://code.google.com/p/guava-libraries/issues/detail?id=863
I would expect striped counters would be efficient enough. While there isn't the ability to stripe by processor yet, you can hash by thread id to reduce the likelihood of contention. JDK8 LongAdder and Cliff Click's Counter perform pretty well.
Then we can't draw any conclusion based on this benchmark.
> The benchmark is single-threaded, so we won't see any difference there.Then we can't draw any conclusion based on this benchmark.
--
guava-...@googlegroups.com
Project site: http://guava-libraries.googlecode.com
This group: http://groups.google.com/group/guava-discuss
This list is for general discussion.
To report an issue: http://code.google.com/p/guava-libraries/issues/entry
To get help: http://stackoverflow.com/questions/ask (use the tag "guava")