Hi,
I've got a question about the zip
operator in Combine in combination with backpressure.
Take the following code snippet:
let sequencePublisher = Publishers.Sequence<Range<Int>, Never>(sequence: 0..<Int.max)
let subject = PassthroughSubject<String, Never>()
let handle = subject
.zip(sequencePublisher.print())
.print()
.sink { letters, digits in
print(letters, digits)
}
subject.send("a")
When executing this in the playground, the following is the output:
receive subscription: (0..<9223372036854775807)
receive subscription: (Zip)
request unlimited
request unlimited
receive value: (0)
receive value: (1)
receive value: (2)
receive value: (3)
receive value: (4)
receive value: (5)
receive value: (6)
receive value: (7)
...
When executing it on an iOS device, the code crashes after a few seconds because of memory issues.
The underlying reason can be seen in the fourth line above where zip
requests an unlimited amount of values from the sequencePublisher
. Since the sequencePublisher
provides the whole range of Int
values, this causes memory overflows.
What I know:
-
zip
waits for one value of each publisher before combining them and pushing them on - backpressure is used to control the demand from a subscriber to a publisher
My expectation would be that zip
only requests one value from each publisher, waits for them to arrive and only requests the next values when it received one from each.
In this particular case I tried to build a behaviour where a sequence number is assigned to every value that is produced by the subject
. However, I could imagine that this is always a problem when zip
combines values from publishers that publish with very different frequencies.
Utilising backpressure in the zip
operator seems to be perfect tool to solve that issue. Do you know why this isn't the case? Is this a bug or intentional? If intentional, why?
Thanks guys