nuclearace / Socket.IO-Client-Swift

socket.io-client for Swift
Other
361 stars 53 forks source link

Memory Leaks #85

Closed ysholqamy closed 8 years ago

ysholqamy commented 9 years ago

Hello, I am facing a problem when trying to deinit a socket and use another one. The server sometimes disconnects me, so I opted to creating a new socket and reconnect to the server using this new socket. I noticed that the old socket was kept around (memory usage keeps going up) although the socket is not referenced anymore or maybe the engine is kept around I am not sure. TL;DR sockets, or one of its dependencies will still occupy memory when they are not referenced anymore. To demo that, have an object referencing a socket, connect the socket disconnect the socket, make the object point to another socket object. If you do it enough times you will notice that memory is growing linearly and not freed.

nuclearace commented 9 years ago

Are you on the latest version of the library?

ysholqamy commented 9 years ago

yes

ysholqamy commented 9 years ago

just upgraded yesterday to 4.0.0

nuclearace commented 9 years ago

Before you assign a new socket, if you call socket.removeAllHandlers() does it still not deint?

nuclearace commented 9 years ago

Try the last version. I don't think the engine was actually being released

ysholqamy commented 9 years ago

Which version? 4.0?

ysholqamy commented 9 years ago

I tried version 4.0.1, still the memory is growing linearly

nuclearace commented 9 years ago

Have you tried turning on logging?

ysholqamy commented 9 years ago

I just turned on logging, the client and engine deinit, still the memory is growing

nuclearace commented 9 years ago

If they're being deinit then it shouldn't be the library

nuclearace commented 9 years ago

Also note, there is still this outstanding thing. https://github.com/socketio/socket.io-client-swift/issues/89 Not entirely sure how to fix this

ysholqamy commented 9 years ago

But this case is different I think, I am not emitting anything still the memory grows. I still believe it is the library somehow although the client and engine deinit, I kept creating and destroying sockets 100 times, the memory was growing and stopped when I stopped creating sockets.

nuclearace commented 9 years ago

Can you create a test project that demonstrates the problem

ysholqamy commented 9 years ago

I will, but I don't have my laptop on me atm. but briefly all what I do is inside the handler of socket.on("disconnect") i init a new socket and dereference the old one thats all.

ysholqamy commented 9 years ago

I init and connect a new socket **

ysholqamy commented 9 years ago

here is a link for a demo project https://github.com/ysholqamy/SocketIOSwiftClientTest

Your server should be configured to disconnect the socket on connecting. run the project and keep an eye on memory usage

nuclearace commented 9 years ago

Instruments doesn't seem to detect any leaks. But then again, I don't think it works well with Swift

nuclearace commented 9 years ago

I'm not really sure what's going. If you set a timeout on the server so that disconnects after a few seconds, you can see it slowly go up. It could be some problem with Swift

ysholqamy commented 9 years ago

maybe the handshake response is cached in memory or something?

nuclearace commented 9 years ago

Perhaps

ysholqamy commented 9 years ago

Well, when forcing websockets the memory does not grow. It still grows a bit, but becomes stable after a while, when force polling is used the memory grows linearly. Still needs more investigation

ysholqamy commented 9 years ago

nvm still grows anyway when forcing websockets, was just a lucky run maybe.

ysholqamy commented 9 years ago

or it actually does not grow, I am not sure really. Can you force websockets and check the results please?

nuclearace commented 9 years ago

If it's not growing when forcing websockets then it's probably NSURLSession doing some caching

ysholqamy commented 9 years ago

I thought the same regarding NSURLSession, but even when I passed a configuration to the used session with URLCache set to nil to disable caching nothing happened. Also I am not sure whether it's growing or not when using websockets, sometimes it does and sometimes it does not.

I detected a lot of leaks using instruments, but I am not that good using instruments so I cant figure out the reason of these leaks screen shot 2015-10-21 at 3 58 48 am

ysholqamy commented 9 years ago

Found the leak! In SocketIOClientOption getSocketIOOptionValue() and description getter. both use Mirror(), I am not sure why mirror is causing a leak but instruments shows a leak in both.

nuclearace commented 9 years ago

Ugh, if that's really the leak then it's a bug in Swift. And I really don't want to implement those methods without using Mirror, since it'll just be a ton of boilerplate.

ysholqamy commented 9 years ago

Yea, it is a bug in swift probably. When using websockets I Noticed that I get the memory back over time so there is no huge leakage, just the mirror one. Thanks alot!

nuclearace commented 9 years ago

If you use the last version v4.0.2 and use the new way to set options it should avoid calling those methods that use Mirror

nuclearace commented 9 years ago

Disregard 4.0.2, use 4.0.3

ysholqamy commented 8 years ago

@nuclearace hello, I am working on an open source swift web framework, so I would like to chat with you about several things concerning how to setup the project. I find socketio-client-swift very neat so I would like to somehow mimic the setup. Any help will be appreciated and thanks in advance.

ysholqamy commented 8 years ago

Uh, actually the latest version fixed the leaks issue. closing this. thanks

nuclearace commented 8 years ago

What do you mean

several things concerning how to setup the project

ysholqamy commented 8 years ago

ah, actually this sounds as I am talking about the actual setting up of a package. but no, I mean how the framework should actually behave. for example, a web framework like ruby on rails takes advantage of the dynamic nature of ruby language and metaprogramming in its ORM. So the question is, how can this be done in a not so dynamic language like swift? Or should I go with a lightweight framework a la Express.js? Also I have some questions about setting up the http server it self, I did not find a good resource on implementing a listener socket which binds to a certain port using swift.

nuclearace commented 8 years ago

Well this library is just a straight socket.io-client. If you're looking for the socket.io server docs checkout http://socket.io/docs/

As for a web framework in Swift, I really have no idea how it would behave, other than it would probably make heavy use of callbacks or another async device like in node.js.

ysholqamy commented 8 years ago

Thanks a lot, I will definitely check the docs.