Pythonのパフォーマンス確認

Pythonの forループは遅いらしく「リスト内包表記」や 「mapの利用」を促す記事が多く目につくが、
これらを使用しない場合、他の言語と比べてどの程度遅いのか確認する。
※とりあえずスクリプト言語でない Java と比較する。

結果

先に結果を書いてしまうと、素のforループ等は Java と比べるとかなり遅い事がわかる。スクリプト言語の限界か・・

※環境:「2 GHz Intel Core i7、コア数: 2、メモリ: 8GB」にて確認。

単位:ミリ秒
言語種別最速最遅平均補足
Pythonfor loop158225175100万回ループ
Pythonwhile loop187209194100万回ループ
Pythonlist ref4551万回分の合算値
Pythondict ref1215131万回の合算値
単位:ミリ秒
言語種別最速最遅平均補足
Javafor loop0.480.540.51億回ループで計測し100分の1にしたもの(※)
Javawhile loop0.040.040.041億回ループで計測し100分の1にしたもの(※)
Javalist ref0421万回分の合算値
Javamap ref1521万回分の合算値

 ※ミリ秒単位だと計測できないくらい早く、System.nanoTime での計測だと
  バラツキが大きく正しく計測できなかった為。

Python

forループ

# coding: utf-8

import time
from statistics import mean

# チェックは100回実施
results = []
for i in range(100):

    # forチェック(100万回繰り返す)
    stime = time.time()
    count = 0 
    for j in range(1000000):
        count += 1
    etime = time.time()
    results.append(etime - stime)

# 結果から最速、最遅を除く
min_result = min(results)
max_result = max(results)
summary = []
for result in results:
    if result != max_result and result != min_result:
        summary.append(result)

# 最速、最遅、平均を出力
print(f'種別\t最速\t最遅\t平均\t補足')
print(f'Python\tfor loop\t{int(min(summary)*1000)}\t{int(max(summary)*1000)}\t{int(mean(summary)*1000)}\t100万回ループ')

whileループ

# coding: utf-8

import time
from statistics import mean

# チェックは100回実施
results = []
for i in range(100):

    # forチェック(100万回繰り返す)
    end_index = 1000000
    count = 0 
    stime = time.time()
    while True:
        count += 1
        if count >= end_index:
            break
    etime = time.time()
    results.append(etime - stime)

# 結果から最速、最遅を除く
min_result = min(results)
max_result = max(results)
summary = []
for result in results:
    if result != max_result and result != min_result:
        summary.append(result)

# 最速、最遅、平均を出力
print(f'種別\t最速\t最遅\t平均\t補足')
print(f'Python\twhile loop\t{int(min(summary)*1000)}\t{int(max(summary)*1000)}\t{int(mean(summary)*1000)}\t100万回ループ')

list参照

# coding: utf-8

import time
import random
from statistics import mean

# 参照元となるlistを作成する
list1 = [ random.randrange(0,1000000) for i in range(1000000)]

# チェックは100回実施
results = []
for i in range(100):

    # 1万回の集計値を取得
    all_times = 0 
    for j in range(10000):
        target_index = random.randrange(0, 1000000 - 1)
        stime = time.time()
        ref_value = list1[target_index]
        etime = time.time()
        diff = etime - stime
        all_times += diff
    results.append(all_times)

# 結果から最速、最遅を除く
min_result = min(results)
max_result = max(results)
summary = []
for result in results:
    if result != max_result and result != min_result:
        summary.append(result)

# 最速、最遅、平均を出力
print(f'種別\t最速\t最遅\t平均\t補足')
print(f'Python\tlist ref\t{int(min(summary)*1000)}\t{int(max(summary)*1000)}\t{int(mean(summary)*1000)}\t1万回分の合算値')

dict参照

# coding: utf-8

import time
import random
from statistics import mean

# 参照元となるdictを作成する
dict1 = dict(map(lambda i: (f'test{i}', random.randrange(0,1000000)), list(range(1000000))))

