WSLを使った方がWindows用バイナリを実行するより速い

 同じプログラムでLinux版とWindows版とが存在する場合、Windows上で動かすなら当然Windows版バイナリの方が高速に動作するであろうと思っていました。が、どうやらWSLでLinux版バイナリを動かした方が高速なことが多いことに気づいたので、少しデータを整理してみました。
 

前提環境

OS
Windows 10 Pro 1903
WSL
Ubuntu 18.04 LTS

 

optipngの場合

 PNGファイル圧縮ツールのoptipngは多様なパラメータで圧縮を何度も試行するため所要時間が長くかかります。またシングルスレッド動作のため、マルチコアCPUの恩恵は直接的には受けられません*1。このため比較的待ち時間が長いのですが、Windows版バイナリよりもLinux版の方が高速に処理されているような気がしたので測定してみました。
 

前提

 Linux版はUbuntuのパッケージマネージャから導入したoptipngで、Windows版はoptipng公式からダウンロードしてきたバイナリで、微妙にバージョンが異なります。

Linux optipng version
OptiPNG version 0.7.6
Windows optipng version
OptiPNG version 0.7.7

 なお、処理対象ファイルは各試行毎に異なりますが、いずれも同一の解像度とビット深度(3x8 bits/pixel, RGB)で同一仕様です。
 

パフォーマンス比較

 WSL上のbashから、以下のようにコマンド実行した場合、下表の結果となりました。

# Linux binary kicked from bash
time optipng -o 7 TARGETFILE

# Windows binary kicked from bash
time optipng.exe -o 7 TARGETFILE
Condition Try# Real[s]
Linux binary kicked from bash 1 19.567
Linux binary kicked from bash 2 20.299
Linux binary kicked from bash 3 17.795
Windows binary kicked from bash 1 27.319
Windows binary kicked from bash 2 25.027
Windows binary kicked from bash 3 26.307

 平均すると、Linux binaryが約19秒、Windows binaryが約26秒と、実にLinux版の方が26%以上も高速です。

 WSL環境からWindowsバイナリを実行するのに何らかのオーバーヘッドがあるために遅いのか?と思い、今度はコマンドプロンプト上から、以下のようにコマンド実行した場合の所要時間を開始終了時間から計算すると下表の結果となりました。

REM Linux binary kicked from cmd
REM cmd.exeのエスケープのため^を使用
wsl date ^&^& optipng -o 7 TARGETFILE ^&^& date

REM Windows binary kicked from cmd
REM &&でワンライン化すると開始終了時の時刻が同一になってしまうため、以下の3行をまとめてコピペして実行
echo %TIME%
optipng -o 7 TARGETFILE
echo %TIME%
Condition Try# ProcessingTime[s]
Linux binary kicked from cmd 1 21
Linux binary kicked from cmd 2 20
Linux binary kicked from cmd 3 22
Windows binary kicked from cmd 1 24
Windows binary kicked from cmd 2 29

 平均して、Linux binaryが約21秒、Windows binaryが約26.5秒と、やはりLinux版の方が速く20.75%も高速です。
 起動するシェルがWSL上のbashでも、コマンドプロンプトでも、Linux版の方が安定して速いという結果になりました。
 

ImageMagickの場合

 ImageMagickは処理内容によって所要時間は大きく異なります。
 今回はImageMagickの組み込みパターンから200万画素の画像を生成し、ぼかし処理を行って保存するを100回繰り返してみました。
 

前提

 Linux版はUbuntuのパッケージマネージャから導入したImageMagickで、Windows版はImageMagick公式からダウンロードしてきたバイナリで、メジャーバージョンも異なります。

Linux IM version
Version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org
Windows IM version
Version: ImageMagick 7.0.8-14 Q16 x64 2018-10-24 http://www.imagemagick.org

 

パフォーマンス比較

 WSL、cmdそれぞれで以下のスクリプトを実行しました。

#!/bin/bash
WORKFILE=./out.png
CMDIM="convert -size 1920x1080 pattern:BRICKS -blur 1x2.5 -quality 91 ${WORKFILE}"

echo `date +"%Y/%m/%d %H:%M:%S.%2N"` MEASURE STARTED
for i in {1..100}; do ${CMDIM}; done
echo `date +"%Y/%m/%d %H:%M:%S.%2N"` MEASURE FINISHED
@ECHO OFF
SET WORKFILE=.\out.png
SET CMDIM=convert -size 1920x1080 pattern:BRICKS -blur 1x2.5 -quality 91 %WORKFILE%

ECHO %TIME% MEASURE STARTED
FOR /L %%V IN (1 1 100) DO %CMDIM%
ECHO %TIME% MEASURE FINISHED

 その結果、下表のとおりとなりました。

Condition ProcessingTime[s]
Linux binary 38
Windows binary 67

 なんと、WSLの方が約43%も速いという結果になりました。
 

まとめ

 検証対象プログラムのバージョンがLinux版の方が古く*2Windowsと同じわけではないため、厳密に公平な比較ではありませんが、WSLでLinux版バイナリを使用した方が20%以上も高速に動作していることが判りました。
 普通に考えればWindowsネイティブの実行体の方が高速に動作しそうなものですが、何故か*3このような挙動となるようです。もちろん、すべてのプログラムやオプションで同様の結果となるのかは分かりませんが、同一PCでもWSLを使えば処理を高速化できる場合もあるということは頭の片隅に入れておいて損しないと思います。
 



以上。

*1:並列実行して複数ファイルを同時圧縮することで総所要時間の短縮を図ることはできますが、単一ファイルの圧縮時間を短くすることはできません。

*2:それでもUbuntuのパッケージマネージャで導入可能な最新版を使っています。

*3:完全な妄想ですが、Windows Defenderによるオーバーヘッドが違うとか?