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

週刊Railsウォッチ(20210518後編)RubyのGCを深掘りする、Psych gemのbreaking change、11月のRubyConf 2021ほか

こんにちは、hachi8833です。

週刊Railsウォッチについて

  • 各記事冒頭には🔗でパーマリンクを置いてあります: 社内やTwitterでの議論などにどうぞ
  • 「つっつきボイス」はRailsウォッチ公開前ドラフトを(鍋のように)社内有志でつっついたときの会話の再構成です👄
  • お気づきの点がありましたら@hachi8833までメンションをいただければ確認・対応いたします🙇

TechRachoではRubyやRailsなどの最新情報記事を平日に公開しています。TechRacho記事をいち早くお読みになりたい方はTwitterにて@techrachoのフォローをお願いします。また、タグやカテゴリごとにRSSフィードを購読することもできます(例:週刊Railsウォッチタグ)

🔗Ruby

🔗 RubyのGCを深掘り


つっつきボイス:「RubyのGC(Garbage Collection)をDeep Dive、いいですね👍」「ちょうど先週のウォッチで追加コメントしたObjectSpaceIMEMOなどもRubyのメモリ管理やGCと関連しますね(ウォッチ20210510)」「あ、なるほど」「図が整ってて見やすいですね」「こういう記事は図が大事」

参考: ガベージコレクション - Wikipedia


同記事より

「ヒープが断片化すると、空きヒープ容量が同じでも新しいオブジェクトが入り切らないことがある↓: これはRubyの例ですが、OSでもまったく同じことが起きます」


同記事より

「このような言語のGCとかメモリ管理を勉強するときは、先に以下のような書籍でOSの基本的なメモリ管理を学んでからにするとよりわかりやすいと思います」「たしかに!」

「そもそもCRubyの実行系はVM(Virtual Machine)で、VMもOSのようなメモリ管理を行っているので、理解のためにはOSから学ぶ方がむしろ近道でしょうね: たとえばRubyの内部データアラインメントにはOSやCPUアーキテクチャのアラインメントも関連しているとか」「なるほど」「そういうふうにRubyのメモリ管理を理解するうえでOSのメモリ管理の前提知識が必要になってくる場面も出てきますので、OSのメモリ管理を理解してからこうした記事を読むとはかどると思います👍」

参考: 第5章 ガーベージコレクション — 『Rubyソースコード完全解説』サポートページ

🔗 RuboCopがRuby 3.1のサポート対応開始

RuboCop AST 1.5はRuby 3.1をサポートするようになった#182
本PRではTargetRubyVersion 3.1をサポートする。
同PRより大意


つっつきボイス:「そうか、もう7か月後にはRuby 3.1が出るのか」「そう思うと近いですね」

🔗 Psych gemにbreaking change

ruby/psych - GitHub


つっつきボイス:「ruby-jp Slackで見かけたトピックです」「PsychというYAMLパーサーgemにあるloadメソッドが正しく使われないと脆弱になる可能性があるので、デフォルトでsafe_loadを実行するようにしようという提案か」「この変更がbreaking changesになるかもだそうです」「今まで読み込めたものが読み込めなくなるならその可能性はあるでしょうね」

「RailsでもYAMLローダーにPsychが使われていますね」「PsychはRubyの”default gem”に含まれていたと思います」

「ところでPsychっていうgemは前からちらほら見かけるんですが、何て読むんでしょう?」「あ、手元の辞書に載ってました↓」「サイク!」「サイケデリックとかサイキックとかに通じるんですね」

psych saɪk【名】《略式》=→psychology,
*【動】|他|《米略式》 …を精神分析する、…を正しい精神状態にする、…の精神を安定させる


