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

Server Side Swift実用性評価 2017 #iosdc #b

ainame
September 17, 2017

Server Side Swift実用性評価 2017 #iosdc #b

ainame

September 17, 2017
Tweet

More Decks by ainame

Other Decks in Programming

Transcript

  1. 話すこと/話さないこと 話す • Server Side Swift(SSS)実際にやってみた事例 / 良い点・苦労する点 • Redis

    • 今後SSS環境への希望 話さない • Web開発、vapor / Kitsura / Perfect などのFrameworkの詳細 • swift-server/http プロジェクト
  2. Swift OSS化 • 2015年末〜Swift + 各種ライブラリがOSS化 ◦ apple/swift - 本体

    ◦ apple/swift-package-manager - パッケージ管理 ◦ apple/swift-corelibs-foundation - 非Apple環境でも動くFoundation ◦ apple/swift-corelibs-libdispatch - Concurrency用Framework a.k.a GCD ◦ apple/swift-corelibs-xctest - ユニットテスト用Framework ◦ apple/swift-llvm, swift-clang, swift-lldb - Compiler & Debugger
  3. Swift Foundation App Standard Library Core Foundation Darwin or Glibc

    Dispatch C Library システムコール などOSに依存するレ イヤー
  4. Server Side Swiftとは? (とても)頑張ればなんでも書けるはず • アプリケーション(Web API, Web Page, Job

    Queue, gRPC, …) • ミドルウェア(Web Server, KVS, DB, 各種Agent, ...) • 各種スクリプト(Cron, 書き捨て, ...) Linux上で動いたらだいたいServer Side Swiftでは?? (現状Ubuntu上でapt install swift出来ない...)
  5. Redis Web/Rails app Cron/Rails runner One-off scripts Worker Worker Worker

    Worker Ruby on Rails • DB処理 • メール・Push通知送信 • Webクローラー • 動画エンコーダー など... Sidekiq http://sidekiq.org/about
  6. class VideoEncodeWorker include Sidekiq::Worker def perform(video_id, size) video = Video.find(video_id)

    encoded_file = VideoEncoder.new.encode(video, size) FileUploader.new.upload(encoded_file, to: key) end end class VideosController < ApplicationController def create @video = Video.create!(video_params) ["1920x1080", "1270x720", "960x540"].each do |size| VideoEncodeWorker.perform_async(@video.id, size) end { status: "OK" } end end
  7. Redis Web/Rails app Cron/Rails runner One-off scripts Worker Worker Worker

    Worker Swift環境 • DB処理 • メール・Push通知送信 • Webクローラー • 動画エンコーダー など... Sidekiq http://sidekiq.org/about Lumpik Vapor/Kituraなどが既にある 参入者いない〜!
  8. import Foundation import Lumpik class EchoWorker: Worker { struct Args:

    Argument { var message: String } var jid: Jid? var queue: Queue? var retry: Int? required init() {} func perform(_ args: Args) throws { print(args.message) sleep(3) } }
  9. 移植方法 • OSS版Swift/Swift Package Manager + Xcode上で書いた ◦ swift package

    generate-xcodeproj • Ruby版の実装を元に可能な限り同じロジックで実装 ◦ Rubyと同じものがほぼ実装できる • VaporのRedisクライアントなどを利用 ◦ SwiftのRedisクライアントの中で一番使いやすい • 各種言語の標準ライブラリから実装方法を学ぶ ◦ RubyのProcess.daemonを元に他にも ainame/Swift-Daemon を作った
  10. 悪かった • 定番のライブラリが整っていない ◦ Foundation がカバーしてないコアな部分にオレオレ実装多い ◦ Socket通信とか ◦ 依存が増えてダルい

    • CompletionHandler問題 ◦ 既存のURLSessionとかもしくはIO処理するコードには completionHandlerを取るものが多い ◦ 他のサーバーサイド言語のようには書きづらい ... • 思ったより早くない(なかった) ◦ ボトルネックがなんなのかは正確に知る必要がある
  11. Performance Tuning • Pipelining (Redis特有の方法) https://redis.io/topics/pipelining ◦ 1度のIO処理で複数のコマンドを実行する方法 ◦ Redisサーバー/クライアント間のRTT(Round

    Trip Time)が減る ◦ send/recvシステムコールのuser land -> kernel landへのcontext switchが減る • Buffered-IO ◦ send/recv システムコールを減らすためメモリ上のバッファを活用
  12. Pipelining 非Pipelining • Client: INCR X • Server: 1 •

    Client: INCR X • Server: 2 • Client: INCR X • Server: 3 • Client: INCR X • Server: 4 Pipelining • Client: INCR X • Client: INCR X • Client: INCR X • Client: INCR X • Server: 1 • Server: 2 • Server: 3 • Server: 4 一度ずつの write/readで済む
  13. 感想 • Cのライブラリが使えばとりあえず何でも動かすのはできる ◦ 今の所OS毎の対応を自前で対応する努力が必要 • Swiftで書くモチベーションとは ◦ IO周りのライブラリがとにかく貧弱 ◦

    それ他の言語でも出来るのでは・・・? ◦ (自分の場合はミドルウェアを作る方法を実際に作って学びたかった) • 既存のフレームワーク、痒いところに手が届かない(今回の例では) ◦ Pipelining, Transactionなどの普通っぽい実装が無い