はじめに
プログラミングにおいて、特定の処理がどれだけの時間を要するかを知ることは極めて重要です。
それによって、プログラムのパフォーマンス分析を行い、最適化を図ることが可能になります。
特に、Pythonで経過時間を計測する手法は、初心者から上級者までの全てのPython開発者が知っておくべき知識の一つと言えるでしょう。
本記事ではPythonで経過時間を計測するための12の手法を詳しく解説します。
●Pythonで時間を計測する理由
Pythonで時間を計測することは、プログラムの効率性やパフォーマンスを分析する上で不可欠です。
コードのどの部分が時間を取っているのかを知ることで、最適化の方向性を見つけ出すことができます。
また、大規模なデータ処理や、マルチスレッド/マルチプロセスを利用した並行処理においても、経過時間の計測は極めて有用です。
●Pythonでの時間の扱い方基本
Pythonで時間を扱うには、標準ライブラリのtimeモジュールやdatetimeモジュールを利用します。
これらのモジュールには、時間を扱うための様々な関数が用意されています。
○現在の時間を取得する
Pythonでは、timeモジュールのtime()関数を用いて現在のUNIXエポック(1970年1月1日0時0分0秒UTC)からの経過秒数を取得することができます。
具体的なコードは次の通りです。
このコードではtimeモジュールを使って現在のUNIXエポックからの経過秒数を取得しています。
この例ではtime.time()を使って現在のUNIXエポックからの経過秒数を取得しています。
○特定の日時を作成する
Pythonのdatetimeモジュールを使用すれば、特定の日時を表現することも可能です。
下記のコードは、2023年7月7日をdatetimeオブジェクトとして表現する例です。
このコードではdatetimeモジュールを使って特定の日時を作成しています。
この例では、2023年7月7日を指定してdatetimeオブジェクトを作成しています。
○日時のフォーマット
datetimeオブジェクトは、strftimeメソッドを使って任意の形式の文字列に変換することができます。
このコードではdatetimeモジュールを使って特定の日時を作成し、その後strftimeメソッドを使って日時を指定した形式の文字列に変換しています。
この例では、作成した日時を”年月日 時分秒”の形式で出力しています。
以上がPythonで時間を扱うための基本的な手法です。
続けて、経過時間を計測するための具体的な方法について解説します。
●経過時間を計測する方法
Pythonでは、timeモジュールを利用して経過時間を計測することができます。
ここでは、主に用いられるtime()関数、perf_counter()関数、そしてprocess_time()関数の使用法を説明します。
○timeモジュールとは
timeモジュールは、Pythonの標準ライブラリで、時間に関連する機能を提供します。
この中には、UNIXエポックからの経過秒数を取得するtime()関数や、ハイレゾリューションタイマーを提供するperf_counter()関数、CPU時間を提供するprocess_time()関数など、経過時間を計測するための関数が含まれています。
○time()関数の使用法
time()関数は、現在のUNIXエポックからの経過秒数を返します。
これを用いると、特定の処理の開始時刻と終了時刻の差分を計算することで、その処理に要した経過時間を計測することができます。
このコードではtime()関数を使って処理の開始時刻と終了時刻を取得し、その差分を計算することで経過時間を計測しています。
この例では、1000000回のループを回すという簡単な処理の経過時間を計測しています。
○perf_counter()関数の使用法
perf_counter()関数は、Pythonが起動してからの経過時間を浮動小数点数の秒数で返します。
これはOSによる時間の補正やスリープ時間も含みます。
そのため、time()関数と比べてより精度の高い経過時間の計測が可能です。
このコードではperf_counter()関数を使って処理の開始時刻と終了時刻を取得し、その差分を計算することで経過時間を計測しています。
この例では、1000000回のループを回すという簡単な処理の経過時間を計測しています。
○process_time()関数の使用法
process_time()関数は、プロセスがCPUを使用した時間を返します。
これはスリープ時間を含まず、Pythonが実行中のCPU時間のみを計測します。
そのため、CPUを使用する処理の経過時間を計測するのに適しています。
このコードではprocess_time()関数を使って処理の開始時刻と終了時刻を取得し、その差分を計算することで経過時間を計測しています。
この例では、1000000回のループを回すという簡単な処理の経過時間を計測しています。
●経過時間計測の応用例
以上の基本的な時間計測の方法を利用して、更に具体的な応用例を見ていきましょう。
○サンプルコード1:関数の実行時間を計測する
関数の実行時間を計測するには、関数の開始時と終了時にそれぞれ時間を記録し、その差分を取ることで実現できます。
このコードでは、関数my_funcの実行時間を計測しています。
関数の開始時と終了時に時間を取得し、その差分を取ることで関数の実行時間を計測します。
○サンプルコード2:ループの実行時間を計測する
ループの実行時間を計測するには、ループの開始時と終了時にそれぞれ時間を記録し、その差分を取ることで実現できます。
このコードでは、1000000回のループ処理の実行時間を計測しています。
ループの開始時と終了時に時間を取得し、その差分を取ることでループの実行時間を計測します。
○サンプルコード3:複数プロセスの実行時間を計測する
複数のプロセスを同時に実行し、その実行時間を計測する場合は、multiprocessingモジュールを使用します。
このコードでは、2つのプロセスを同時に実行し、その実行時間を計測しています。
複数プロセスの開始時と全てのプロセスが終了した時に時間を取得し、その差分を取ることで複数プロセスの実行時間を計測します。
●注意点と対処法
経過時間を計測する際の注意点とそれに対する対処法を解説します。
○適切な関数の選択
Pythonの時間計測には様々な関数がありますが、その中で「perf_counter」、「process_time」、「time」などが主に利用されます。
これらは似たような機能を持つものの、それぞれが計測する時間の範囲が異なるため、使用する関数の選択が結果に大きく影響します。
例えば、perf_counter()関数はPythonが起動してからの経過時間を返します。
一方、process_time()関数はプロセスがCPUを使用した時間を返します。
したがって、perf_counter()関数はOSの時間補正やスリープ時間を含む実経過時間を計測するのに対して、process_time()関数はスリープ時間を除いたCPU使用時間を計測するのに適しています。
また、time()関数は1970年1月1日(UNIXエポック)からの経過時間を返します。
この関数も実経過時間を計測するのに利用できますが、perf_counter()関数と比べて精度は劣るため、短時間の計測には向いていません。
○マルチスレッド/マルチプロセスの取扱い
Pythonでマルチスレッドやマルチプロセスを利用する場合、特に注意が必要です。
process_time()関数はプロセスのCPU使用時間を返すため、マルチスレッドの計測には適していません。
マルチスレッド内の各スレッドがCPUを使用した時間を個別に計測することはできません。
一方、マルチプロセスの場合、各プロセスは独立してCPUを使用するため、process_time()関数を使用して各プロセスのCPU使用時間を個別に計測することが可能です。
したがって、マルチスレッドの計測にはperf_counter()関数、マルチプロセスの計測にはprocess_time()関数を適切に使い分けることが必要です。
○OSとの依存性
最後に、経過時間の計測はOSとの依存性があることを覚えておきましょう。
Pythonのtimeモジュールの関数は内部でOSの時間計測機能を使用しています。
そのため、OSやハードウェアの性能、設定によって結果が異なることがあります。
特に、マルチプロセッサ環境ではprocess_time()関数の結果に注意が必要です。
また、perf_counter()関数はPython 3.3以降で利用可能であり、それ以前のバージョンでは利用することができません。
Pythonのバージョンを確認し、適切な関数を選択することが重要です。
まとめ
プログラムのパフォーマンス分析には、経過時間の計測が不可欠です。
Pythonでは様々な関数を使って経過時間を計測することができますが、使用する関数の選択やマルチスレッド/マルチプロセスの取扱い、OSとの依存性などに注意が必要です。
以上の12の手法を理解し、適切に利用することで、Pythonでの経過時間計測を完全にマスターすることができます。
今後のプログラミングに活かしていただければ幸いです。