Psych.loadは、信頼できないデータに対して使うと安全ではない。Psych.loadを誤って信頼できないデータに対して使い、ある種のセキュリティ脆弱性が生じているアプリケーションがあまりに多い。
本コミットはPsych.loadがデフォルトでsafe_loadを使うよう変更する。信頼できるデータをパースしたい場合はPsych.unsafe_loadを使える。
Psych.loadYAML.loadはRCE(Remote Code Execution)にさらされやすい。load関数そのものが問題なのではなく、システム内の他のオブジェクトを悪用してRCEを実行するのに使われてしまう可能性があることが問題。このブログ記事では、YAMLをRubyGemsと組み合わせてRCEに昇格させる方法が詳しく説明されている。信頼できないソースからYAMLを読み込もうとした場合、悪意のあるユーザーがこの問題に乗じて対象のシステムで任意のコードを実行できる可能性がある。

Psychでは、こうした攻撃に利用できないsafe_loadというメソッドも提供している。ここでの提案は、loadを実行したときにデフォルトでsafe_loadを実行するよう変更すること。当然ながら、safe_loadloadよりもずっと制約が大きいので、この変更によって既存のコードが動かなくなる可能性もある。

また、YAMLのload関数はRubyGems以外にもシステム内の他のオブジェクトで利用可能で、RCEに昇格する可能性があることについても言及しておく価値があるだろう。また、任意のオブジェクト読み込みに使えるもの(Marshal.loadなど)も同じように悪用される可能性があることも言及しておきたい。したがって、RubyGemsを変更しても別のシリアライズ方式(Marshalなど)に変更しても、この穴は塞げない。
同PRより大意


つっつきの後で確認してみました。

$ ruby -v
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin20]
$ gem list
...
pstore (default: 0.1.1)
psych (default: 3.3.0)
public_suffix (4.0.6)
...

上のプルリクがマージされた後だったので、gem update psychすると4.0.0にアップデートされました。

$ gem list
...
pstore (default: 0.1.1)
psych (4.0.0, default: 3.3.0)
public_suffix (4.0.6)
...

参考: bundled gem と default gem の違い - @znz blog

🔗 Rubyとボロノイ分割でアニメーション(Ruby Weeklyより)

mike-bourgeous/mb-geometry - GitHub


つっつきボイス:「ボロノイパーティションって初めて見ました」「グラフが石鹸の泡みたいに動いてる」「配置されたさまざまな点を基準にして領域を分けるアルゴリズムらしい🤔」「それをRubyでやってみたという記事なんですね」「これは楽しそう」

参考: ボロノイ図 - Wikipedia


以下はつっつき後に拾った動画です。

🔗 11月のRubyConf 2021


つっつきボイス:「今年の11/8〜11/10にコロラド州デンバーで開催が予定されているRubyConf 2021のサイトを見ると、今回はハイブリッド方式で開催するとありました」「お〜、現地でも開催されるのかな?」「詳しくはわかりませんが、対面式とバーチャルの二本立てだそうです」「今後のカンファレンスはこういうハイブリッド形式が主流になるかもしれませんね」「パンデミックも国によっては収束に向かっているところもありますし、ワクチンパスポートを持っていれば現地参加できるみたいなふうになるかも」

Q: カンファレンスが対面式とバーチャルのハイブリッドとのことですが、もう少し詳しくお願いします。
A: 詳しくは今後数か月のうちに詰めていく予定です。現時点では、対面式のカンファレンスに戻る方向で進んでいます。既にコロラド州のコンベンションセンターでは対面式のイベントが開催されていますし、米国でCOVIDワクチンが入手しやすくなったこともあり、この傾向はさらに強まると思われます。パンデミックに備えて、CDCとコロラド州保健局の安全ガイドラインに沿って、対面式イベントの形式を調整することになります。
私たちはこれまで2つのカンファレンスをバーチャルで開催してきましたが、今年のRubyConfでは両カンファレンスでうまくいった部分を統合する予定です。コミュニティメンバーの多くがコロラドに来ないことが予想されるため、対面式のイベントと並行して、できる限り最高のバーチャル体験を提供したいと考えています。
FAQより大意

