Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [golo-dev] Using SAXParser in Golo results in memory leak

Hello Vincent.

Not sure it's related to your issue, but the adapter is a factory class
and you create a new one for each `parseXml` call.

Try to make it a singleton, either by using a module constant as

```
let HANDLER_FACTORY = Adapter()
                        : extends("org.xml.sax.helpers.DefaultHandler")

local function parseXml = |parser, inputStream| {
  var xmlHandler = HANDLER_FACTORY: newInstance()
  parser: parse(inputStream, xmlHandler)
}
```

or a banged factory function

```
local function createHandler = -> Adapter()
                        : extends("org.xml.sax.helpers.DefaultHandler")

local function parseXml = |parser, inputStream| {
  var xmlHandler = createHandler!(): newInstance()
  parser: parse(inputStream, xmlHandler)
}
```

Hope it helps...


Yannick.


Vincent (2018-08-04 16:26):
> Hello,
> 
> I've been working on a Last FM  scrobbler for several hardware players in Golo for quite some time now.
> 
> As part of this project, I've implemented my own SSDP (Simple Service Discovery Protocol) handler in Golo, which seems to be working fine. However, part of this protocol requires dealing with good old XML files. Since this program is supposed to run on machines which do not have a lot of RAM, I decided to use SAX parsers.
> 
> I've noticed a huge memory leak in my program, that is quite easy to reproduce, in less than 30 lines of code:
> 
> =======
> 
> module xmlMemoryLeakTest
> 
> import gololang.Adapters
> import java.io.ByteArrayInputStream
> import javax.xml.parsers.SAXParserFactory
> 
> let TEST_XML = """<?xml version="1.0" encoding="UTF-8"?><note><text>Random XML example</text></note>"""
> 
> function main = |args| {
>     let factory = SAXParserFactory.newInstance()
>     let parser = factory: newSAXParser()
> 
>     while (true) {
>         let inputStream = ByteArrayInputStream(TEST_XML: getBytes())
>         parseXml(parser, inputStream)
>         inputStream: close()
>     }
> }
> 
> local function parseXml = |parser, inputStream| {
>     var xmlHandlerAdapter = Adapter():
>         extends("org.xml.sax.helpers.DefaultHandler")
> 
>     var xmlHandler = xmlHandlerAdapter: newInstance()       
>     
>     parser: parse(inputStream, xmlHandler)
> }
> 
> =======
> 
> If you run this program and use Java VisualVM, you'll probably see that the program keeps creating new objects (the "Classes" graph shows a line that is growing all the time).
> 
> Since a org.xml.sax.helpers.DefaultHandler instance normally requires mutating internal data, I don't really see how I could create the adapter instance once and re-use it.
> 
> If I do the same in Java (using a similar structure where the DefaultHandler instance is created and used at every iteration of the parseXml() method), then I see a more or less flat line in JVisualVM  in the "Classes" graph, after a short while.  I could all code and screenshots on GitHub if that would be appreciated.
> 
> Anybody understanding what is going? Is there anything that I can do about this? My current plan is to rewrite the XML parsing parts in Java, but was interested to see if the community had anything to say about this case. 
> 
> Thanks for your help again!
> 
> Best regards,
> Vincent
> _______________________________________________
> golo-dev mailing list
> golo-dev@xxxxxxxxxxx
> To change your delivery options, retrieve your password, or unsubscribe from this list, visit
> https://dev.eclipse.org/mailman/listinfo/golo-dev
> 

Attachment: signature.asc
Description: PGP signature


Back to the top