【Python】実行時間を計測する方法

この記事では、基本的な計測方法から高精度な計測方法まで、初心者でもわかりやすく解説します。

具体的なサンプルコードを使って、実際にどのように計測するのかを学びましょう。

目次から探す

基本的な計測方法

Pythonでプログラムの実行時間を計測する方法はいくつかあります。

ここでは、基本的な計測方法として、timeモジュールとdatetimeモジュールを使用する方法を紹介します。

timeモジュールの使用

timeモジュールは、Pythonの標準ライブラリに含まれており、時間に関する様々な機能を提供します。

ここでは、time.time()time.perf_counter()の2つの関数を使った計測方法を説明します。

time.time()の使い方

time.time()は、エポック(1970年1月1日 00:00:00 UTC)からの経過時間を秒単位で返します。

この関数を使って、プログラムの実行時間を計測する方法は以下の通りです。

import time
# 計測開始
start_time = time.time()
# 計測したい処理
for i in range(1000000):
    pass
# 計測終了
end_time = time.time()
# 実行時間を計算
execution_time = end_time - start_time
print(f"実行時間: {execution_time}秒")

このコードでは、time.time()を使って計測開始時と終了時の時間を取得し、その差を計算することで実行時間を求めています。

time.perf_counter()の使い方

time.perf_counter()は、より高精度な計測を行うための関数です。

この関数は、システムの高精度なタイマーを使用して、経過時間を秒単位で返します。

time.time()と同様に、計測開始時と終了時の時間を取得して実行時間を計算します。

import time
# 計測開始
start_time = time.perf_counter()
# 計測したい処理
for i in range(1000000):
    pass
# 計測終了
end_time = time.perf_counter()
# 実行時間を計算
execution_time = end_time - start_time
print(f"実行時間: {execution_time}秒")

このコードでは、time.perf_counter()を使って高精度な実行時間を計測しています。

datetimeモジュールの使用

datetimeモジュールも、Pythonの標準ライブラリに含まれており、日付と時間に関する様々な機能を提供します。

ここでは、datetime.now()を使った計測方法を説明します。

datetime.now()の使い方

datetime.now()は、現在の日時を取得するための関数です。

この関数を使って、プログラムの実行時間を計測する方法は以下の通りです。

from datetime import datetime
# 計測開始
start_time = datetime.now()
# 計測したい処理
for i in range(1000000):
    pass
# 計測終了
end_time = datetime.now()
# 実行時間を計算
execution_time = end_time - start_time
print(f"実行時間: {execution_time.total_seconds()}秒")

このコードでは、datetime.now()を使って計測開始時と終了時の日時を取得し、その差を計算することで実行時間を求めています。

execution_time.total_seconds()を使うことで、実行時間を秒単位で取得できます。

以上が、基本的な計測方法としてのtimeモジュールとdatetimeモジュールの使用方法です。

これらの方法を使って、簡単にプログラムの実行時間を計測することができます。

高精度な計測方法

Pythonには、より高精度で実行時間を計測するためのモジュールがいくつか用意されています。

ここでは、timeitモジュールとcProfileモジュールの使用方法について詳しく解説します。

timeitモジュールの使用

timeitモジュールは、Pythonのコードの実行時間を高精度に計測するためのツールです。

特に、短いコードの実行時間を計測するのに適しています。

timeit.timeit()の使い方

timeit.timeit()関数は、指定したコードを複数回実行し、その平均実行時間を計測します。

以下に基本的な使い方を示します。

import timeit
# 計測したいコードを文字列として指定
code_to_test = """
a = [i for i in range(1000)]
"""
# timeit.timeit()を使用して実行時間を計測
execution_time = timeit.timeit(code_to_test, number=1000)
print(f"実行時間: {execution_time}秒")

この例では、リスト内包表記を使ってリストを生成するコードの実行時間を計測しています。

number引数で指定した回数だけコードが実行され、その平均実行時間が返されます。

timeit.repeat()の使い方

timeit.repeat()関数は、指定したコードを複数回実行し、その実行時間をリストとして返します。

これにより、実行時間のばらつきを確認することができます。

import timeit
# 計測したいコードを文字列として指定
code_to_test = """
a = [i for i in range(1000)]
"""
# timeit.repeat()を使用して実行時間を計測
execution_times = timeit.repeat(code_to_test, number=1000, repeat=5)
print(f"実行時間: {execution_times}")

この例では、コードを5回実行し、それぞれの実行時間をリストとして取得しています。

これにより、実行時間のばらつきを確認することができます。

cProfileモジュールの使用

cProfileモジュールは、Pythonプログラムのプロファイリングを行うためのツールです。

プロファイリングとは、プログラムのどの部分がどれだけの時間を消費しているかを詳細に分析することです。

cProfile.run()の使い方

cProfile.run()関数は、指定したコードを実行し、そのプロファイル結果を表示します。

以下に基本的な使い方を示します。

import cProfile
# 計測したいコードを関数として定義
def test_code():
    a = [i for i in range(1000)]
# cProfile.run()を使用してプロファイルを取得
cProfile.run('test_code()')

この例では、リスト内包表記を使ってリストを生成するコードのプロファイルを取得しています。

実行結果には、各関数の呼び出し回数や実行時間が表示されます。

cProfile.Profile()の使い方

cProfile.Profile()クラスを使用すると、より詳細なプロファイル結果を取得することができます。

以下に基本的な使い方を示します。

import cProfile
# 計測したいコードを関数として定義
def test_code():
    a = [i for i in range(1000)]
# cProfile.Profile()を使用してプロファイルを取得
profiler = cProfile.Profile()
profiler.enable()
test_code()
profiler.disable()
# プロファイル結果を表示
profiler.print_stats()

この例では、cProfile.Profile()クラスを使用してプロファイルを取得し、print_stats()メソッドで結果を表示しています。

これにより、プログラムのどの部分がどれだけの時間を消費しているかを詳細に分析することができます。

以上が、timeitモジュールとcProfileモジュールを使用した高精度な実行時間の計測方法です。

これらのツールを活用することで、プログラムのパフォーマンスを詳細に分析し、最適化することができます。

実行時間計測のベストプラクティス

Pythonでプログラムの実行時間を計測する際には、単に計測するだけでなく、正確で信頼性のある結果を得るためのベストプラクティスを守ることが重要です。

ここでは、計測の前後に行うべき準備、複数回の計測と平均値の取得、そして計測結果の解釈と改善方法について詳しく解説します。

計測の前後に行うべき準備

実行時間を正確に計測するためには、計測の前後に適切な準備を行うことが重要です。

以下のポイントに注意してください。

1. 環境の安定化

計測を行う前に、プログラムが実行される環境をできるだけ安定させることが重要です。

例えば、他のプログラムがバックグラウンドで動作していると、計測結果に影響を与える可能性があります。

可能であれば、計測中は他のプログラムを停止させるか、リソースの使用を最小限に抑えるようにしましょう。

2. ウォームアップ

PythonのインタプリタやJITコンパイラ(Just-In-Timeコンパイラ)は、初回の実行時にオーバーヘッドが発生することがあります。

そのため、計測を行う前に数回プログラムを実行してウォームアップを行うと、より正確な結果が得られます。

import time
def sample_function():
    # 計測対象の関数
    time.sleep(1)
# ウォームアップ
for _ in range(5):
    sample_function()

複数回の計測と平均値の取得

単一の計測結果は、環境の変動や一時的なオーバーヘッドの影響を受ける可能性があります。

そのため、複数回の計測を行い、平均値を取得することで、より信頼性の高い結果を得ることができます。

1. 複数回の計測

同じプログラムを複数回実行し、それぞれの実行時間を記録します。

以下は、10回の計測を行う例です。

import time
def sample_function():
    # 計測対象の関数
    time.sleep(1)
times = []
for _ in range(10):
    start_time = time.time()
    sample_function()
    end_time = time.time()
    times.append(end_time - start_time)
print(times)

2. 平均値の取得

記録した実行時間の平均値を計算します。