参考: 英「ワクチンパスポート」 イベント会場で実証実験|テレ朝news-テレビ朝日のニュースサイト

その他Ruby

つっつきボイス:「このRuby-dev office hourというイベントを今になってruby-jp Slackで知りました」「そうそう、開発者同士が気軽に話せる場を設けようという感じで、雑談を交えて毎週開催しているらしいですよ」

つっつき後の2021/5/17の回では上述のPsychの件も話題になっていますね。


🔗DB

🔗 OracleのHeatWave


つっつきボイス:「HeatWaveはOracleのクラウドでMySQLを高速化するエンジンだそうです」「図を見た感じでは、MySQLサーバー内からプラグイン経由でHeatWaveクラスタにアクセスするようですね↓」


Understanding MySQL’s New Heatwave | Severalninesより

参考: HeatWave | オラクル | Oracle 日本

「こういうふうにセカンダリエンジンとしてHeatWave(RAPID)を指定して、SECONDARY_LOADでテーブルを読み込むのか: クエリ呼び出しではHeatWaveを特に意識しないで実行できるらしい」

# severalnines.comより
mysql> CREATE TABLE orders (id INT) SECONDARY_ENGINE = RAPID;
or
mysql> ALTER TABLE orders SECONDARY_ENGINE = RAPID;
mysql> ALTER TABLE orders SECONDARY_LOAD;

「見たところ、投機的実行っぽく両方にやらせて結果が先に返ってきた方を使うか、あるいはクエリオプティマイザが判断していずれかにクエリを投げるのかなと想像してみました🤔」「ふむふむ」

参考: 投機的実行とは - IT用語辞典 e-Words

「そういえばHeatWaveはcolumnar(列指向)なエンジンと書かれていました」「たとえばカラムを絞ってGROUP BYするような処理は、行指向DBよりも列指向DBの方が圧倒的に高速になりますね」「なるほど」

参考: 列指向データベース管理システム - Wikipedia

「こういうふうに行指向なDBと列指向なDBを両方使うことのメリットは、クエリを変更せずに高速化できることでしょうね」「たしかに」「単に自分が欲しいデータを取得するクエリを書ける難易度と、そうした欲しいデータを十分高速に最適化して取得するクエリを書ける難易度の差は結構大きいので、ある程度の高速化の部分をクエリ自体は変更せずにDBMS側で対応してくれるというのはデータ処理を頻繁に行う人たちにとってはありがたいと思います」

「カラム指向データベースはAmazon Redshiftなども含めて以前からあって、行指向だと遅いクエリがカラム指向だとものすごく高速になる(あるいはその逆)ことも以前から知られていますが、計算資源を潤沢に使えるという前提条件を付けて良いなら、HeatWaveのように両方を使うというのはなかなか理にかなっているかもしれませんね」

参考: 列指向ストレージ - Amazon Redshift


「1時間あたり4万円超えという値段にびっくりしました」「エンタープライズ方面などならその価格で買うところはあると思いますよ: 極端に言えばクエリ最適化のためにプログラマーを雇わなくても高速化できますし、結果整合性も保証されるし、デプロイも短期間で済む」「たしかに」「結局人間が一番値段が高い」

「クエリを書き換えるタイプの最適化だとテストを全面的にやり直さないといけなくなったりしますが、ミドルウェア対応だけで高速化できるならそれをしないで済みますね」「なるほど」「ちなみにRedshiftはPostgreSQLベースになっていて、基本的にはPostgreSQLクエリを変えずに使える: それと同じような感じで、HeatWaveもMySQLのクエリを基本的に変えずに高速化できるのはエンタープライズ方面にアピールしそうですね」

「ただしRedshiftのクエリはPostgreSQLと100%互換ではなく制約もあります↓: HeatWaveにももしかするとそうした制約があるかもしれませんね」

参考: Amazon Redshift and PostgreSQL - Amazon Redshift

