Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題

7,661 views

Published on

Published in: Technology
  • Be the first to comment

『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題

  1. 1. 『How to build a High Performance PSGI/Plack Server』のその後と ISUCON3を受けての話題 Shibuya Plack/PSGI Conference (shibuya.pl) #1 #plackcon Masahiro Nagano @kazeburo 13年11月20日水曜日
  2. 2. Me • • • • • 13年11月20日水曜日 長野雅広 Masahiro Nagano @kazeburo PAUSE: KAZEBURO Operations Engineer, Site Reliability LINE Corp. Development support on LINE Familly, livedoor
  3. 3. ISUCON3 優勝しました! We used nginx, Proclet, Starlet, Imager, Kossy 13年11月20日水曜日
  4. 4. WEB+DB PRESS Vol.78 (2013年12月発売) Perl Hackers Hub 【第23回】Plack/PSGI 実践入門 13年11月20日水曜日
  5. 5. YAPC::Asia 2013 Tokyo http://www.slideshare.net/kazeburo/yapc2013psgi-plack 13年11月20日水曜日
  6. 6. Summary of Slide • Monoceros • Plack/PSGI Basics • How to build a high performance PSGI/Plack server • 13年11月20日水曜日 Introduction of PSGI servers on CPAN
  7. 7. Performance Techniques for PSGI/Plack server • Prefork • no accept serialization • TCP_DEFER_ACCEPT • non blocking IO / reduce system calls • XS HTTP Parser • TCP_NODELAY 13年11月20日水曜日
  8. 8. その後にやったこと 13年11月20日水曜日
  9. 9. Monoceros 編 13年11月20日水曜日
  10. 10. 1. accept4(2) 13年11月20日水曜日
  11. 11. 13年11月20日水曜日
  12. 12. Set FD_CLOEXEC and O_NONBLOCK in one system call select(16, [4 10], NULL, NULL, {1, 0}) = 1 (in [4], left {0, 999997}) accept(4, {sa_family=AF_INET, sin_port=htons(41296), sin_addr=inet_addr("127.0.0.1")}, [16]) = 6 ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffc03016c0) = -1 EINVAL (Invalid argument) lseek(6, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffc03016c0) = -1 EINVAL (Invalid argument) lseek(6, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) fcntl(6, F_SETFD, FD_CLOEXEC) = 0 fcntl(6, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 setsockopt(6, SOL_TCP, TCP_NODELAY, [1], 4) = 0 read(6, "GET / HTTP/1.0rnHost: localhost:"..., 131072) = 82 gettimeofday({1381121587, 895814}, NULL) = 0 write(6, "HTTP/1.1 200 OKrnDate: Mon, 07 O"..., 112) = 112 close(6) 13年11月20日水曜日 = 0
  13. 13. Set FD_CLOEXEC and O_NONBLOCK in one system call select(16, [4 10], NULL, NULL, {1, 0}) = 1 (in [4], left {0, 999997}) accept4(4, {sa_family=AF_INET, sin_port=htons(42605), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_CLOEXEC| SOCK_NONBLOCK) = 6 ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffc03016c0) = -1 EINVAL (Invalid argument) lseek(6, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffc03016c0) = -1 EINVAL (Invalid argument) lseek(6, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) setsockopt(6, SOL_TCP, TCP_NODELAY, [1], 4) = 0 read(6, "GET / HTTP/1.0rnHost: localhost:"..., 131072) = 82 gettimeofday({1381121587, 895814}, NULL) = 0 write(6, "HTTP/1.1 200 OKrnDate: Mon, 07 O"..., 112) = 112 close(6) 13年11月20日水曜日 = 0
  14. 14. パフォーマンスの変化はなかった。。。 13年11月20日水曜日
  15. 15. 2. :unix PerlIO 13年11月20日水曜日
  16. 16. select(16, [4 10], NULL, NULL, {1, 0}) 何コレ? = 1 (in [4], left {0, 999997}) accept4(4, {sa_family=AF_INET, sin_port=htons(42605), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_CLOEXEC|SOCK_NONBLOCK) = 6 ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffc03016c0) = -1 EINVAL (Invalid argument) lseek(6, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) ioctl(6, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffc03016c0) = -1 EINVAL (Invalid argument) lseek(6, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) setsockopt(6, SOL_TCP, TCP_NODELAY, [1], 4) = 0 read(6, "GET / HTTP/1.0rnHost: localhost:"..., 131072) = 82 gettimeofday({1381121587, 895814}, NULL) = 0 write(6, "HTTP/1.1 200 OKrnDate: Mon, 07 O"..., 112) = 112 close(6) 13年11月20日水曜日 = 0
  17. 17. :perlio adds these 13年11月20日水曜日
  18. 18. :unix PerlIO sub do_accept { my $self = shift; use open 'IO' => ':unix'; my ($conn,$peer); $peer = accept4($conn,$self->{listen_sock}); return ($conn, $peer); } 13年11月20日水曜日
  19. 19. :unix PerlIO select(16, [4 10], NULL, NULL, {1, 0}) = 1 (in [4], left {0, 999997}) accept4(4, {sa_family=AF_INET, sin_port=htons(42605), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_CLOEXEC|SOCK_NONBLOCK) = 6 setsockopt(6, SOL_TCP, TCP_NODELAY, [1], 4) = 0 read(6, "GET / HTTP/1.0rnHost: localhost:"..., 131072) = 82 gettimeofday({1381121587, 895814}, NULL) = 0 write(6, "HTTP/1.1 200 OKrnDate: Mon, 07 O"..., 112) = 112 close(6) 13年11月20日水曜日 = 0
  20. 20. パフォーマンスほぼ変わらなかった。。。 13年11月20日水曜日
  21. 21. 3. sendfile(2) 13年11月20日水曜日
  22. 22. 13年11月20日水曜日
  23. 23. read(7, "GET /static/jquery-1.10.2.min.js"..., 131072) = 185 open("./jquery-1.10.2.min.js.gz", O_RDONLY) = 9 write(7, "HTTP/1.1 200 OKrnDate: Wed, 20 N"..., 213) = 213 read(9, "372131010344207361Q03jquery-1.10.2.min.js0254"..., 8192) = 8192 read(9, "3402632542327315d344v3216jY346"..., 8192) = 8192 read(9, "2335|G3i1204205?3742514[,}u235"..., 8192) = 8192 read(9, "361307N-ns254212370p)`*276276"..., 8192) = 8192 read(9, "25027323263k10", 8192) = 7 read(9, "", 8192) = 0 brk(0x2eed000) = 0x2eed000 write(7, "372131010344207361Q03jquery-1.10.2.min.js0254"..., 32775) = 32775 close(7) 13年11月20日水曜日 = 0
  24. 24. read(7, "GET /static/jquery-1.10.2.min.js"..., 131072) = 185 open("./jquery-1.10.2.min.js.gz", O_RDONLY) = 9 write(7, "HTTP/1.1 200 OKrnDate: Wed, 20 N"..., 213) = 213 lseek(9, 0, SEEK_CUR) = 0 sendfile(7, 9, [0], 32775) close(7) 13年11月20日水曜日 = 32775 = 0
  25. 25. sendfile(2) benchmark jquery-min.js(90KB) Req/Sec 1471 1500 1125 1121 750 375 0 no-sendfile 13年11月20日水曜日 sendfile
  26. 26. ISUCON3 編 13年11月20日水曜日
  27. 27. ISUCON3予選のPerlアプリケーションの初期スコアが Rubyのそれより悪かったのでごにょごにょやっていた Ruby/Perl 初期スコア 3000 2361 2250 1500 865 750 0 Ruby 13年11月20日水曜日 Perl
  28. 28. やったこと ✓ ✓uri_forのキャッシュ ✓Response->finalizeの最適化 Plack::Middleware::Session::Simple ✓ ✓Monocerosアップデート ✓改造Starlet Kossy 13年11月20日水曜日
  29. 29. 改造 Starlet の中身 https://github.com/kazeburo/isucon3qualifier-myhack/blob/master/lib/Starlet/Server.pm 13年11月20日水曜日
  30. 30. 改造 Starlet • • • • • 13年11月20日水曜日 no use IO::Socket’s methods AnyEvent::Util::fh_nonblocking accept4(2) sendfile(2) supports unix domain socket (starmanはサポートしている)
  31. 31. unix domain socket $ plackup -s Starlet --socket-path /tmp/app.sock --max-workers 4 --max-reqs-per-child 1000 --min-reqs-per-child 800 -E production -a app.psgi 13年11月20日水曜日
  32. 32. nginx.conf upstream apps { #server localhost:5000; server unix:/tmp/app.sock; } location / { proxy_set_header Host $host; proxy_pass http://apps; } 13年11月20日水曜日
  33. 33. benchmark Kossy “Hello World” req/sec 11534.51 12000 9000 7974.09 6000 3000 0 tcp 13年11月20日水曜日 unix
  34. 34. ISUCON本選では使ってない。。。 13年11月20日水曜日
  35. 35. ISUCON本選では使ってない。。。 TCPでListenしないからデバックしにくい 試す時間がなかった 使ったとしても効果は限定的だったと思われる 13年11月20日水曜日
  36. 36. Plack/PSGIと パフォーマンスと 私とまとめ 13年11月20日水曜日
  37. 37. 普通のアプリケーション 数十msec∼ 数百msec アプリケーション側のコスト >>>>> (超えられない壁) >>>>> Plack/PSGIレイヤーのコスト 数msec∼ 数百μsec 13年11月20日水曜日
  38. 38. 特殊なアプリケーション eg: Games, advertisement, Large Scale SNS 数msec∼ 数十msec アプリケーション側のコスト >>> Plack/PSGIレイヤーのコスト 数msec∼ 数百μsec 13年11月20日水曜日
  39. 39. Improve Plack/PSGI • PSGI/Plackの適用領域を広げる = Perlの適用領域を広げる • 大規模サービスでのコスト削減 (Perlで働けるところ増えて、給料も増えてuma-) 13年11月20日水曜日
  40. 40. Found Problems? Github issues, pull reqs IRC, @kazeburo 13年11月20日水曜日
  41. 41. #fin. thank you 13年11月20日水曜日

×