71 lines
2.3 KiB
TeX
71 lines
2.3 KiB
TeX
\appendix
|
||
|
||
\section{付録}
|
||
|
||
\subsection{Deep Dive - if と switch の根本的な違い}
|
||
|
||
初学者は\texttt{if}文と\texttt{switch}文の使い分けで困まる時があるようだ。
|
||
前述したとおり、どちらも条件分岐を行うことができる。
|
||
|
||
しかし、2つには文法以外に明確な違いがある。それは、\texttt{switch}文のほうが「圧倒的」に\\処理速度が速いというところである。
|
||
まず、その処理速度の違いを見てみる。
|
||
|
||
以下のPythonスクリプトで10万個の条件文を含むCソースコードを生成する:
|
||
|
||
\defaultlistingstyle
|
||
\lstinputlisting[language=Python,title={\texttt{if}文10万個}]{../programs/ifvswitch/gen-if.py}
|
||
\lstinputlisting[language=Python,title={\texttt{switch}文10万個}]{../programs/ifvswitch/gen-switch.py}
|
||
|
||
これらを実行し、Cソースコードを生成する:
|
||
|
||
\begin{lstlisting}
|
||
$ python gen-if.py
|
||
$ python gen-switch.py
|
||
\end{lstlisting}
|
||
|
||
\newpage
|
||
|
||
以下が生成されたソースコードの一部始終:
|
||
|
||
\lstinputlisting[language=C,title={\texttt{if}文10万個のソースコード},consecutivenumbers=false,linerange={1-8,199996-200010}]{../programs/ifvswitch/ifs.c}
|
||
|
||
\lstinputlisting[language=C,title={\texttt{switch}文10万個のソースコード},consecutivenumbers=false,linerange={1-8,99998-100011}]{../programs/ifvswitch/switch-case.c}
|
||
|
||
\begin{lstlisting}
|
||
// 検証に影響する最適化を無効にしてコンパイルする
|
||
$ gcc -O0 ifs.c -o ifs
|
||
$ gcc -O0 switch-case.c -o switch-case
|
||
\end{lstlisting}
|
||
|
||
生成物をタイマに通して実行する:
|
||
|
||
\begin{lstlisting}
|
||
$ time ./ifs
|
||
|
||
real 0m59.045s
|
||
user 0m58.444s
|
||
sys 0m0.001s
|
||
|
||
$ time ./switch-case
|
||
|
||
real 0m0.006s
|
||
user 0m0.004s
|
||
sys 0m0.002s
|
||
\end{lstlisting}
|
||
|
||
実行結果から\texttt{switch}文の方が\texttt{if}文の約9840倍も高速であると分かる。
|
||
|
||
では、なぜ\texttt{switch}文の方が速いのか。それは、比較演算の数にある。
|
||
|
||
\texttt{if}文はその数と同じ数の比較演算が使われている。
|
||
一方、\texttt{switch}文は比較に関する演算は一度しか行われない。
|
||
|
||
それぞれのバイナリを逆アセンブルする:
|
||
|
||
\begin{lstlisting}
|
||
$ objdump -Mintel -d ifs
|
||
$ objdump -Mintel -d switch-case
|
||
\end{lstlisting}
|
||
|
||
|