Swinject / Swinject

Dependency injection framework for Swift with iOS/macOS/Linux
MIT License
6.3k stars 514 forks source link

GraphIdentifiers don't seem to be cleaned-up #510

Open jbehrens94 opened 2 years ago

jbehrens94 commented 2 years ago

Hi all,

I'm working on an app extension with extremely limited resources in terms of memory. I noticed that Swinject is claiming a lot of memory through GraphIdentifier, it'll increase quite a lot when doing regular actions throughout the extension.

Am I using Swinject wrong, or what should I do to minimise that amount in memory?

jbehrens94 commented 2 years ago

@mpdifran Who's able to help me on this? I don't know who the current contributors are, because I saw in an issue from 2020 that it looked like Swinject isn't maintained actively.

jbehrens94 commented 2 years ago

CC @yoichitgy Maybe you can help?

mpdifran commented 2 years ago

I'll flag this to the contribution group! We are trying to continue maintaining this actively, and we've extended our contributors to help with that.

jbehrens94 commented 2 years ago

Some additional information: I've got a set of structs conforming to Assembly that I then combine into a Assembler like this.

extension Assembler {
    static let filesExtension: Assembler = {
        let container = Container()
        let assembler = Assembler([
            DatabaseAssembly(),
            KeychainAssembly(),
            APIAssembly(),
            FileProviderAssembly(),
            FileProviderImplementationAssembly()
        ], container: container)

        return assembler
    }()
}

I'll then have a property private lazy var container = Assembler.filesExtension.resolver in my FileProviderExtension class. Does that seem correct to you, @mpdifran @yoichitgy?

jbehrens94 commented 2 years ago

@mpdifran @yoichitgy Can you confirm that my previously sent message contains a correct setup for Swinject?

jbehrens94 commented 2 years ago

Schermafbeelding 2022-07-27 om 11 07 52 Schermafbeelding 2022-07-27 om 11 07 03

The first screenshot is a clean start, the second screenshot is after an action in the app extension is finished. The memory Swinject is claiming seems to only be growing.

mpdifran commented 2 years ago

@jbehrens94 yeah your setup looks correct, I don't see anything wrong with it.

jbehrens94 commented 2 years ago

What could be causes for Swinject to keep graph identifiers in memory and not clean up?

jbehrens94 commented 2 years ago

Same question for the Swinject.(Weak..) things

bbrk24 commented 2 years ago

I investigated this a little, and from what I can tell, the GraphIdentifier and Weak<Any> objects are being held onto by GraphStorage. Perhaps instead of [GraphIdentifier: Weak<Any>], it needs some kind of WeakDictionary<GraphIdentifier, Any>.

Edit: On platforms with the Objective-C runtime, this is available as NSMapTable<GraphIdentifier, AnyObject>.weakToWeakObjects(). Some local testing shows that using this does fix the issue. However, I don't believe that's present on Linux, so a solution using NSMapTable wouldn't be completely portable.