RxSwiftExt icon indicating copy to clipboard operation
RxSwiftExt copied to clipboard

repeatWithBehavior has memory leak

Open tospery opened this issue 5 years ago • 15 comments

repeatWithBehavior has memory leak

tospery avatar Aug 17 '20 05:08 tospery

Hey, this isn't a valid Issue. Please provide many more details, analytics, reproduction, etc. If you can provide a PR to fix it, that would be best.

freak4pc avatar Aug 17 '20 07:08 freak4pc

image i repeat a simple observable sequence, and found the memory will grow

tospery avatar Aug 18 '20 02:08 tospery

Hey, this isn't a valid Issue. Please provide many more details, analytics, reproduction, etc. If you can provide a PR to fix it, that would be best.

The demo as above, can you help me, thanks

tospery avatar Aug 19 '20 01:08 tospery

Does anyone have the same problem?

tospery avatar Sep 23 '20 03:09 tospery

I copied your example into a project (it was pretty cumbersome considering you uploaded a screenshot, not the code itself), and I can confirm that memory usage steadily increases while the subscription is alive and repeating itself. Especially after changing the interval to 0.001 seconds instead of 1.

image

From the Allocations instrument, it seems that the concat used to implement repeatWithBehavior is spawning new Observables and keeping them in memory.


Here is the whole class so no one else has to type it in:


import UIKit
import RxSwift
import RxSwiftExt

class ViewController: UIViewController {
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        repeatTest()
    }
    
    private func repeatTest() {
        Observable.just(true)
            .repeatWithBehavior(.delayed(maxCount: UInt.max, time: 0.001))
            .subscribe(onNext: { _ in
                print("ping")
            })
            .disposed(by: disposeBag)
    }
}

vzsg avatar Sep 24 '20 18:09 vzsg

Here is the full project for quicker repro: RepeatTest.zip.

vzsg avatar Sep 24 '20 19:09 vzsg

Here is the full project for quicker repro: RepeatTest.zip.

Thanks your reply, do you have any idea to solve this problem?

tospery avatar Sep 30 '20 03:09 tospery

I tried to debug it but couldn’t immediately find a solution. I’ll see if I can find some more time but this is a bit of a packed period of time.

Shai On Sep 30, 2020, 6:03 AM +0300, 杨建祥 [email protected], wrote:

Here is the full project for quicker repro: RepeatTest.zip. Thanks your reply, do you have any idea to solve this problem? — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

freak4pc avatar Sep 30 '20 03:09 freak4pc

Here is the full project for quicker repro: RepeatTest.zip.

Thanks your reply, do you have any idea to solve this problem?

None, sadly. All I could do is pop in and add the missing details of the issue.

Perhaps as a temporary measure, you could replace repeat with an interval + flatMapFirst.

vzsg avatar Oct 04 '20 20:10 vzsg

We ran into this problem as well, leading to a stackOverflow.

        // This will crash before 1000 is printed.
        let v = DisposeBag()
        Observable.just(10)
            .flatMapLatest { num -> Observable<Int> in
                let repeatingEvents = Observable<Int>.just(num).repeatWithBehavior(
                    .customTimerDelayed(maxCount: .max, delayCalculator: { return .milliseconds(100 + $0)
                    })
                ).enumerated()

                return repeatingEvents.map { return $0.0 + 1
                }
            }
            .bind {
                if $0 % 10 == 0 {
                    print($0)
                }
            }.disposed(by: v)

winstondu avatar Jan 17 '21 02:01 winstondu

We fixed this problem by rewriting repeatWithBehavior.

This is our solution for RxSwift 5.1.1. While I'm not completely sure it doesn't leak, we were no longer seeing a clear increase in memory over time.

Feel free to adapt back to official solution @freak4pc

https://gist.github.com/winstondu/91da8a889ed4e42ef7b1c11951cd3edd

winstondu avatar Jan 17 '21 04:01 winstondu

Thank you! Any chance you can make a PR out of this, so it's a bit easier to review the changes you made in your rewrite? Appreciate your help!

freak4pc avatar Jan 17 '21 21:01 freak4pc

Thank you! Any chance you can make a PR out of this, so it's a bit easier to review the changes you made in your rewrite? Appreciate your help!

Unfortunately this solution is based on RxSwift 5.1.1, not the current head of RxSwift (6). We may not migrate our codebase to RxSwift 6 for a while.

I can still make the PR, but only if you also make a branch and new release for RxSwiftExt 5.2

winstondu avatar Jan 17 '21 21:01 winstondu

@freak4pc , I can't even build the repo right now. Carthage does not work for XCode 12: https://github.com/Carthage/Carthage/pull/3106

winstondu avatar Jan 17 '21 22:01 winstondu

Yup, unfortunately aware of that :( Need to use the SPM/CocoaPods alternatives in this case. Might have to update the demo project.

freak4pc avatar Jan 17 '21 22:01 freak4pc