ぱろっと・すたじお

技術メモなどをまったりと / my site : http://parrot-studio.com/

モバイルブラウザでクリックの動作が遅い問題の対応(改善編)

相変わらず開発を続けている「チェンクロパーティーシミュレーター」ですが・・・


Get our light! - チェンクロパーティーシミュレーター

・・・昨年末に「部分的でもいいからスマフォ対応が欲しい」という要望をいただきまして

「パーティーを編集する仕組み」として考えると、
スマフォの狭い画面ではいろいろ設計が面倒なのですが、
「データを見るだけ」であれば、専用の画面を作ればいけるかなと

「データを見るだけモード」は元々ToDoに入れて放置していたのですが、
今回の要望とあわせ、イメージが湧いたので、
現在ごりごりと実装しております...φ(・ω・`)

まあ、裏のAPIは同じでViewを差しかえるだけですので、
大雑把なプロトタイプはすぐに完成し、
試しにサーバに突っ込んで実機テストしてみたのですが・・・

・・・いろいろ動作が怪しすぎて、使い物になりませんでした(´・ω・`)

どうもクリック周りの動作が怪しいのです
最初の2回くらいはまともなのですが、
そのうちイベントが取れなくなり、最後には固まるという・・・

そもそも、タブレットで動作させた時にも、
クリック周りで怪しい動きがあったのですが、
見なかったことにしていたんですよね・・・Σ(・ω・ノ)ノ

今回はそういうわけにいかないので、いろいろ調査してみたところ、
たぶん「Hammer.js」が原因、というところに行き着きました

そもそもこのライブラリをなんで使ったのかというと、
タブレットのブラウザでクリック動作が遅かったからなのです


「チェンクロパーティーシミュレーター」を公開しました - ぱろっと・すたじお

Hammer.jsはいろいろなイベントを実装する上で、
クリックの動作も改善していたわけですが、
「汎用的にいろいろ作り込まれていて、影響が大きい」のも事実です

最初のうちはHammer.jsでいろいろやろうとしていたのですが、
今使っているのは結果的に「クリックの反応速度改善」だけであり、
もっと軽いのはないのか・・・と調べ始めました

そして見つけたのがこちらです(´・ω・)っ


ftlabs/fastclick · GitHub


JavaScript - FastClickを使った体感応答時間の短縮テスト - Qiita

その名の通り、クリック速度の改善に特化されており、
ライブラリもシンプルで、組み込みやすくなってます

しかも、Hammer.jsと違い、イベントの記述は一般的な
「$(hoge).on 'click'」とかでよく、コードもシンプルで良いです(`・ω・´) b

とはいえ、やはりイベントに割り込んで動作するライブラリのため、
他のライブラリ(盲点なレベルだとBootstrap)等と、
競合しておかしくなる可能性は十分にあります

当たり前のことですが、動作確認はしっかりと(´-ω-)


・・・とまあ、これで終わってもいいのですが、
今回の話には落ちがありまして

サーバに改善版をUPし、実機でテストしてもOKだったので安心していたら、
コードに記述漏れがあり、ライブラリは読み込んでいたけど、
イベントは適用されてない状態でしたΣ(゚Д゚)ガーン

でも、実機でテストしたときにクリックの違和感はなかったわけです
だとすると、元々私が「遅い」と感じたクリックはどこへ・・・
という疑問が湧きます

私のスマフォはAndroidで、ブラウザはChromeですので、
先ほどの実験記事にある「対策済み」のパターンに該当しますし、
元々スマフォでは「編集できない」という表示テストしかしてません

しかし、タブレットiPad miniで、OSは7で留めてますので、
Safariのバージョンはリリース当初と変わってないはずなんですよね・・・

・・・まあ、今まともに動いているからいいかΣ(・ω・ノ)ノ

「Rubyのしくみ」 "10.times do"から始まる冒険

お正月って、あらゆる気力を奪われる時期なわけですよ

長期休みって意味では夏休みも変わらないはずなのに、
世間の空気感も含めて、全力で怠惰になるというか、
ゲームをやる気力すら削がれるというかc(・ω・`c )っ

そのうち布団から出るのすら面倒になり、
布団の中で積んでいた漫画を崩した結果、読むものがなくなり、
ついに積んでいた技術書を崩し始める・・・そんな時期なのでございます

・・・というのがどこまで本当かはともかくとして、
お正月にだらだらと読んでいた本がこちらに(´・ω・)っ

Rubyのしくみ -Ruby Under a Microscope-

Rubyのしくみ -Ruby Under a Microscope-

Rubyist Magazine - 書籍紹介『Rubyのしくみ Ruby Under a Microscope』

「プログラム(言語)とは、結局のところメモリの書き換えである」と、
セガの方もおっしゃっていましたが・・・


「プログラミングを教える」ということ - ぱろっと・すたじお

・・・「言語がどのようにメモリを使っているか?」は、
言語を深く理解する上では重要な概念ですし、
少なくともパフォーマンスチューニングにおいては必須です*1

実際、新人時代からJavaを書いていたものの、
「感覚的に理解した」のはこちらの本を読んだときです

Java 謎+落とし穴 徹底解明 (標準プログラマーズライブラリ)

Java 謎+落とし穴 徹底解明 (標準プログラマーズライブラリ)

この本もJavaのメモリ管理について解説されており、
「参照」とは何なのか、GCは何をしているのかが理解できまして、
それ以降ぬるぽ*2を作り込むことが圧倒的に減りました( ゚д゚)o彡゚

その後、Javaを離れてRubyを書き始めたときも、
最初のうちはJavaっぽいコードを書いていたものの、
本質的にRubyっぽいコードに近づき始めたのは、こちらを読んだときです

Rubyソースコード完全解説
http://i.loveruby.net/ja/rhg/book/

この本・・・というかサイト(RHGと略すらしい)は有名でして、
Rubyを深く知りたい方はたいてい目を通しているはずですが、
どうにも解説しているバージョンが古い、という問題がありました(´-ω-)

その「RHGの現代版」と言えるのが先ほどの本でして、
本質的な狙いはほぼ同じです

とはいえ、私自身はC言語に明るいわけではなく、
Brainf**kの評価器を作れる程度の知識*3はあっても、
正直YARVの解説は難しすぎて、完全に理解することはできません(´・ω・`)

とはいえ、表面的にでも「何をしたいのか?」は読み取れますし、
5章以降のオブジェクトに始まる一連の話は、
C言語の細かい知識がなくても十分にわかります

Rubyにおいて全てがオブジェクト=メモリの束で管理されているなら、
オブジェクトの構造が理解できれば、Rubyの本質的な部分が、
かなりのレベルで見えてくるんじゃないかと(`・ω・´) *4

そもそもRuby自体(おそらくはLisp等と同じく)、
「概念」とか「理想」がまずあって、それを「実装」している感じで、
その「概念」自体はわりとシンプルで合理的なわけです*5

つまり、「何に使うか?」という「目的」ではなく、
「こういう言語にしたい」という「理想」が起点だと思っているので、
そのあたりの「意図」を読み取れれば、後は応用なのかな・・・と思います

逆に、「概念」や「理想」が先行しているからこそ、
JRubyやRubiniusのような他の処理系も存在できるわけで、
そのあたりの解説も面白いものになってます

「黒魔術」と言われがちなRubyが、
実際のところ「合理性の塊」であることがよくわかるという意味でも、
この本は面白いですし、おすすめします・・・が・・・


・・・やっぱり難しい本だと思います、ええ(´-ω-)

*1:メソッドの呼び出し」すらも、突き詰めればメモリ管理の問題です そのあたりの理解を助けるのに、平山さんの本はとても優れてます

*2: ガッ