これにより、個々の計測結果のばらつきを抑えた、より正確な実行時間を得ることができます。

average_time = sum(times) / len(times)
print(f"平均実行時間: {average_time}秒")

計測結果の解釈と改善方法

計測結果を正しく解釈し、プログラムのパフォーマンスを改善するための方法を考えることが重要です。

1. ボトルネックの特定

計測結果を分析し、どの部分が最も時間を要しているかを特定します。

これにより、最も効果的に改善できる部分を見つけることができます。

例えば、以下のように関数ごとに計測を行い、ボトルネックを特定します。

def function_a():
    time.sleep(0.5)
def function_b():
    time.sleep(1.5)
start_time = time.time()
function_a()
end_time = time.time()
print(f"function_aの実行時間: {end_time - start_time}秒")
start_time = time.time()
function_b()
end_time = time.time()
print(f"function_bの実行時間: {end_time - start_time}秒")

2. 改善方法の検討

ボトルネックが特定できたら、その部分のコードを最適化する方法を検討します。

例えば、アルゴリズムの改善、データ構造の変更、並列処理の導入などが考えられます。

3. 再計測

改善を行った後は、再度計測を行い、改善の効果を確認します。

これにより、実際にパフォーマンスが向上したかどうかを確認できます。

# 改善後の関数
def optimized_function():
    time.sleep(0.5)  # 例として、実行時間を短縮
start_time = time.time()
optimized_function()
end_time = time.time()
print(f"optimized_functionの実行時間: {end_time - start_time}秒")

以上が、Pythonで実行時間を計測する際のベストプラクティスです。

これらの方法を活用して、プログラムのパフォーマンスを正確に評価し、効果的に改善していきましょう。

実践例

ここでは、実際にPythonのコードを使って実行時間を計測する方法を具体的に見ていきます。

簡単なスクリプトから複雑なプログラム、さらには外部ライブラリを使った計測方法までを解説します。

簡単なスクリプトの計測

まずは、簡単なスクリプトの実行時間を計測してみましょう。

ここでは、リストの要素を二乗する処理を例にします。

import time
# 計測開始
start_time = time.time()
# 処理
numbers = [i for i in range(1000000)]
squared_numbers = [n**2 for n in numbers]
# 計測終了
end_time = time.time()
# 実行時間の表示
print(f"実行時間: {end_time - start_time}秒")

このスクリプトでは、time.time()を使って処理の前後の時間を取得し、その差を計算することで実行時間を求めています。

複雑なプログラムの計測

次に、もう少し複雑なプログラムの実行時間を計測してみましょう。

ここでは、クイックソートアルゴリズムを例にします。

import time
def quicksort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quicksort(left) + middle + quicksort(right)
# 計測開始
start_time = time.time()
# 処理
unsorted_list = [i for i in range(10000, 0, -1)]
sorted_list = quicksort(unsorted_list)
# 計測終了
end_time = time.time()
# 実行時間の表示
print(f"実行時間: {end_time - start_time}秒")

このスクリプトでは、クイックソートアルゴリズムを実装し、time.time()を使ってその実行時間を計測しています。

外部ライブラリの計測

最後に、外部ライブラリを使った計測方法を見てみましょう。

ここでは、NumPyを使った行列の積の計算を例にします。

import time
import numpy as np
# 行列の生成
matrix_a = np.random.rand(1000, 1000)
matrix_b = np.random.rand(1000, 1000)
# 計測開始
start_time = time.time()
# 行列の積の計算
result = np.dot(matrix_a, matrix_b)
# 計測終了
end_time = time.time()
# 実行時間の表示
print(f"実行時間: {end_time - start_time}秒")

このスクリプトでは、NumPyを使ってランダムな行列を生成し、その積を計算しています。

time.time()を使って計測することで、外部ライブラリを使った処理の実行時間も簡単に求めることができます。

以上のように、Pythonでは様々な方法で実行時間を計測することができます。

簡単なスクリプトから複雑なプログラム、さらには外部ライブラリを使った計測まで、用途に応じて適切な方法を選びましょう。

目次から探す