Upgrade to Pro — share decks privately, control downloads, hide ads and more …

挑戦!ISUCON de Server-side Swift 〜タイムゾーンには気をつけろ〜

freddi(Yuki Aki)
September 11, 2022
1.4k

挑戦!ISUCON de Server-side Swift 〜タイムゾーンには気をつけろ〜

iOSDC Japan 2022
Special Thanks: http://www.ankokukoubou.com/font/onryou.htm

freddi(Yuki Aki)

September 11, 2022
Tweet

Transcript

  1. ISUCONとは、かの有名なイスカンダル(アレクサンドロス3世)が 
 紀元前320年頃に開いた異国の椅子品評会にルーツが遡る。その際、 
 かの王がこの品評会の名前を考得ていたところ、家臣の一人が「 
 椅子だしイスコンテストでいいんじゃないんすか?w」と放ち、 
 イスカンダル王が絶賛。以降その品評会はイスコンテストと呼ば れることになる。日本には安土桃山時代にシルクロードから伝わり、

    
 楽市楽座で活発に行われるようになる。かの織田信長が打たれた本 能寺の変では、このイスコンテスト落選に腹を立てた明智光秀が 
 腹いせに矢を寺にはなったところから始まるというただのとばっ 
 ちりの説がある。その後、名前の呼び方が訛り、明治時代には 
 ついにイスコンという名前に。第二次大戦などで中止になるものの、 
 現在までに毎年コンテストが開かれて、現在に至る
  2. ス ウ ィ フ ト を 愛 し ス ウ

    ィ フ ト に 愛 さ れ た 者 チ | ム 何 も わ か 
 ら ん
  3. こんな感じに! routes.get("firstUser") { req async throws -> String in guard

    let user = try await User.query(on: req.db).first() else { throw Abort(.notFound) } user.lastAccessed = Date() try await user.update(on: req.db) return user.name }
  4. Q. あれ?でも Swift Concurrency ってその時安定してたの? A. いろいろと使うのには手間があった Swift Toolchain のインストール

    サーバーがLinuxなのでインストール方法の工夫 デバッグが効かない(LLDB) < だいたいやっといたでw
  5. // swift-tools-version:5.3 import PackageDescription let package = Package( name: "isucon11",

    platforms: [ .macOS(.v10_15) ], dependencies: [ .package(url: "https://github.com/vapor/vapor.git", .branch("async-await")), .package(url: "https://github.com/vapor/mysql-kit.git", from: "4.0.0"), .package(url: "https://github.com/Flight-School/AnyCodable", from: "0.6.0"), .package(url: "https://github.com/vapor/jwt-kit.git", from: "4.0.0"), ], targets: [ .target( name: "App", dependencies: [ .product(name: "Vapor", package: "vapor"), .product(name: "MySQLKit", package: "mysql-kit"), .product(name: "JWTKit", package: "jwt-kit"), .product(name: "AnyCodable", package: "AnyCodable") ], swiftSettings: [ .unsafeFlags(["-cross-module-optimization"], .when(configuration: .release)), // Disable availability checking to use concurrency API on macOS for development purpose // SwiftNIO exposes concurrency API with availability for deployment environment, // but in our use case, the deployment target is Linux, and we only use macOS while development, // so it's always safe to disable the checking in this situation. .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]) ] ), .target(name: "Run", dependencies: [.target(name: "App")]) ] ) Package.swift (+ k8s などの設定ファイル) 作れば開発可能!
  6. 謎のPayload 上限 public func collect(max: Int? = 1 << 14)

    -> EventLoopFuture<ByteBuffer?> { switch self.request.bodyStorage { case .stream(let stream): return stream.consume(max: max, on: self.request.eventLoop).map { buffer in self.request.bodyStorage = .collected(buffer) return buffer } case .collected(let buffer): return self.request.eventLoop.makeSucceededFuture(buffer) case .none: return self.request.eventLoop.makeSucceededFuture(nil) } } max: Int? = 1 << 14 https://github.com/vapor/vapor/blob/45bc9ab1e3c4ba309606762664fc18358b7c92e5/Sources/Vapor/Request/Request%2BBody.swift#L38
  7. 謎のPayload 上限 max: Int? = 1 << 14 1 <<

    14 = 0b100000000000000 0b100000000000000 = 16(KB)
  8. ひ ょ っ と し て そ れ は ギ

    ャ グ と し て い っ て い る の か 💧 💧
  9. @discardableResult @_disfavoredOverload public func values(_ values: Encodable...) -> Self {

    let row: [SQLExpression] = values.map(SQLBind.init) self.insert.values.append(row) return self } @discardableResult public func values(_ values: SQLExpression...) -> Self { self.insert.values.append(values) return self } SQLクエリを組み立てる関数 https://github.com/vapor/sql-kit/blob/3c5413a229bc2abc962dab17ea66d25e448ad344/Sources/SQLKit/Builders/SQLInsertBuilder.swift#L94 謎のオーバーロード
  10. @discardableResult @_disfavoredOverload public func values(_ values: Encodable...) -> Self {

    let row: [SQLExpression] = values.map(SQLBind.init) self.insert.values.append(row) return self } @discardableResult public func values(_ values: SQLExpression...) -> Self { self.insert.values.append(values) return self } SQLクエリを組み立てる関数 https://github.com/vapor/sql-kit/blob/3c5413a229bc2abc962dab17ea66d25e448ad344/Sources/SQLKit/Builders/SQLInsertBuilder.swift#L94 こっち呼んでるつもり 謎のオーバーロード
  11. SQLクエリを組み立てる関数 https://github.com/vapor/sql-kit/blob/3c5413a229bc2abc962dab17ea66d25e448ad344/Sources/SQLKit/Builders/SQLInsertBuilder.swift#L94 こっち呼ばれる ちゃんとクエリ 
 つくってくれない @discardableResult @_disfavoredOverload public func

    values(_ values: Encodable...) -> Self { let row: [SQLExpression] = values.map(SQLBind.init) self.insert.values.append(row) return self } @discardableResult public func values(_ values: SQLExpression...) -> Self { self.insert.values.append(values) return self } こっち呼んでるつもり 謎のオーバーロード
  12. SQLクエリを組み立てる関数 https://github.com/vapor/sql-kit/blob/3c5413a229bc2abc962dab17ea66d25e448ad344/Sources/SQLKit/Builders/SQLInsertBuilder.swift#L94 こっち呼ばれる ちゃんとクエリ 
 つくってくれない @discardableResult @_disfavoredOverload public func

    values(_ values: Encodable...) -> Self { let row: [SQLExpression] = values.map(SQLBind.init) self.insert.values.append(row) return self } @discardableResult public func values(_ values: SQLExpression...) -> Self { self.insert.values.append(values) return self } こっち呼んでるつもり @_disfavoredOverload 謎のオーバーロード