🔗JavaScript

🔗 zx: JavaScriptでシェルスクリプトを書く

google/zx - GitHub


つっつきボイス:「はてブでバズっていたのを見つけました: JavaScriptでシェルスクリプトを書けて、async/awaitやPromiseなども使えるとか」「Rubyにもバッククォート``でシェルのコマンドを実行できる構文がありますけど、それをJavaScriptで書けるようにした感じかな」

参考: コマンド出力 — リテラル (Ruby 3.0.0 リファレンスマニュアル)

#!/usr/bin/env zx

await $`cat package.json | grep name`

let branch = await $`git branch --show-current`
await $`dep deploy --branch=${branch}`

await Promise.all([
  $`sleep 1; echo 1`,
  $`sleep 2; echo 2`,
  $`sleep 3; echo 3`,
])

let name = 'foo bar'
await $`mkdir /tmp/${name}`

「バッククォート構文でないと取れないデータもありますよね」「たとえばデータサイエンス系のツールやユニケージツールの出力をJavaScriptで組み立てて使いたい人向けかも」

参考: ユニケージ開発手法 - Wikipedia

「自分はRubyがプライマリ言語なのでzxはたぶん使わないと思いますが、JSがプライマリ言語の人にはこういうツールが便利でしょうね👍」「たしかにプライマリ言語は人によって違いますよね: この言語なら頑張れば必ずビジネスロジックを書けると確信できる言語」「そうそう」

🔗 その他JS


つっつきボイス:「短い記事ですが、ちょっとびっくりしました」「JavaScriptの配列にlengthというセッターがあるとはね〜」「面白いしわかるといえばわかりますけど、一瞬直感に反しているような気が…」「直感に反する書き方が流行ると後で読みにくくなったりすることもありますね」「たとえばTypeScriptからトランスパイルした結果にlength = 0が入るならいいけど、業務コードで直接書くのはためらうかも」

// 同記事より
const a = ['hoge', 'fuga']
console.log(a.length) // => 2

a.length = 0
console.log({a}) // => { a: [] }

🔗言語/ツール/OS/CPU

🔗 ミニLED


つっつきボイス:「次のMacBook ProのCPUはM2かM1Xか」「ここで言っているミニLEDは今度のiPadで採用されると言われているものですね↓: バックライトのLEDを領域ごとに分割してオンオフすることで消費電力を減らせる」「なるほど、黒い部分が液晶で遮られるんじゃなくて本当にその領域のバックライトをオフにするんですね」

参考: 液晶&有機ELに続く!「ミニLED」と「マイクロLED」って何? - 価格.comマガジン

いっぽうのミニLEDは、マイクロLEDと似て非なるもの。現在のところ、ミニLEDには明確な定義や規格がないのだが、おおむね液晶テレビを構成する技術の一部で、従来のバックライトを分割してエリアごとに輝度を制御する「局所輝度制御」あるいは「ローカルディミング」と呼ばれる技術の延長線上にあるものだ。バックライトの分割をより細かくすることで、画柄に合わせてよりきめ細やかな明るさ調整が行え、コントラストアップを狙える。
kakakumag.comより


「ちなみに手持ちのiPadがいい加減古くなったので新しいiPad注文しました: 届くのは7月ですけど」「いいな〜」「私もKindle Fireの昨年モデルを中古で見かけて衝動買いしちゃいました」

「そういえばリモートワークするようになって以来タブレットの利用頻度がとても上がりましたよ」「私はむしろ以前よりスマホ触るようになりましたけど」「タブレットはすごく使うようになって、逆にノートPCとスマホをほぼまったく触らなくなった」「そんなに!」


後編は以上です。

バックナンバー(2021年度第2四半期)

週刊Railsウォッチ(20210517前編)Bootstrap 5リリース、productionでSQLiteがwarning表示、rails-ujsの舞台裏ほか

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

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

Ruby Weekly


CONTACT

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