* 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>)