# チェックは100回実施
results = []
for i in range(100):

    # 1万回の集計値を取得
    all_times = 0 
    for j in range(10000):
        target_index = random.randrange(0, 1000000 - 1)
        stime = time.time()
        target_key = f'test_{target_index}'
        ref_value = None
        if target_key not in dict1:
            dict1[target_key] = None
        ref_value = dict1[target_key]
        etime = time.time()
        diff = etime - stime
        all_times += diff
    results.append(all_times)

# 結果から最速、最遅を除く
min_result = min(results)
max_result = max(results)
summary = []
for result in results:
    if result != max_result and result != min_result:
        summary.append(result)

# 最速、最遅、平均を出力
print(f'種別\t最速\t最遅\t平均\t補足')
print(f'Python\tdict ref\t{int(min(summary)*1000)}\t{int(max(summary)*1000)}\t{int(mean(summary)*1000)}\t1万回の合算値')

Java

forループ

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class App {

    public static void main(String[] args) {
        try {
            forLoop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void forLoop() {

        List<Long> results = new ArrayList<Long>();

        // チェックは100回実施
        for (int i = 0; i < 100; i++) {

            // forチェック(1億回繰り返す) ※100万回程度だと計測にならない
            int count = 0;
            long stime = System.currentTimeMillis();
            //long stime = System.nanoTime();
            //for (int j = 0; j < 1000000; j++) {
            for (long j = 0; j < 100000000; j++) {
                count++;
            }
            long etime = System.currentTimeMillis();
            //long etime = System.nanoTime();
            results.add(etime - stime);
            //System.out.println(etime - stime);
        }

        // GCがなければバラツキが殆ど無いようなので除外しない
        final List<Long> summary = results;
        /*
        // 結果から最速、最遅を除く
        final List<Long> summary = new ArrayList<Long>();
        {
            final long min = results.stream().min((a, b) -> a.compareTo(b)).get();
            final long max = results.stream().max((a, b) -> a.compareTo(b)).get();
            //results.forEach(num -> { if ((num != min) && (num != max)){ summary.add(num);} });
            results.forEach(num -> { summary.add(num); }); 
        }
        */

        // 最速、最遅、平均を出力
        final long min = summary.stream().min((a, b) -> a.compareTo(b)).get();
        final long max = summary.stream().max((a, b) -> a.compareTo(b)).get();
        final long sum = summary.stream().mapToLong(num -> num).sum();

        //System.out.println("Java\tfor loop\t最速\t最遅\t平均\t補足");
        System.out.println("Java\tfor loop\t" + min/100.0 + "\t" + max/100.0 + "\t" + (sum/summary.size()/100.0) + "\t1億回ループで計測し100分の1にしたもの");
    }   
} 

whileループ

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class App {

    public static void main(String[] args) {
        try {
            whileLoop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void whileLoop() {

        List<Long> results = new ArrayList<Long>();

        // チェックは100回実施
        for (int i = 0; i < 100; i++) {

            // forチェック(1億回繰り返す) ※100万回程度だと計測にならない
            int count = 0;
            long stime = System.currentTimeMillis();
            int endIndex = 100000000;;
            while (true) {
                count++;
                if (count >= endIndex) {
                    break;
                }
            }
            long etime = System.currentTimeMillis();
            results.add(etime - stime);
        }

        // GCがなければバラツキが殆ど無いようなので除外しない
        final List<Long> summary = results;
        /*
        // 結果から最速、最遅を除く
        final List<Long> summary = new ArrayList<Long>();
        {
            final long min = results.stream().min((a, b) -> a.compareTo(b)).get();
            final long max = results.stream().max((a, b) -> a.compareTo(b)).get();
            //results.forEach(num -> { if ((num != min) && (num != max)){ summary.add(num);} });
            results.forEach(num -> { summary.add(num); }); 
        }
        */

        // 最速、最遅、平均を出力
        final long min = summary.stream().min((a, b) -> a.compareTo(b)).get();
        final long max = summary.stream().max((a, b) -> a.compareTo(b)).get();
        final long sum = summary.stream().mapToLong(num -> num).sum();

        //System.out.println("Java\tfor loop\t最速\t最遅\t平均\t補足");
        System.out.println("Java\twhile loop\t" + min/100.0 + "\t" + max/100.0 + "\t" + (sum/summary.size()/100.0) + "\t1億回ループで計測し100分の1にしたもの");
    } 
} 

List参照

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class App {

    public static void main(String[] args) {
        try {
            listRef();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void listRef(){

        List<Long> results = new ArrayList<Long>();

        // チェックは100回実施
        for (int i = 0; i < 100; i++) {

            // 参照元となるListを作成する
            List<Long> list1 = new ArrayList<Long>();
            for (int j = 0; j < 1000000; j++) {
                list1.add(Math.round(Math.random() * 1000000));
            }

            // 1万回の集計値を取得
            long allTimes = 0;
            for (int j = 0; j < 10000; j++) {
                int index = new Long(Math.round(Math.abs(Math.random() * 1000000) - 1)).intValue();
                long stime = System.currentTimeMillis();
                Long num = list1.get(index);
                long etime = System.currentTimeMillis();
                allTimes = allTimes + (etime - stime);
            }
            results.add(allTimes);
        }

        // GCがなければバラツキが殆ど無いようなので除外しない
        final List<Long> summary = results;
        /*
        // 結果から最速、最遅を除く
        final List<Long> summary = new ArrayList<Long>();
        {
            final long min = results.stream().min((a, b) -> a.compareTo(b)).get();
            final long max = results.stream().max((a, b) -> a.compareTo(b)).get();
            //results.forEach(num -> { if ((num != min) && (num != max)){ summary.add(num);} });
            results.forEach(num -> { summary.add(num); }); 
        }
        */

        // 最速、最遅、平均を出力
        final long min = summary.stream().min((a, b) -> a.compareTo(b)).get();
        final long max = summary.stream().max((a, b) -> a.compareTo(b)).get();
        final long sum = summary.stream().mapToLong(num -> num).sum();

        //System.out.println("Java\tfor loop\t最速\t最遅\t平均\t補足");
        System.out.println("Java\tlist ref\t" + min + "\t" + max + "\t" + (sum/summary.size()) + "\t1万回分の合算値");
    } 
} 

Map参照

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class App {
    public static void main(String[] args) {
        try {
            mapRef();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void mapRef(){

        List<Long> results = new ArrayList<Long>();

        // チェックは100回実施
        for (int i = 0; i < 100; i++) {

            // 参照元となるMapを作成する
            Map<String,Long> map1 = new HashMap<String,Long>();
            for (int j = 0; j < 1000000; j++) {
                map1.put("test"+Math.round(Math.random() * 1000000), Math.round(Math.random() * 1000000));
            }

            // 1万回の集計値を取得
            long allTimes = 0;
            for (int j = 0; j < 10000; j++) {
                String key = "test" + Math.round(Math.abs(Math.random() * 1000000));
                long stime = System.currentTimeMillis();
                if (!map1.containsKey(key)) {
                    map1.put(key, null);
                }
                Long num = map1.get(key);
                long etime = System.currentTimeMillis();
                allTimes = allTimes + (etime - stime);
            }
            results.add(allTimes);
        }

        // GCがなければバラツキが殆ど無いようなので除外しない
        final List<Long> summary = results;
        /*
        // 結果から最速、最遅を除く
        final List<Long> summary = new ArrayList<Long>();
        {
            final long min = results.stream().min((a, b) -> a.compareTo(b)).get();
            final long max = results.stream().max((a, b) -> a.compareTo(b)).get();
            //results.forEach(num -> { if ((num != min) && (num != max)){ summary.add(num);} });
            results.forEach(num -> { summary.add(num); }); 
        }
        */

        // 最速、最遅、平均を出力
        final long min = summary.stream().min((a, b) -> a.compareTo(b)).get();
        final long max = summary.stream().max((a, b) -> a.compareTo(b)).get();
        final long sum = summary.stream().mapToLong(num -> num).sum();

        //System.out.println("Java\tfor loop\t最速\t最遅\t平均\t補足");
        System.out.println("Java\tmap ref\t" + min + "\t" + max + "\t" + (sum/summary.size()) + "\t1万回分の合算値");
    } 
} 

Pythonのチューニング


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-07-30 (月) 07:23:16 (132d)