Skip to content

Instantly share code, notes, and snippets.

@finestructure
Created January 28, 2023 12:25
Show Gist options
  • Save finestructure/91f7d755c7d966751fd1a23e64b03013 to your computer and use it in GitHub Desktop.
Save finestructure/91f7d755c7d966751fd1a23e64b03013 to your computer and use it in GitHub Desktop.
ELF vs async/await behaviour test program
import Foundation
import NIO
extension Array where Element == EventLoopFuture<Void> {
/// Converts a collection of `EventLoopFuture<Void>`s to an `EventLoopFuture<Void>`.
///
/// Acts as a helper for the `EventLoop.flatten(_:[EventLoopFuture<Value>])` method.
///
/// let futures = [el.future(1), el.future(2), el.future(3), el.future(4)]
/// let flattened = futures.flatten(on: el)
/// // flattened: EventLoopFuture<Void>
///
/// - parameter eventLoop: The event-loop to succeed the futures on.
/// - returns: The succeeded future.
public func flatten(on eventLoop: EventLoop) -> EventLoopFuture<Void> {
return .andAllSucceed(self, on: eventLoop)
}
}
struct Database {
var eventLoopGroup: EventLoopGroup
var eventLoop: EventLoop {
eventLoopGroup.next()
}
}
struct BuildTriggerInfo {
var packageId: Package.Id
var versionId: Int
var pairs = Array(0..<5)
}
func findMissingBuilds(_ database: Database,
packageId: Package.Id) -> EventLoopFuture<[BuildTriggerInfo]> {
database.eventLoop.makeSucceededFuture([
BuildTriggerInfo(packageId: packageId, versionId: 0),
BuildTriggerInfo(packageId: packageId, versionId: 1),
])
}
struct Response {
}
struct Build {
var id: UUID
static func trigger(database: Database) -> EventLoopFuture<Response> {
print("\(Date()): trigger")
sleep(1)
return database.eventLoop.makeSucceededFuture(.init())
}
func create(on database: Database) -> EventLoopFuture<Void> {
database.eventLoop.makeSucceededVoidFuture()
}
}
func triggerBuildsUnchecked(on database: Database,
triggers: [BuildTriggerInfo]) -> EventLoopFuture<Void> {
print("triggerBuildsUnchecked: \(triggers.count) triggers")
return triggers.flatMap { trigger -> [EventLoopFuture<Void>] in
print("triggerBuildsUnchecked: \(trigger.pairs.count) triggers")
return trigger.pairs.map { pair in
return Build.trigger(database: database)
.flatMap { response in
Build(id: .init()).create(on: database)
}
}
}
.flatten(on: database.eventLoop)
}
struct Package {
typealias Id = Int
var id: Id
}
@main
public struct nio_test {
public static func main() async {
elf()
print("--------------------")
await asyncAwait()
}
static func elf() {
print("ELF")
let group = MultiThreadedEventLoopGroup(numberOfThreads: 8)
let database = Database(eventLoopGroup: group)
let packages = (0..<2)
let start = Date()
print("packages: 2")
try? packages.map {
findMissingBuilds(database, packageId: $0).flatMap {
triggerBuildsUnchecked(on: database, triggers: $0) }
}
.flatten(on: database.eventLoop)
.wait()
let elapsed = Date().timeIntervalSince(start)
print("elapsed: \(elapsed)")
}
static func asyncAwait() async {
print("asyncAwait")
let group = MultiThreadedEventLoopGroup(numberOfThreads: 8)
let database = Database(eventLoopGroup: group)
let packages = (0..<2)
let start = Date()
await withThrowingTaskGroup(of: Void.self) { group in
for package in packages {
group.addTask {
let triggerInfo = try await findMissingBuilds(database, packageId: package).get()
try await triggerBuildsUnchecked(on: database, triggers: triggerInfo).get()
}
}
}
let elapsed = Date().timeIntervalSince(start)
print("elapsed: \(elapsed)")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment