Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

週刊Railsウォッチ(20200818後編)ruby_jardデバッガがスゴい、RubyオンラインマニュアルにEdit機能が追加、Ruby 2.7のBundlerを消す方法ほか

こんにちは、hachi8833です。今日はほんのちょっと暑さがましになりましたね。

  • 各記事冒頭には⚓でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄

Ruby

@_ko1さんのD論審査発表スライド『高速なRUBY用仮想マシンの開発』


同スライドより


つっつきボイス:「YARVがRubyに入ったのが1.9の頃なのでかなり昔のスライドなんですが、RubyのYARVはこういう理由でこういう設計にしたということが詳しく述べられているのを今頃知りました」「スライドじゃなかったけど読んだ覚えあるかも」「YARVをスタックマシンにしたのはRubyではメソッド呼び出しが多いからとか、そういう設計の意図を今になって知りました」

参考: YARV - Wikipedia

「@_ko1さんのように実装中心で博士論文を取るのって、最近ならともかく当時はもっと大変だったと思います」「そういえば前にも話題に出ましたね(ウォッチ20190128)」「独自性ももちろんですけど、相当丁寧にやらないと実装でドクターを取るのは難しかったと思います」「そうですよね😅」

「実際RubyにYARVが導入されたことで速くなったというのはあちこちで見聞きしますね」「ところが研究の世界だと、高速化は実装という技術の話であって研究ではないとみなす界隈もあってですね」「あ〜思い当たります」「昔は未踏に通っても論文誌に通らないとかありましたけど、最近は実装寄りの論文もだいぶ通るようになりましたね」

参考: YARV Maniacs 【第 1 回】 『Ruby ソースコード完全解説』不完全解説
参考: IPA:2004年度「未踏ユース」採択概要:05笹田

「論文のタイトル↓も『アーキテクチャ』や『評価』という言葉を中心に使ってますけど、こういうタイトルの方が通りやすかったりします」「そうそう」「他の言語との比較もきちんとやってたりしますし」


同スライドより

機能リクエスト: SetをRubyにビルトインして欲しい


つっつきボイス:「たしかruby-jp Slackで見かけたと思うんですけど、RubyのSetを標準として加えようという提案です」「他の言語だとSet(集合)が標準で入っていることもありますね」「RubyのSetというと重複のないArrayという印象ですけど」「要素の順序性を問わないときに使うヤツですね」

参考: class Set (Ruby 2.7.0 リファレンスマニュアル)

「順序性を保証しなくてよければ速くできるケースであればSetは有効でしょうね」「自分はSetArrayの使い分けをそこまで意識しないかな」「何となくArrayの方が速そうな印象があるかも」

「私はJavaでSet使った経験ならあるので、そっちのSetを想像しちゃいます」「数学的には集合って重複を認めないんだっけ?」「そのはずです」

参考: Set (Java Platform SE 8 )
参考: 集合 - Wikipedia
参考: 多重集合 - Wikipedia -- 重複を許す集合の概念

後でやってみると、RubyのSetはたしかに要素が重複しませんでした。

require 'set'

s1 = Set[10, 20, 30]
s2 = Set[10, 20, 40]
s = s1 + s2
p s     #=> #<Set: {10, 20, 30, 40}>
s.add(10) #=> #<Set: {10, 20, 30, 40}>
s << 10   #=> #<Set: {10, 20, 30, 40}>

自分はSetに関する一連のフィーチャーリクエストのissueを立てているが、いずれもこのユースケースに基づいている

主に念頭にあるユースケースは、RuboCopで最近遭遇したものだ。後でinclude?を呼ぶためだけにfrozen arrayが大量に使われていることに気づいたのだが、これはO(1)ではなくO(n)である。

これらをSetに変換しようとすると大きな互換問題が発生した。これは実にいまいましい状況であり、ものによっては変換によって効率がかなり落ちる。

こうした非互換性問題をきっかけに、RuboCopではArrayをベースにして最適化済みのinclude?===を装備したカスタムクラスを作っている。RuboCopではRubyコードに対してさまざまなチェックを走らせ、そうしたチェックはcopと呼ばれている。RuboCopのパフォーマンスは(私見では)かなり低く、一部のcopではO(n^2)になっているものすらある(nは検査するコードのサイズ)。このような効率の極端に低いcopが渡されたときでも、100を超えるarrayを最適化すると(といってもほとんどはささやかなものだが)、5%ほどスピードが向上した。

参考までにRuboCopのプルリクを貼っておく:
[fixes #22] Introduce FastArray, a frozen Array with fast inclusion lookup by marcandre · Pull Request #29 · rubocop-hq/rubocop-ast
Use FastArray by marcandre · Pull Request #8133 · rubocop-hq/rubocop

自分の経験に基づいて考えると、Setを用いればよいところにSetが使われていないことがまだまだたくさんあると思われる。その理由はSetがRubyに標準で組み込まれていないためにSetの知名度が低いのと、Setを手軽に書ける記法がないからだと思う。

以下のリクエストについての議論はこのissueにまとめたいと思う。SetをRubyのコアオブジェクトに加えるべきかどうか(かつてコアになかったComplexがその後コアに入ったように)。今後のフィーチャーリクエストの中にも、SetがRubyに組み込まれていればもっと簡単にやれる(あるいはそうしないと実現できない)ものがあるだろう。
同issueより大意

Idiosyncratic Rubyの記事2本(Ruby Weeklyより)


つっつきボイス:「1つ目はinを代入っぽく使う方法が紹介されてました」「Ruby 2.7のパターンマッチングで入ってきたヤツ」「inの機能そのものという感じですね」

# 同記事1より(Ruby 2.7ではwarningが出ます)
[1, 2, 3, 4] in [first, second, *other]

puts first  # => 1
puts second # => 2
puts other  # => [3,4]

参考: プロと読み解くRuby 2.7 NEWS - クックパッド開発者ブログ

「2つ目はNULLバイトを引用符の中で表す書き方をこんなに見つけたという記事です」「NULLバイトのリテラル書式を43個も見つけるとは、ようやる〜」「まあ自分は普通に"\0"でやるのが好きかな」

ruby_jard: ByeBugベースのRubyデバッガ


同リポジトリより


つっつきボイス:「ruby_jard、はてブにあがってましたね」「まるでIDEみたい」

asciicast

「ruby_jardをRailsコンソールで使えたらありがたいかも!」「使いみち結構ありそうですね」「本番環境でどうしても値を調べないといけない状況になったときとか」「本番環境でRailsコンソールを叩くのはどうよというのは置いといて😆」「まあ自分は基本的にRubyMine使いますけど😆」

「ベースはbyebugみたいですね」「それを単体gemのデバッグツールとしてここまで作り込んだのがスゴい」「あ、これプラグインとかじゃないのか」「なお試しに手元のirbでちょっとやってみたらたちまち吹っ飛びました😇」

deivid-rodriguez/byebug - GitHub

「ここまで仕上げたのはスゴいですね」「偉大なモチベーション」「カラースキームまで装備してるし」「そこは既存のライブラリとか使ってるんでしょうけど」「ランタイムの依存gemも意外に少ない↓」「じゃそれ以外はほとんど自分で作り上げたのね」

  spec.add_runtime_dependency 'byebug', '>= 9.1', '< 12.0'
  spec.add_runtime_dependency 'pry', '~> 0.13.0'
  spec.add_runtime_dependency 'tty-screen', '~> 0.8.1'

Ruby 2.7にデフォルトで入るBundlerを消し去る方法(Ruby Weeklyより)


つっつきボイス:「Goby↓の@st0012さんの記事をRuby Weeklyで見かけたんですけど、ちょうど自分もRuby組み込みのBundlerの削除方法が気になってたので」「え、そんなことできたっけ?」「正規の方法ではなさそうですけどやったらできたそうです」

goby-lang/goby - GitHub

「今は別バージョンのbundlerを--default付きで入れてもconfig defaultしても組み込みのbundlerが使われる↓」「自分も以前同じ結果になって諦めました」

$ bundle -v
Bundler version 2.1.4

$ gem install bundler:1.17.3 --default
Successfully installed bundler-1.17.3 as a default gem
Done installing documentation for bundler after 0 seconds
1 gem installed

$ bundle -v
Bundler version 2.1.4

$ bundle config default 1.17.3
$ bundle -v
Bundler version 2.1.4

「で方法はbundler-2.1.4.gemspecを削除するということなのね」「gempathの探索から外すということか、なるほど〜」

「これやりたくなる気持ちワカル: bundler本体をアップグレードしたときに『bundlerのバージョンが違います』みたいになってデプロイがたまにコケることがありますし」「たしかに」「まあ今はコンテナでデプロイすることが増えてきたからあんまり問題にはならなくなってきてますけど」

その他Ruby

つっつきボイス:「そうそう、これはマジスゴいと思った: 俺たちの欲しかったものはまさにこれ🎉」「これいいですよね〜」「この仕組みがあれば自分もドキュメントに修正投げようという気持ちになれますし」


「応募しようと思ったら地域.rbが対象でした😅」「RubyKaigiで発注するから量も質もスゴいんだろうなと想像」「めちゃめちゃ美味しいという評判です」

地域.rbの皆さまぜひ!

(追記↓2020/08/20)

DB

大量のレコードでOutOfMemoryになるとき


つっつきボイス:「はてブで上がってました」「JDBCの仕様らしいという話でしたっけ」「ぽすぐれでautoCommit=trueって使うんだろうか?MySQLでやるとどうなるんだろう?🤔」

「autoCommitってちょっと怖そう...」「MySQLとかだと、トランザクションを書かないときはコミットするみたいな機能があった気がする」「まあこんな設定されてたら全部フェッチして死ぬでしょうね😇」

参考: MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.3.1 START TRANSACTION、COMMIT、および ROLLBACK 構文

クラウド/コンテナ/インフラ/Serverless

Docker Hubの利用規約が更新


つっつきボイス:「無料プランは6か月以上pushまたはpullされないとinactiveにされる...だと?」「Docker Hubに何も考えずにイメージをばんばんアップロードする人がよほどたくさんいたんでしょうね」「リポジトリのサイズがペタクラスに達してるそうですし、Docker Hubとしては勘弁して欲しいでしょうね」「15ペタバイトのうち4.5ペタバイトがpushもpullもなしか...」

「GitHub Actionsとかでビルドしたイメージを自動でDocker Hubに投げてるとか割とありそうですし」「あ〜」「自動化されてるとリソースのことって気にしなくなりがちですよね」

「対象は無料プランだけだから有料プランは無事か」「有料プランは個人向けのProが月5ドルだからまあまあですかね」「でも個人用だからアカウントを共有できませんし」「あ、そうか」「無限のリソースはやっぱりないということで」

「怖いのは、自分のプロジェクトで依存しているDockerイメージが突然消えたりすること」「それですよね」「6か月以上pushまたはpullされなければ、ということはイメージが変更されなければ消えるということですし」

「自分たちが依存しているDockerイメージは、たとえばdocker rmiでイメージを消してリビルドするだけのGitHub Actionsなんかを作っておけばpullはされることになるから生存報告はできるかな」「う〜む」「Docker Hubがこうするのは無理もないし、とてもよくわかるんですけど、プロジェクトが依存している元イメージが消えるとプロジェクトが死ぬ可能性があるんですよね」「規約更新は11月からだから、来年4月ぐらいにどこかで悲鳴が上がるのかな...」

その他インフラ

つっつきボイス:「へ〜、GitHub ActionsはIPv6サポートしてるのね」「そういえばAWSのVPCってIPv6サポートしてるのかな?2016年からだから割と前からサポートしてるのか↓」「IPv6のテストが必要なときってありますよね」「IPv6のCIDRsも作れるのか、やらないけど😆」「😆」

参考: Amazon VPC の IPv6 の使用開始 - Amazon Virtual Private Cloud
参考: Classless Inter-Domain Routing - Wikipedia

自宅でIPoE+IPv6

「ところで、今一般人が自宅で最も速いインターネットを使いたければIPoE(IP over Ethernet)でIPv6を使えという話はよくありますよね」「ですね」「プロバイダ直結のIPoEでつなぐヤツで、知人には実効で800Mbps出てる人もいますし」

参考: IPoE接続とPPPoE接続との違い | NTTコミュニケーションズ 法人のお客さま

「これをやるには自宅まで光ファイバーがやってこないとできないんですけど、うちのマンションは残念ながらVDSL銅線だからできなくって😢」「うちの団地も同じくVDSLなのでできません😭」「自宅までファイバーが届いてるところはまだそんなにありませんし」「うう、窓の外の電信柱には光ケーブル通ってるのが今も見えてるのに...」「2階だか3階までだったらNTTに依頼して窓から直接引き込むことってできたと思いますけどね」「うちは3階だから可能だと思います、後は団地の管理組合に拒否されなければですけど」

参考: VDSL方式と光回線方式の違い!変更する方法とできないときの対処法は? | NURO 光

言語/ツール/OS/CPU

PHP7の定数配列

<?php
// 同記事より
function foo($bar) {
    $arr = [
        "x1"=>["foo"=>1,"bar"=>1,"baz"=>3,"qux"=>4,"quux"=>5,"corge"=>6,"grault"=>7,"garply"=>8,"waldo"=>9,"fred"=>10,"plugh"=>11,"xyzzy"=>12,"thud"=>13],
        "x2"=>["foo"=>2,"bar"=>1,"baz"=>3,"qux"=>4,"quux"=>5,"corge"=>6,"grault"=>7,"garply"=>8,"waldo"=>9,"fred"=>10,"plugh"=>11,"xyzzy"=>12,"thud"=>13],
        /* 約30000行省略 */
        "x29999"=>["foo"=>29999,"bar"=>1,"baz"=>3,"qux"=>4,"quux"=>5,"corge"=>6,"grault"=>7,"garply"=>8,"waldo"=>9,"fred"=>10,"plugh"=>11,"xyzzy"=>12,"thud"=>13],
        "x30000"=>["foo"=>30000,"bar"=>1,"baz"=>3,"qux"=>4,"quux"=>5,"corge"=>6,"grault"=>7,"garply"=>8,"waldo"=>9,"fred"=>10,"plugh"=>11,"xyzzy"=>12,"thud"=>13],
    ];
    return $arr;
}
foo(1);

つっつきボイス:「定数配列、PHP 7ということはもう使えるのか」「使い放題というのはどうかな〜?😆」

「定数配列ってどういうときに使うんでしょう?」「Railsでもこんな感じでyamlの設定ファイルにネステッドハッシュで設定を置いたりしますし、Railsのコンフィグ↓もまさにそれですね」「たしかに」

参考: Rails アプリケーションを設定する - Railsガイド

その他

これなら欲しいかも


つっつきボイス:「ムーンランダー!」「@tenderloveさんがこれ薄くていいよって盛り上がってたので」「このキートップの横が浮いてるのってゴミが入っちゃうからあんまり好きじゃないかな〜」「自分もゴミが入らない構造ならいいのにって思っちゃいました」「でなければキートップを簡単に外せて掃除できるとありがたいですよね」「これならキートップ外せると思いますよ」「自分がずっと使ってるKINESISもごくたまに全部引っこ抜いて掃除してますけど、そんなに大変でもないですね」

夏のセール明後日まで

例のエンタープライズアプリケーションアーキテクチャパターンも入ってました。

エンタープライズアプリケーションアーキテクチャパターンを読む: 1.概要


つっつきボイス:「翔泳社がGoogleスプレッドシートでセール本のリストを公開してたのをruby-jp Slackで知りました」「これ見ましたけど書影がなくて文字だけだと意外と探しにくいんですよね」「同じく😢」「シート複製してフィルタかけました」「お、そのままでもフィルタかけられますよ」

「買ってもきっと積ん読ですヨ🤣」「ああっほんとのこと言わないでください〜🤣」「最近は今すぐ読む本以外はAmazonのウイッシュリストに入れてますし」「私もウイッシュリストに積んでたんですが4000冊ぐらいになって顧みなくなりました...」「電子書籍ですし、読みたくなったら買うでいいんじゃないでしょうか」「まあまあ、買って積んどけばそのうち読みたくなるかもしれないじゃないですか、その可能性に投資しているんですよ〜」「ならないならない🤣」

「昔の回線が細くて高かった時代は、旅行するとネットのない世界に行く可能性もあったから、Kindleにあらかじめダウンロードして持っていくとかやってましたけど、今どきは回線がつながらない環境がほぼ見当たらなくなりましたよね」「そうなんですよね、私にとってフェリーに乗ってるときが数少ないそういう世界だったんですけど、最近は高知県沖以外だとネットつながるんですよ」「なぜ高知県沖なんでしょう?」「あそこは海岸が大きく湾曲してて陸地から離れてるせいかつながりませんでしたね」「へ〜」「5年ぐらい前の話なので今は違うかもしれませんけど」(以下延々)


後編は以上です。

バックナンバー(2020年度第3四半期)

週刊Railsウォッチ(20200817前編)お盆も続くRails改修、Rails 6.1にManyモナドが入る?rails-auth gemでクライアント認証ほか

今週の主なニュースソース

ソースの表記されていない項目は独自ルート(TwitterやはてブやRSSやruby-jp SlackやRedditなど)です。

Ruby Weekly


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。