2

Since each Observable has a cache which can be traced back to the very first emitted value it seems an amount of memory used to store this cache is not bounded.

I've tested this assumption with the following code:

Observable.interval(1.microsecond).map(_ => System.currentTimeMillis)
  .subscribe(x => ())

And indeed the memory usage has been steadily rising during the whole 10 minute period while an app was running.


My question is if it's possible to instantiate a special Observable without cache or maybe instruct it to cap it's cache at some level?

src091
  • 2,807
  • 7
  • 44
  • 74
  • 2
    Are you sure it won't all be GC'd away at some point? – Carcigenicate Feb 07 '17 at 19:59
  • @Carcigenicate 10 minutes seems like a pretty sufficient interval for GC to do it's job. Besides, logically cache should not be GC'd as it stores all the values and is not being dereferenced while `Observable` is active – src091 Feb 07 '17 at 20:06
  • Still, opening VisualVM and forcing a GC might be worth a try. I don't know the specifics of how the `Observable` works, but I know I've had some programs that held onto objects for seemingly forever, only to be auto-cleared once usage got high enough. – Carcigenicate Feb 07 '17 at 20:08
  • @Anton that would only be true if your initial assumption that the Observable would cache values. The easiest way to find out is to force a GC. – Nándor Előd Fekete Feb 07 '17 at 20:19

1 Answers1

6

Only a specific set of Observables (ReplaySubject, replay(), GroupedObservable for example) tend to cache items, but not Observable.interval().

What you are likely experiencing here is the hundreds of thousands of boxed Long values. If you have a lot of RAM, GC might not kick in but just increase the heap size up to a maximum. Assuming you can really get a 1 microsecond timer, you have roughly 24 MB/s allocation rate or 1.4 GB/minute. If left alone for 10 minutes, you'd likely see a sawtooth like shape in memory usage.

akarnokd
  • 69,132
  • 14
  • 157
  • 192