Update for BatchRequest and PlanetsRequest for modern concurrency (#11)
This commit is contained in:
parent
f512a9fafe
commit
448c495948
|
@ -11,7 +11,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>1.4072</real>
|
||||
<real>1.407200</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
@ -21,7 +21,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.0048445</real>
|
||||
<real>0.004844</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>2.55</real>
|
||||
<real>2.550000</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
@ -41,7 +41,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.45805</real>
|
||||
<real>0.458050</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
@ -51,7 +51,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.1499</real>
|
||||
<real>0.149900</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
@ -61,7 +61,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.28996</real>
|
||||
<real>0.289960</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
@ -71,7 +71,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.2513</real>
|
||||
<real>0.251300</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
@ -94,7 +94,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.14739</real>
|
||||
<real>0.147390</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
@ -104,7 +104,7 @@
|
|||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.766</real>
|
||||
<real>0.766000</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>classNames</key>
|
||||
<dict>
|
||||
<key>PerformanceTests</key>
|
||||
<dict>
|
||||
<key>testBatchRequestPlanetCoordinates()</key>
|
||||
<dict>
|
||||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.000011</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>testBatchRequestPlanetCoordinatesDeprecated()</key>
|
||||
<dict>
|
||||
<key>com.apple.XCTPerformanceMetric_WallClockTime</key>
|
||||
<dict>
|
||||
<key>baselineAverage</key>
|
||||
<real>0.637282</real>
|
||||
<key>baselineIntegrationDisplayName</key>
|
||||
<string>Local Baseline</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -28,6 +28,30 @@
|
|||
<key>targetArchitecture</key>
|
||||
<string>x86_64</string>
|
||||
</dict>
|
||||
<key>ECF89B48-B02C-4625-9453-0816115FCFF4</key>
|
||||
<dict>
|
||||
<key>localComputer</key>
|
||||
<dict>
|
||||
<key>busSpeedInMHz</key>
|
||||
<integer>0</integer>
|
||||
<key>cpuCount</key>
|
||||
<integer>1</integer>
|
||||
<key>cpuKind</key>
|
||||
<string>Apple M1</string>
|
||||
<key>cpuSpeedInMHz</key>
|
||||
<integer>0</integer>
|
||||
<key>logicalCPUCoresPerPackage</key>
|
||||
<integer>8</integer>
|
||||
<key>modelCode</key>
|
||||
<string>MacBookPro17,1</string>
|
||||
<key>physicalCPUCoresPerPackage</key>
|
||||
<integer>8</integer>
|
||||
<key>platformIdentifier</key>
|
||||
<string>com.apple.platform.macosx</string>
|
||||
</dict>
|
||||
<key>targetArchitecture</key>
|
||||
<string>arm64</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -6,7 +6,7 @@ import PackageDescription
|
|||
let package = Package(
|
||||
name: "SwissEphemeris",
|
||||
platforms: [
|
||||
.macOS(.v10_15), .iOS(.v14)
|
||||
.macOS(.v11), .iOS(.v14)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries produced by a package, and make them visible to other packages.
|
||||
|
|
15
README.md
15
README.md
|
@ -106,19 +106,16 @@ The `enum` types for `Planet`, `Asteroid`, and `LunarNode` correspond to IPL num
|
|||
|
||||
#### Batch Calculations
|
||||
|
||||
To get the most out of the ephemeris, you may need to make a lot of calculations at one time. Making calculations in mass is an expensive operation. and should never be done on the main thread. If you are making hundreds of calculations at one time it is recommended to use a `BatchRequest` for increased performance and to avoid the undefined behavior that results from making numerous calculations concurrently on a single thread.
|
||||
To get the most out of the ephemeris, you may need to make a lot of calculations at one time. Making calculations in mass is an expensive operation. and should never be done on the main thread. If you are making hundreds of calculations at one time it is recommended to use a `BatchRequest` for increased performance and to avoid the undefined behavior that results from making a high number of calculations concurrently.
|
||||
|
||||
For example, if I wanted to calculate the exact dates for the phases of the moon I could create a map of the hourly percentage by requesting a `Lunation` for every hour over the next 30 days.
|
||||
For example, to calculate the exact coordinates for the sun for a period of time:
|
||||
|
||||
```swift
|
||||
let lunationsRequest = LunationsRequest()
|
||||
let request = PlanetsRequest(body: .sun)
|
||||
let now = Date()
|
||||
let end = Date(),.addingTimeInterval(60 * 60 * 24 * 30)
|
||||
lunationsRequest.fetch(start: now, end: end, interval: 60.0 * 60.0) { lunations in
|
||||
/// An array of `Lunation` for every hour between now and 720 hours in the future
|
||||
/// mapped to percentage values.
|
||||
let percentages = lunations.map { $0.percentage }
|
||||
}
|
||||
let end = now.addingTimeInterval(60 * 60 * 24 * 30)
|
||||
// Asynchronously returns an array of `.sun` `Coordinate`s for every hour between now and 720 hours in the future.
|
||||
let batchCoordinates = await request.fetch(start: now, end: end, interval: 60.0 * 60.0)
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
|
|
@ -10,14 +10,24 @@ import Foundation
|
|||
/// Models a request for batch calculations at a consistent
|
||||
/// date interval. If you are making hundreds of calculations at one time
|
||||
/// it is recommended to use these utility methods for increased performance
|
||||
/// and to avoid the undefined behavior that results from making numerous calculations
|
||||
/// concurrently on a single thread.
|
||||
/// and to avoid the undefined behavior that results from making a high number of
|
||||
/// calculations concurrently.
|
||||
public protocol BatchRequest {
|
||||
/// The type returned from the fetch request.
|
||||
associatedtype EphemerisItem
|
||||
/// The maximum amount of concurrent calculations. Exceed `478` at your own risk.
|
||||
var datesThreshold: Int { get }
|
||||
|
||||
@available(macOS 12.0.0, *)
|
||||
/// Fetches a collection of `EphemerisItem` for a time interval through a span of dates.
|
||||
/// - Parameters:
|
||||
/// - start: The beginning of the date range.
|
||||
/// - end: The end of the date range.
|
||||
/// - interval: The frequency in which an item is calculated.
|
||||
/// - Returns: An array of `EphemerisItem`.
|
||||
func fetch(start: Date, end: Date, interval: TimeInterval) async -> [EphemerisItem]
|
||||
|
||||
@available(*, deprecated, renamed: "fetch(start:end:interval:_:)")
|
||||
/// Fetches all of the `RequestType`s between two dates.
|
||||
/// - Parameters:
|
||||
/// - start: The starting date.
|
||||
|
|
|
@ -20,7 +20,28 @@ final public class PlanetsRequest: BatchRequest {
|
|||
public init(body: Planet) {
|
||||
self.body = body
|
||||
}
|
||||
|
||||
@available(macOS 12.0.0, *)
|
||||
public func fetch(start: Date, end: Date, interval: TimeInterval = 60.0) async -> [EphemerisItem] {
|
||||
var coordinates = [EphemerisItem]()
|
||||
var dates = dates(for: start, end: end, interval: interval)
|
||||
let stream = AsyncStream<[EphemerisItem]> {
|
||||
guard !dates.isEmpty else { return nil }
|
||||
do {
|
||||
try await Task.sleep(nanoseconds: 1)
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
let batch = dates.removeFirst()
|
||||
return batch.map { EphemerisItem(body: self.body, date: $0) }
|
||||
}
|
||||
for await items in stream {
|
||||
coordinates.append(contentsOf: items)
|
||||
}
|
||||
return coordinates
|
||||
}
|
||||
|
||||
@available(*, deprecated, renamed: "fetch(start:end:interval:_:)")
|
||||
public func fetch(start: Date, end: Date, interval: TimeInterval = 60.0, _ closure: ([EphemerisItem]) -> Void) {
|
||||
var coordinates = [EphemerisItem]()
|
||||
let group = DispatchGroup()
|
||||
|
|
|
@ -122,24 +122,29 @@ final class PerformanceTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testBatchRequestPlanetCoordinates() {
|
||||
let planetsRequest = PlanetsRequest(body: .moon)
|
||||
measure {
|
||||
planetsRequest.fetch(start: date, end: date.addingTimeInterval(60 * 60 * 24 * 30)) {
|
||||
XCTAssertEqual($0.count, 43200)
|
||||
}
|
||||
}
|
||||
}
|
||||
func testBatchRequestPlanetCoordinatesDeprecated() {
|
||||
measure {
|
||||
PlanetsRequest(body: .moon).fetch(start: date, end: date.addingTimeInterval(60 * 60 * 24 * 30)) {
|
||||
XCTAssertEqual($0.count, 43200)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(macOS 12.0.0, *)
|
||||
func testBatchRequestPlanetCoordinates() async {
|
||||
let batch = await PlanetsRequest(body: .moon).fetch(start: date, end: date.addingTimeInterval(60 * 60 * 24 * 30))
|
||||
XCTAssertEqual(batch.count, 43200)
|
||||
}
|
||||
|
||||
static var allTests = [
|
||||
("testCoordinatePerformance",testCoordinatePerformance,
|
||||
"testHouseCuspsPerformance", testHouseCuspsPerformance,
|
||||
"testRiseTimePerfomance", testRiseTimePerfomance,
|
||||
"testSetTimePerformance", testSetTimePerformance,
|
||||
"testLunationPerformance", testLunationPerformance,
|
||||
"testAspectPerformance", testAspectPerformance,
|
||||
"testSpringEquinoxDatePerformance", testSpringEquinoxDatePerformance,
|
||||
"testAutumnalEquinoxDatePerformance", testAutumnalEquinoxDatePerformance,
|
||||
"testBatchRequestPlanetCoordinates", testBatchRequestPlanetCoordinates)
|
||||
]
|
||||
static var allTests = [
|
||||
("testCoordinatePerformance",testCoordinatePerformance,
|
||||
"testHouseCuspsPerformance", testHouseCuspsPerformance,
|
||||
"testRiseTimePerfomance", testRiseTimePerfomance,
|
||||
"testSetTimePerformance", testSetTimePerformance,
|
||||
"testLunationPerformance", testLunationPerformance,
|
||||
"testAspectPerformance", testAspectPerformance,
|
||||
"testSpringEquinoxDatePerformance", testSpringEquinoxDatePerformance,
|
||||
"testAutumnalEquinoxDatePerformance", testAutumnalEquinoxDatePerformance,
|
||||
"testBatchRequestPlanetCoordinatesDeprecated", testBatchRequestPlanetCoordinatesDeprecated)
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue