Skip to content

Commit 7f9010e

Browse files
committed
Added an AsyncStream to receive footprint changes
1 parent 0d12b57 commit 7f9010e

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

Sources/Footprint/DefaultMemoryProvider.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ extension Footprint {
2727
// In the simulator `limit_bytes_remaining` returns -1
2828
// which means we can't calculate limits.
2929
// Due to this, we just set it to 4GB.
30-
let limit: Int64 = 4_000_000_000
30+
let limit: Int64 = 6_000_000_000
3131
let remaining: Int64 = max(limit - used, 0)
3232
#else
3333
let remaining: Int64 = kerr == KERN_SUCCESS ? Int64(info.limit_bytes_remaining) : 0

Sources/Footprint/Footprint.swift

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
///
77

88
import Foundation
9+
import os
910

1011
/// The footprint manages snapshots of app memory limits and state,
1112
/// and notifies your app when these change.
@@ -82,7 +83,7 @@ public final class Footprint: @unchecked Sendable {
8283

8384
/// The high watermark of memory bytes your app can use before being terminated.
8485
public let limit: Int64
85-
86+
8687
/// The state describing where your app sits within the scope of its memory limit.
8788
public let state: State
8889

@@ -93,7 +94,12 @@ public final class Footprint: @unchecked Sendable {
9394
public let timestamp: UInt64
9495

9596
/// Initialize for the `Memory` structure.
96-
init(used: Int64, remaining: Int64, compressed: Int64 = 0, pressure: State = .normal) {
97+
init(
98+
used: Int64,
99+
remaining: Int64,
100+
compressed: Int64 = 0,
101+
pressure: State = .normal
102+
) {
97103

98104
self.used = used
99105
self.remaining = remaining
@@ -108,13 +114,8 @@ public final class Footprint: @unchecked Sendable {
108114
usedRatio < 0.90 ? .critical : .terminal
109115

110116
self.timestamp = {
111-
let time = mach_absolute_time()
112-
var timebaseInfo = mach_timebase_info_data_t()
113-
guard mach_timebase_info(&timebaseInfo) == KERN_SUCCESS else {
114-
return 0
115-
}
116-
let timeInNanoseconds = time * UInt64(timebaseInfo.numer) / UInt64(timebaseInfo.denom)
117-
return timeInNanoseconds / 1_000_000
117+
let timeInNanoseconds = clock_gettime_nsec_np(CLOCK_UPTIME_RAW)
118+
return timeInNanoseconds / NSEC_PER_MSEC
118119
}()
119120
}
120121

@@ -158,7 +159,14 @@ public final class Footprint: @unchecked Sendable {
158159
public var memory: Memory {
159160
_memoryLock.withLock { _memory }
160161
}
161-
162+
163+
/// Returns an AsyncStream that pushes a _Memory_ as it changes.
164+
public var memoryStream: AsyncStream<Memory> {
165+
AsyncStream { continuation in
166+
_memoryStreamContinuations.append(continuation)
167+
}
168+
}
169+
162170
/// Based on the current memory footprint, tells you if you should be able to allocate
163171
/// a certain amount of memory.
164172
///
@@ -205,6 +213,8 @@ public final class Footprint: @unchecked Sendable {
205213

206214
_memoryPressureSource.suspend()
207215
_memoryPressureSource.cancel()
216+
217+
_memoryStreamContinuations.forEach { $0.finish() }
208218
}
209219

210220
private func heartbeat() {
@@ -308,8 +318,11 @@ public final class Footprint: @unchecked Sendable {
308318
if changeSet.contains(.footprint) {
309319
// copy behind the lock
310320
// deploy outside the lock
311-
let observers = _memoryLock.withLock { _observers }
321+
let (observers, continuations) = _memoryLock.withLock {
322+
(_observers, _memoryStreamContinuations)
323+
}
312324
observers.forEach { $0(memory) }
325+
continuations.forEach { $0.yield(memory) }
313326
}
314327
}
315328

@@ -322,6 +335,7 @@ public final class Footprint: @unchecked Sendable {
322335
private var _observers: [(Memory) -> Void] = []
323336
private let _memoryLock: NSLock = NSLock()
324337
private var _memory: Memory
338+
private var _memoryStreamContinuations: [AsyncStream<Memory>.Continuation] = []
325339
}
326340

327341
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, visionOS 1.0, *)

0 commit comments

Comments
 (0)