* Pythonのパフォーマンス確認 [#b923692c]
#setlinebreak(on)

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

#contents

**  結果 [#w880969b]
#html(<div style="padding-left:10px">)

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

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

#html(<table><tr><td style="vertical-align:top">)

#html(<div style="padding-left:10px;">単位:ミリ秒</div>)
|言語|種別|最速|最遅|平均|補足|h
|Python|for loop|158|225|175|100万回ループ|
|Python|while loop|187|209|194|100万回ループ|
|Python|list ref|4|5|5|1万回分の合算値|
|Python|dict ref|12|15|13|1万回の合算値|
#html(</td><td style="vertical-align:top">)

#html(<div style="padding-left:10px;">単位:ミリ秒</div>)
|言語|種別|最速|最遅|平均|補足|h
|Java|for loop|0.48|0.54|0.5|1億回ループで計測し100分の1にしたもの(※)|
|Java|while loop|0.04|0.04|0.04|1億回ループで計測し100分の1にしたもの(※)|
|Java|list ref|0|4|2|1万回分の合算値|
|Java|map ref|1|5|2|1万回分の合算値|
 ※ミリ秒単位だと計測できないくらい早く、System.nanoTime での計測だと
  バラツキが大きく正しく計測できなかった為。

#html(</td><tr></table>)

#html(</div>)

** Python [#kc3fa8ab]
#html(<div style="padding-left:10px">)

*** forループ [#u3e6b5bd]
#html(<div style="padding-left:10px">)
#mycode2(){{
# 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万回ループ')
}}
#html(</div>)

*** whileループ [#vf427814]
#html(<div style="padding-left:10px">)
#mycode2(){{
# 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万回ループ')
}}
#html(</div>)

*** list参照 [#b245409d]
#html(<div style="padding-left:10px">)
#mycode2(){{

# 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万回分の合算値')
}}
#html(</div>)

*** dict参照 [#n59443dd]
#html(<div style="padding-left:10px">)
#mycode2(){{
# 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万回の合算値')
}}
#html(</div>)

** Java [#se3f2c61]
#html(<div style="padding-left:10px">)

*** forループ [#s8520b81]
#html(<div style="padding-left:10px">)

#mycode2(){{
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にしたもの");
    }   
} 
}}
#html(</div>)

*** whileループ [#g8c328eb]
#html(<div style="padding-left:10px">)
#mycode2(){{
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にしたもの");
    } 
} 
}}
#html(</div>)

*** List参照 [#f9f48834]
#html(<div style="padding-left:10px">)
#mycode2(){{
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万回分の合算値");
    } 
} 
}}
#html(</div>)

*** Map参照 [#nf418a2d]
#html(<div style="padding-left:10px">)
#mycode2(){{
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万回分の合算値");
    } 
} 
}}
#html(</div>)


#html(</div>)



** Pythonのチューニング [#g702b599]
#html(<div style="padding-left:20px">)
[[Pythonのチューニング]] を参照
#html(</div>)

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS