monoの開発ブログ

Jekyllのページ生成を並列化する

Jekyll (Octopress) は全ページを事前に生成しているので、デプロイ後はとても軽快でいい感じなのですが、そのページ生成にすごく時間が掛かってしまい日々の更新作業が面倒です。

例えば、うちのマシン (Core i5 1.6GHz) とブログ (記事数188) の組み合わせだと、外部に取りに行くデータがすべてキャッシュされた状態でOctopressのgenerateに約44秒掛かってしまいます。

私はJekyllについて特に詳しいわけではないので、とりあえず簡単にできそうな高速化の工夫として、レンダリングの並列化を試してみました。一番効果がありそうで、かつ簡単そうだった部分だけ並列化してます。

require 'parallel'

module Jekyll

  class Site

    def render
      payload = site_payload
      self.posts.zip(Parallel.map(self.posts) {|post|
        post.render(self.layouts, payload)
        [ post.output, post.content ]
      }).each do |post, result|
        post.output = result[0]
        post.content = result[1]
      end

      self.pages.zip(Parallel.map(self.pages) {|page|
        page.render(self.layouts, payload)
        [ page.output, page.content ]
      }).each do |page, result|
        page.output = result[0]
        page.content = result[1]
      end

      self.categories.values.map { |ps| ps.sort! { |a, b| b <=> a } }
      self.tags.values.map { |ps| ps.sort! { |a, b| b <=> a } }
    rescue Errno::ENOENT => e
      # ignore missing layout dir
    end

  end

end

利用するためにはGemfileに gem 'parallel' を追加する必要があります。

自分のブログでしか確認していませんが、約44秒掛かっていたところが約31秒になったので、そこそこ効果がありそうです。クアッドコア以上の環境だと、より効果的かもしれません。