-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use off-heap cache #331
base: master
Are you sure you want to change the base?
use off-heap cache #331
Conversation
Thank you @hamsterksu for another important contribution :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hamsterksu , I've ran a load test locally and was able to check that heap memory is being consumed rapidly and it requires a Major GC collection to clean it. Not good, the root cause must be investigated.
Seems like the byte arrays that store the track's payload are kept in old gen:
I think that by keeping in-memory a map of Downloaders that store the track's payload is the problem here.
What do you think of replacing the current cache from Cache<String,byte[]> to Cache<String,LazyLoader> where LazyLoader is an object responsible for storing the payload and downloads it in lazy fashion?
Running test without caching keeps old gen consumption at a steady 131Mb.
Some details about test:
- 300 concurrent calls with 1-min duration.
- Each call plays a different file with size=986Kb.
- Cache size is 300Mb.
- In total, 900 calls were executed.
thanks @hrosa i will do more tests before commit in future :( i don't want to store custom object in cache, because it should be serializable |
@hamsterksu any news on this one? |
hi @hrosa but old generation heap is still growing |
@hrosa i don't see a solution for this. Because this behavior is predictable. |
@hamsterksu im a bit confused from your latests comments.. |
Hi @hamsterksu That seems to be the case, the "downloader" is keeping the entire audio file in memory before passing it to the cache. The problem will get worse as file size increases (either by length or codec quality). The only workaround that comes to mind is to use DirectByteBuffers. Needless to say, this will be very costly and makes me wonder about the usefulness of the cache in this scenario. The other solution would be to stream the contents of the file directly into the ehcache's entry, but you were against it IIRC. |
Hi @hamsterksu I've been thinking about this. On the other hand, this caching implementation is not. Because it holds the entire payload in-memory before actually placing it into the cache, the data gets promoted to old gen. The problem gets worse the bigger the file (either by length and/or quality). In last analysis, seems the problem here is the lack of support for stream-like behaviour in ehcache. The workaround I had in mind would be to keep a pool of DirectByteBuffers to store the payload before passing to the cache. But this solution is heavy and hard to maintain. And actually makes me wonder about the usefulness of the off-heap cache... In case we don't find a proper workaround to justify the off-heap cache, then maybe the answer will be to cache the audio tracks locally in the filesystem. What do you think about this? |
hi @hrosa, i have updated implementation. but i have got some limitation of guava cache implementation. Guava implements cache with segments for concurrent access. Entity will be evicted if segment is full even if other segments are not. Segments count can be managed: Their recommendation I suppose our numbers of threads is number of players. am i right? Also i want to add functionality to specify url pattern for cached audio. WDYT? one more comment: i see another issue with cache implementation - we need to download whole file before playing. Thanks, |
14407dd
to
0f947b6
Compare
0f947b6
to
1542b6c
Compare
@hrosa one additional issue - seems cache was removed from guava in the latest release. which version of java do you recommend for mediaserver? |
Guava hasn't removed or deprecated their cache and it would take a minimum of 2 years from deprecation to removal. If you require pre-JDK8, then another alternative is Cassandra's off-heap cache. However, it is also segmented. |
anyway we don't use "off-heap" cache from any library anymore. |
Tks @hamsterksu I will try to find some time in upcoming week to review your work. Unfortunately, we are currently stuck on Java 7 for now. But I plan to move on to version 8 soon. |
Hi @hrosa
i have refactored cache.
Now i use off-heap cache and string key instead of URL.
These changes should solve #283
URL class has trouble with hascode method: it executes
getHostAddress
which issynchronized
https://docs.oracle.com/javase/7/docs/api/java/net/URLStreamHandler.html#getHostAddress(java.net.URL)
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/net/URLStreamHandler.java#428