実現したいこと

ビルドが遅いと感じても、hugoはどのテンプレートに時間がかかっているかを教えてくれない。

--templateMetricsを付けると、ビルド時にテンプレートごとの累積の実行時間や呼び出し回数を一覧表示できる。

使い方

hugo--templateMetricsを付ける。public/を上書きしたくない場合は-M(--renderToMemory)と組み合わせる。

$ hugo -M --templateMetrics

参考: 【Hugo】-Mオプションでディスクへ書かずにビルドする

動作確認: テンプレートを累積時間でランキングする

ビルド出力の末尾に、テンプレートごとの表が追加される。

$ hugo -M --templateMetrics 2>&1 | tail -30
       cumulative       average       maximum         
         duration      duration      duration  count  template
       ----------      --------      --------  -----  --------
     3.892665669s    6.188657ms  234.429209ms    629  single.html
     2.040040048s    2.663237ms   30.371167ms    766  _partials/single_meta.html
     707.308373ms    9.823727ms  241.160541ms     72  section.html
     626.732417ms    9.642037ms  237.369041ms     65  list.html
     241.190125ms  241.190125ms  241.190125ms      1  404.html
     200.358749ms     261.223µs   19.973125ms    767  _partials/footer.html
      89.174982ms     116.264µs    3.020875ms    767  _partials/latests.html
      60.507536ms       93.81µs   15.598625ms    645  all.rss.xml
      48.037586ms       62.63µs    2.680541ms    767  _partials/json_ld.html
      19.156757ms      24.976µs    1.797166ms    767  _partials/author.html
       4.696812ms       6.123µs     566.334µs    767  _partials/header.html

(以下略、テンプレートの種類は続く)

累積時間の降順で並び、テンプレート単位の合計時間・平均時間・最大時間・呼び出し回数が分かる。--quietを付けると表全体が出力されなくなるため、確認する際は外す。

–templateMetricsHintsでキャッシュの余地を見つける

--templateMetrics--templateMetricsHintsを組み合わせると、cache potentialなど追加の列が表示される。

$ hugo -M --templateMetrics --templateMetricsHints 2>&1 | tail -30
       cumulative       average       maximum      cache  percent  cached  total  
         duration      duration      duration  potential   cached   count  count  template
       ----------      --------      --------  ---------  -------  ------  -----  --------
     3.769406789s    5.992697ms  205.423333ms          0        0       0    629  single.html
     1.856326511s    2.423402ms   29.196833ms         35        0       0    766  _partials/single_meta.html
     171.670413ms      223.82µs     16.5025ms        100        0       0    767  _partials/footer.html
      19.619044ms      25.578µs    3.105417ms        100        0       0    767  _partials/author.html
       6.118412ms       7.977µs      1.2355ms        100        0       0    767  _partials/header.html
        608.556µs         793ns     133.292µs        100        0       0    767  _partials/adsense.html
        509.486µs         664ns      145.75µs        100        0       0    767  _partials/categories.html

cache potentialは、そのpartialを複数回呼び出しても毎回同じ出力になるかどうかの割合である。100%であれば、partial関数の代わりにpartialCached関数を使ってキャッシュできる可能性が高い。percent cachedcached countは、実際にpartialCachedでキャッシュがヒットした割合・回数を示す。

参考: Diagnose and troubleshoot build performance issues | Hugo

このブログでは_partials/footer.html_partials/author.html_partials/header.html_partials/adsense.html_partials/categories.htmlの5つがcache potential100%でありながらpercent cachedは0%だった。テンプレートの呼び出し方を確認すると、いずれもpartial関数で呼ばれているだけでpartialCachedは使われていない。

$ grep -n 'partial "header.html"\|partial "footer.html"\|partial "author.html"\|partial "categories.html"\|partial "adsense.html"' themes/hugo-theme-suer-til/layouts/baseof.html
39:    {{- partial "adsense.html" . -}}
55:    {{- partial "header.html" . -}}
62:          {{ partial "author.html" . }}
64:          {{ partial "categories.html" . }}
69:    {{- partial "footer.html" . -}}

partialCachedに変えると実際に速くなるか

header.htmlの呼び出しだけを試しにpartialからpartialCachedに変えて計測する(検証後は元に戻した)。

-    {{- partial "header.html" . -}}
+    {{- partialCached "header.html" . -}}
$ hugo -M --templateMetrics --templateMetricsHints 2>&1 | grep -i "header.html"

変更前。

       4.484955ms       5.847µs      169.75µs        100        0       0    767  _partials/header.html

変更後。

       1.048747ms       1.367µs      61.459µs        100      100     766    767  _partials/header.html

767回中766回がキャッシュにヒットし、累積時間は約4.3倍短縮された。cache potentialが100%でも、ログ出力や検証処理など副作用を持つテンプレートをキャッシュすると、その副作用が初回以降呼ばれなくなる点には注意が必要である(参考ページにも同様の注意書きがある)。

参考: hugo | Hugo