わからないこと調べてみた | rails commit log流し読み(2018/03/15)

f:id:sktktk1230:20180726121250p:plain

1. 概要

@y_yagiさんのrails commit log流し読みを読んでいてわからなかったこと調べてみました

2. 読んだエントリ

y-yagi.hatenablog.com

3. わからなかったこと

  1. PRの中の処理に書かれていたZlib::Deflate.deflate とは何だろう?
  2. PRの中の処理に書かれていたMarshal.dump とは何だろう?

4. PRを読んでみる

対象のPR

github.com

1. どんな修正内容?

activesupport/lib/active_support/cache.rb の修正です。
ActiveSupport::Cache::Entry で保存するオブジェクトを複数回marshalしていたのを、値をキャッシュして複数回marshalしないよう修正しています。
引用:rails commit log流し読み(2018/03/15)

2. 複数回実施しているところは?

initialize 内の処理でshould_compress?がtrueだった場合、should_compress?compress で2回 Marshal.dump(@value) が実行されている為、should_compress? 実行時にインスタンス変数に格納し、 compress 実行時にはそのインスタンス変数内のデータを再度利用することで、複数回実施しないようにしているようです

変更箇所
  1. def should_compress? f:id:sktktk1230:20180316135525p:plain
  2. def compress f:id:sktktk1230:20180316135528p:plain
  3. def marshaled_value f:id:sktktk1230:20180316135532p:plain

5. PR読んでてわからない部分調べてみた

1. Zlib::Deflate.deflate とは何だろう?

string を圧縮します。level の有効な値は Zlib::NO_COMPRESSION, Zlib::BEST_SPEED, Zlib::BEST_COMPRESSION, Zlib::DEFAULT_COMPRESSION 及び 0 から 9 の整数です。

ちなみに、このメソッドは以下のコードとほぼ同じです:

require 'zlib'

def deflate(string, level)
  z = Zlib::Deflate.new(level)
  dst = z.deflate(string, Zlib::FINISH)
  z.close
  dst
end

引用:Ruby 2.5.0 リファレンスマニュアル class Zlib::Deflate

文字列を圧縮する際に使うメソッドのようです

実際の挙動を確認してみました
f:id:sktktk1230:20180316135617p:plain

ちなみに、zlib自体はRubyの機能ではなく

gzipのメイン開発者が、"Deflate"アルゴリズム処理部分だけを緩いライセンスで実装したライブラリ。Linux/UNIXだけでなく、Windowsなど幅広いプラットフォームに移植されている。
引用:技術/歴史/zip,gzip,zlib,bzip2

ということのようです

その後、gzipの主要開発者であるJean-Loup Gailly と Mark Adler らは"Deflate"圧縮アルゴリズム処理だけをライブラリとして実装し、"zlib"として商用利用も可能な緩いライセンスで公開する。
引用:技術/歴史/zip,gzip,zlib,bzip2

2. Marshal.dump とは何だろう?

obj を指定された出力先に再帰的に出力します。

ファイルに書き出せないオブジェクトをファイルに書き出そうとすると 例外 TypeError が発生します。 ファイルに書き出せないオブジェクトは以下の通りです。

  • 名前のついてない Class/Module オブジェクト。(この場 合は、例外 ArgumentError が発生します。無名クラスについて は、Module.new を参照。)
  • システムがオブジェクトの状態を保持するもの。具体的には以下のイン スタンス。Dir, File::Stat, IO とそのサブクラス File, Socket など。
  • MatchData, Data, Method, UnboundMethod, Proc, Thread, ThreadGroup, Continuation のインスタンス。
  • 特異メソッドを定義したオブジェクト
  • また、これらのオブジェクトを間接的に指すオブジェクトなども書き出せ ません。例えば、デフォルト値を求めるブロックを持った Hash は Proc を間接的に指していることになります。
p Marshal.dump(Hash.new {})
=> -:1:in `dump': cannot dump hash with default proc (TypeError)

引用:Ruby 2.5.0 リファレンスマニュアル module Marshal

実際の挙動を確認してみました
f:id:sktktk1230:20180316135628p:plain