Hi Petr,
I've switched the logging level to DEBUG and triggered another rescan (btw, after launchctl unload, I have to additionally kill the Java process -- it won't quit by itself). Also, I increased the logfile sizes. I am getting 1.2 GB of log but none of the entries is related to expired media items. All exceptions in the log are related to meta data extraction or the JPG libraries' read function throwing exceptions. As I cannot share this much of log data here in the forum, I digged deeper.
There is *ANOTHER* log file at /var/log/serviio/serviio.log and it contains additioal exceptions (which seem to go uncatched by the Serviio code and should be treated and turned to ERRORs in the normal log file at least). The most important one is this:
- Code:
Exception in thread "ActionDistributor: Thread-2" Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.LinkedHashMap$LinkedValues.iterator(LinkedHashMap.java:588)
at org.simpleframework.transport.reactor.ActionDistributor.cancel(ActionDistributor.java:365)
at org.simpleframework.transport.reactor.ActionDistributor.execute(ActionDistributor.java:188)
at org.simpleframework.transport.reactor.ActionDistributor.run(ActionDistributor.java:172)
at java.lang.Thread.run(Thread.java:745)
java.lang.OutOfMemoryError: Java heap space
at org.apache.derby.impl.jdbc.Util.javaException(Unknown Source)
at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedResultSet.noStateChangeException(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedResultSet.getString(Unknown Source)
at org.apache.derby.impl.jdbc.EmbedResultSet.getString(Unknown Source)
at org.serviio.library.dao.MediaItemDAOImpl.initMediaItem(MediaItemDAOImpl.java:454)
at org.serviio.library.dao.MediaItemDAOImpl.mapResultSet(MediaItemDAOImpl.java:433)
at org.serviio.library.dao.MediaItemDAOImpl.getMediaItemsInRepository(MediaItemDAOImpl.java:195)
at org.serviio.library.local.service.MediaService.getMediaItemsInRepository(MediaService.java:83)
at org.serviio.library.local.indexing.LibraryOneTimeScanner.searchForRemovedAndUpdatedFiles(LibraryOneTimeScanner.java:228)
at org.serviio.library.local.indexing.LibraryOneTimeScanner.searchForUpdatesAndRemovals(LibraryOneTimeScanner.java:133)
at org.serviio.library.local.indexing.LibraryOneTimeScanner.scanLibrary(LibraryOneTimeScanner.java:82)
at org.serviio.library.local.indexing.LocalLibraryManager.performManualScan(LocalLibraryManager.java:186)
at org.serviio.library.local.indexing.LocalLibraryManager.startLibraryScanning(LocalLibraryManager.java:117)
at org.serviio.MediaServer.main(MediaServer.java:162)
So, in org.serviio.library.dao.MediaItemDAOImpl.getMediaItemsInRepository(), Serviio is trying to read the ENTIRE existing database into memory all at once and it fails at that. I thought that I already increased the memory footprint beyond reasonable (for thumbnail creation) but obvious not.
Analyzing the exception, the problem is most likely with a full iteration over a large ResultSet. I don't know for Derby, but many JDBC implementations are poor in that they keep a reference to all rows already visited in the ResultSet object (to implement ResultSet.previous() w/o a need to visit the db again). Making it grow in memory even if the ResultSet consumer remains small (like just filling a HashSet). This can be overcome by splitting the single loop over the ResultSet into many smaller ones, where each smaller loop uses ResultSet.absolute() (or an offset via SQL) to skip over data already read and possibly using ResultSet.setFetchSize() to avoid reading too many data twice. The consumer would still be able to see all data this way. The small loop size can then be set to fit into the 512MB default heap size of serviio. My feeling is that small loop size (fetch size) would be around 250k records. Note that media archives can encompass millions of entries.
Observing Serviio uses a 64 Bit JVM, I increased the memory to 4GB and now it worked.
The Delta scanner now runs with a memory footprint of 3.5 GB.I.e., I solved the main problem I was experiencing. The Serviio content is now in sync with the actual media files.
But a more incremental algorithm to iterate over existing entries, or a more defensive approach may be appropriate. Or at least, to manually garbage collect to shrink the memory footprint after each run of the delta scanner.
Any ideas how to reduce the Serviio memory footprint?
Moreover, any feedback on my other problems (e.g., funny entries in the "movies" category, like 30 entries for some "Bruce Lee" movie where I have none)? Meanwhile, I checked they are coming from VTS_x_y.VOB entries of archived and non-encoded DVDs.
Kind regards,
Falk