*3: ネタプログラミング言語クリエイターYouma (Gunma.web #8) - ぱろっと・すたじお

*4: RHGを読んでいても、「Module#prepend」がどう実装されているのかはわからないのですが、この本を読むとすっきりします(`・ω・´) b

*5: 例:「全てはオブジェクトである」「(たとえ演算子であっても)全てはメソッド呼び出しである」etc...

「エンジニアでも恋がしたい」(・・・らしいが、いくらなんでも展開が早すぎるやろ)を解いた件

POH!も4回目ですってよ、奥様(`・ω・´)


マンガ版「エンジニアでも恋がしたい!」〜転職初日にぶつかった女の子が同僚だった件〜|paizaオンラインハッカソン4 Lite

今回は評価点の高低でストーリー分岐する仕組みだったわけですが、
過去3回に比べると、一番簡単な内容だったと思います
たぶん、1回目と同じくらいかもしれません


「女子大生とペアプロするだけの簡単なお仕事」でSSSをとるまでに考えたこと - ぱろっと・すたじお


「女子大生とペアプロ問題」の言語別通過率を分析してみる - ぱろっと・すたじお


天才火消しエンジニア霧島さんのトラップに引っかかった件 - ぱろっと・すたじお

今回は間口を広げるための回だったようで、
ITmedia等でも取り上げられました


プログラミングでストーリーが変わるぞ! Webマンガ「エンジニアでも恋がしたい!」公開 - ねとらぼ

今回の特徴は、3問連続で突破しないといけないところです

しかし、1問目2問目は足切り問題であり、
「職業プログラマがこれを即座に書けないとマジで話にならない」レベル*1で、
3問目の問題が本命です

とはいえ、3問目も100点が取れない場合にヒントが出るため、
その単語でググってアルゴリズムを押さえれば解けてしまいますがΣ(゚Д゚)ガーン

ポイントは「O(mn)」の計算量を、いかにして「O(n)」にするか・・・なのですが、
アルゴリズム自体はすぐ出てくるわけで、
後はどう効率的なコードにするか、だけでしょう*2

今回は簡単なため、私の解答は「続きを読む」に貼っておきます
ぜひ自力で解いてみてください


・・・なお、どうでもいいことですが、
個人的には100点の水着より60点の浴衣の方が好みですΣ(・ω・ノ)ノ



<追記>
CoffeeScriptでも書いてみたのですが、
3問目のTestCase4でエラーになりますΣ(゚Д゚)ガーン

配列のindexが間違っているのかと思って、
デバッグ文とか突っ込んだりしてみたのですが・・・
アルゴリズムは全く同じなんですけどね

*1: それこそ、面接でこれを書いてくださいと言われてもおかしくないレベル

*2: 実際、名前そのものは知らなくても、よく使うアルゴリズムだとは思います というか、使ってたのにな・・・(´-ω-)

続きを読む

今さらOGPとTwitterCardについて調べてみた

Facebookのような「THE・リア充空間」に全く縁のない私ですが、
最近になってやっと「Open Graph protocol」(OGP)というものの存在を知りました


The Open Graph protocol

最近はてなにRO(+α)のBlogを移転して気づいたのですが、
URLを貼り付ける際に開く選択で、「埋め込み形式」ってのがあります

例えばこんな感じで(´・ω・)っ


新しいスマフォゲーを試そう・その1 - あるネットゲーマーの日常

当然、この方が見栄えがいいし、
この形式が並んでいる中に非対応のサイトがあると、
浮いて見えたり目立たなかったりするわけです
(ゲームのBlogで画像多めなので余計に)

なので、「埋め込みが可能になる条件」を調べていて、
たどり着いたのがOGPだった・・・というわけです


「ブログカード」をOGPなどに対応しました。さまざまなWebページをコンパクトに整形して掲載できます - はてなブログ開発ブログ

これを見ると、まだ対応して数ヶ月ってレベルだったんですね・・・
Blog移転が10月だったので、いいタイミングでした(`・ω・´) b

さて、私が最近作っているサイトに、
「チェンクロパーティーシミュレーター」というものがあるのですが、
これもOGPに対応させてみました


Get our light! - チェンクロパーティーシミュレーター

自分のBlogで紹介する際、埋もれてしまうのが気になったので・・・(´-ω-)

とはいえ、対応そのものはタグの追加だけなので楽です

<meta property="og:site_name" content=“サイトの名前" />
<meta property="og:title" content="記事タイトル" />
<meta property="og:type" content="website" />
<meta property="og:image" content="記事画像" />
<meta property="og:url" content=“記事のURL" />
<meta property="og:description" content="記事の概要" />

https://github.com/parrot-studio/cc-pt-viewer/blob/master/app/views/layouts/application.html.erb

今回は1ページしかないので適当に書きましたが、BlogなどのCMSでは、
自動でこのあたりのタグを生成する仕組みにすればいいわけです

・・・と、これだけでも十分だったのですが、
はてなBlogにTweetを貼り付けたところ、このように見えました

post内容の下にBlogの概要が表示されています

おそらくOGPが絡んでいるのだろうと、自分のサイトをpostしてみても、
このようには見えなかったので、調べてみました


Twitterカード | Twitter Developers

このように、タグを追加して「申請」しないとダメだそうで(´-ω-)

とはいえ、OGPに対応しておけば、追加するタグはシンプルです

<meta name="twitter:site" content="@parrot_studio">
<meta name="twitter:card" content="summary">

これだけΣ(゚Д゚)ガーン

申請も面倒なのかな・・・と思ったら、わりと簡単でした
(ただし、反映されるまでに少々時間がかかります)


Twitter Cards利用申請 - Qiita

するとこのようになります

これだけで「できるサイト」っぽくなって素敵ですね(`・ω・´)


最近、(いいか悪いかは別として)ニュースをまとめるサイト・アプリが増えていますが、
そこで「埋もれないために」、このような仕組みに対応することも必要かと思います

例えば、私がよく見ているMSNのニュースサイトはこのようなデザインです

http://www.msn.com/ja-jp/news

少なくともOGPに対応していない限り、
「画像付きの見出し」にはならないはずです

これに気づいただけでも、
はてなBlogに移行した価値があったかな・・・と思ってます



むしろ問題は、「この(技術っぽい)Blog」と「RO(+α)のBlog」、
どっちが「私にとってのメインBlogか?」ってことで・・・Σ(・ω・ノ)ノ

もう一度Nginx+Unicorn+Railsを試してみる

もう3年以上前のことですが、一度Unicornを試してはいます


Rails3アプリをnginx+unicornで動かしたら速すぎた - ぱろっと・すたじお

その頃はまだ「運用」に関するノウハウが足りておらず、
サーバ再起動のたびに失敗する起動スクリプト*1を手動で実行するとか、
速さの代償にいろいろ面倒を背負い込んでいる感じでした(´-ω-)

なにより、動かしていたサイト自体が頓挫し、
その後構築していたRO用のシステム*2は、
一つのサーバに複数動かす仕組みだったので、あまりUnicorn向きではありませんでした

(今の仕事でも、Rack以外の部分も含めて統一した運用をしたいということで、
 あえてApache+Passengerという環境で動かしています)

そして今取り組んでいるのがこちらですが・・・


Get our light! - チェンクロパーティーシミュレーター

・・・これを独立したドメインにするか悩んでいて、
とりあえずサーバだけ移行しようかな・・・と考えていたところ、
今月のWEB+DBでRackサーバの記事を読んだわけです*3

WEB+DB PRESS Vol.83

WEB+DB PRESS Vol.83

一つのサーバに一つのアプリならUnicornで問題ないですし、
記事の中でもだいぶ枯れていると紹介されていたので、
いい機会だからやり直してみようかと


以上、経緯と前置きでしたΣ(・ω・ノ)ノ


なお、今回参考にさせていただいたサイトはこちらです

Ruby - Nginx+Unicorn設定ファイルサンプル - Qiita

Unicorn+Rails入門 - Less is Best

Unicornの設定

Unicorn側は3年前とそんなに変わるところがないのですが、
同一サーバの場合はソケットがいいらしいので、
そこが以前と変わったところでしょうか

https://github.com/parrot-studio/cc-pt-viewer/blob/master/config/unicorn.rb

といっても、以前のシステムはソースをGitHubに置いてない*4ので、
比較しようもないわけですが・・・(´・ω・`)

あと、以前は「unicorn_rails」ってコマンドを使っていましたが、
今はただの「unicorn」で起動するのが主流だそうです

Nginxの構築

Passengerの場合、組み込む都合で専用のインストーラーがあったりしますが、
今回はProxy経由なので普通にyumでインストールしただけです

設定ファイルもひな形を作ってくれるツールがあります

https://github.com/i2bskn/nginx_utils

Unicornとの連係を前提にしたconfを出力できるので、
そこだけ指定した形で出力し、細かいところは後からいじりました

upstream backend-unicorn {
  server unix:/path/to/app/tmp/sockets/unicorn.sock;
}
server {
  listen 80;
  server_name ccpts.parrot-studio.com;
  root /path/to/web/root;
  index index.html;
  location / {
    try_files $uri @proxy;
  }
  location @proxy {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://backend-unicorn;
  }
}

「ファイルがあればそのまま返し、なければProxy」って設定が、
これだけ簡単に書けるのはすばらしいですね(`・ω・´) b

まあ、以前からあったのを、当時の私が知らなかっただけ、という可能性も・・・

あとは自動起動スクリプト(for CentOS6.5)ですが、
調べるといろいろ出てきますので、必要なところを書き換えて使用しました
私がやったのは、「unicorn_rails」を「unicorn」に変えた程度です

運用レベルでのPassengerとの違い

PassengerはNginxに組み込まれて動いており、
アプリ再起動のために「restart.txt」の仕組みが存在します
なので、基本的にはアプリの管理を一般ユーザで実行できます

Unicornの場合はアプリ自体をinit.dで自動起動しているため、
実行権限はrootになります
そのため、システムが生成するtmp以下のファイルは、root権限になります

このため、アプリのcacheクリア等*5をsudo経由でやらないといけないのが面倒なのですが、
一般権限でUnicornを動かすような指定も面倒だったので、そこは許容してますΣ(・ω・ノ)ノ

いやまあ、「最近のサーバ管理手法」とかなんとかいろいろあるのはわかりますが、
今回の目的は「Nginx+Unicornで動かすこと」なので、
その辺は "面倒になったら" 考えます


以上、わかっている方には当たり前の話でしたが、
例によって自分用のメモ書きということで...φ(・ω・`)

*1: 今にして思えば、スクリプトの実行順の問題ではないかと思いますが、もう環境を破棄してしまったので・・・

*2: http://parrot.hatenadiary.jp/entry/2014/04/16/124949

*3: 実際には電子書籍版ですが・・・

*4: あまりにソースが汚い&機密情報の切り出しが甘い

*5: 今回のシステムの運用上、memcachedよりファイルキャッシュが楽なのです