I am shifting from Storm's traditional topology to Trident topology, which maintain batches of tuples before pushing them to database. We are processing XMLs as single tuple. In the traditional topology, which processes one xml at a time, this worked fine. But in Trident topology, it keeps a lot of tuples in memory, before committing in database, which leads to out of memory exception. It is also not clear how does storm decides the batch size and it changes on each iteration. Following is the error which we receive:
java.lang.OutOfMemoryError: GC overhead limit exceeded at java.util.Arrays.copyOf(Arrays.java:2367) at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415) at java.lang.StringBuilder.append(StringBuilder.java:132) at clojure.core$str$fn__3896.invoke(core.clj:517) at clojure.core$str.doInvoke(core.clj:519) at clojure.lang.RestFn.invoke(RestFn.java:423) at backtype.storm.daemon.executor$mk_task_receiver$fn__5564.invoke(executor.clj:397) at backtype.storm.disruptor$clojure_handler$reify__745.onEvent(disruptor.clj:58) at backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:125) at backtype.storm.utils.DisruptorQueue.consumeBatchWhenAvailable(DisruptorQueue.java:99) at backtype.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:80) at backtype.storm.daemon.executor$fn__5641$fn__5653$fn__5700.invoke(executor.clj:746) at backtype.storm.util$async_loop$fn__457.invoke(util.clj:431) at clojure.lang.AFn.run(AFn.java:24) at java.lang.Thread.run(Thread.java:745)
Futher Info:
In processing bolts we use DOM parser to parse the XMLs. We tried to reduce the size of individual tuples by taking single element of XML as one tuple, but it didn't help either.
Possible solution might include limiting the size of batches stored in memory or employing fast Garbage Collection.