Joh*_*ohn 5 python sorting perl performance
解
这解决了我的Perl代码的所有问题(加上额外的实现代码...... :-))在Perl和Python中同样令人敬畏.
use WWW::Curl::Easy;
Run Code Online (Sandbox Code Playgroud)
感谢所有回复的人,非常感谢.
编辑
看来我正在使用的Perl代码花费大部分时间来执行http get,例如:
my $start_time = gettimeofday;
$request = HTTP::Request->new('GET', 'http://localhost:8080/data.json');
$response = $ua->request($request);
$page = $response->content;
my $end_time = gettimeofday;
print "Time taken @{[ $end_time - $start_time ]} seconds.\n";
Run Code Online (Sandbox Code Playgroud)
结果是:
Time taken 74.2324419021606 seconds.
Run Code Online (Sandbox Code Playgroud)
我的python代码比较:
start = time.time()
r = requests.get('http://localhost:8080/data.json', timeout=120, stream=False)
maxsize = 100000000
content = ''
for chunk in r.iter_content(2048):
content += chunk
if len(content) > maxsize:
r.close()
raise ValueError('Response too large')
end = time.time()
timetaken = end-start
print timetaken
Run Code Online (Sandbox Code Playgroud)
结果是:
20.3471381664
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,排序时间都是次秒.首先,我为这个误导性问题道歉,这是我永远不会做出假设的另一个教训...... :-)
我不确定现在对这个问题最好的做法是什么.也许有人可以提出一种在perl中执行请求的更好方法?
编辑结束
这只是关于Perl与Python中排序性能差异的一个快速问题.这不是关于哪种语言更好/更快等等的问题,对于记录,我首先在perl中写这个,注意到排序所花费的时间,然后尝试在python中编写相同的东西,看看它会有多快.我只想知道,如何使perl代码的执行速度与python代码一样快?
让我们说我们有以下json:
["3434343424335": {
"key1": 2322,
"key2": 88232,
"key3": 83844,
"key4": 444454,
"key5": 34343543,
"key6": 2323232
},
"78237236343434": {
"key1": 23676722,
"key2": 856568232,
"key3": 838723244,
"key4": 4434544454,
"key5": 3432323543,
"key6": 2323232
}
]
Run Code Online (Sandbox Code Playgroud)
假设我们有一个大约30k-40k记录的列表,我们希望按其中一个子键排序.然后,我们想要构建由子键排序的新记录数组.
Perl - 大约需要27秒
my @list;
$decoded = decode_json($page);
foreach my $id (sort {$decoded->{$b}->{key5} <=> $decoded->{$a}->{key5}} keys %{$decoded}) {
push(@list,{"key"=>$id,"key1"=>$decoded->{$id}{key1}...etc));
}
Run Code Online (Sandbox Code Playgroud)
Python - 大约需要6秒
list = []
data = json.loads(content)
data2 = sorted(data, key = lambda x: data[x]['key5'], reverse=True)
for key in data2:
tmp= {'id':key,'key1':data[key]['key1'],etc.....}
list.append(tmp)
Run Code Online (Sandbox Code Playgroud)
对于perl代码,我尝试使用以下调整:
use sort '_quicksort'; # use a quicksort algorithm
use sort '_mergesort'; # use a mergesort algorithm
Run Code Online (Sandbox Code Playgroud)
你的基准是有缺陷的,你是对多个变量进行基准测试,而不是一个.它不仅仅是对数据进行排序,而且还在进行JSON解码,创建字符串以及附加到数组.你不知道排序花了多少时间以及花在做其他事情上花了多少钱.
事情变得更糟,因为Perl中有几个不同的JSON实现,每个实现都有自己不同的性能特征.更改基础JSON库,基准测试将再次更改.
如果要对排序进行基准测试,则必须更改基准测试代码,以消除从基准测试中加载测试数据的成本.
Perl和Python有自己的内部基准测试库,可以对各个函数进行基准测试,但是他们的工具可以使它们的表现远远低于现实世界中的表现.每个基准测试实施的性能拖累都会有所不同,可能会引入误判.这些基准测试库对于比较同一程序中的两个函数更有用.要比较语言,请保持简单.
获得准确基准测试最简单的方法是使用挂钟在计划内计时.
# The current time to the microsecond.
use Time::HiRes qw(gettimeofday);
my @list;
my $decoded = decode_json($page);
my $start_time = gettimeofday;
foreach my $id (sort {$decoded->{$b}->{key5} <=> $decoded->{$a}->{key5}} keys %{$decoded}) {
push(@list,{"key"=>$id,"key1"=>$decoded->{$id}{key1}...etc));
}
my $end_time = gettimeofday;
print "sort and append took @{[ $end_time - $start_time ]} seconds\n";
Run Code Online (Sandbox Code Playgroud)
(我将Python版本作为练习)
从这里你可以改进你的技术.您可以使用CPU秒而不是挂钟.数组追加和创建字符串的成本仍然包含在基准测试中,它们可以被淘汰,因此您只需对基准测试进行排序.等等.
此外,您可以使用分析器找出您的课程花费时间的位置.它们具有与基准测试库相同的原始性能警告,结果仅用于查找程序在其中使用的时间百分比,但是对于快速查看基准测试是否具有意外阻力将非常有用.
重要的是要对您认为自己的基准测试进行基准测试.
还有别的东西在这里发挥作用; 我可以在半秒内完成你的排序.改进不依赖于排序算法,而是减少每次比较的代码运行量; 一个施瓦茨变换得到它的三分之一秒,一个Guttman-Rosler变换将其降低到四分之一秒:
#!/usr/bin/perl
use 5.014;
use warnings;
my $decoded = { map( (int rand 1e9, { map( ("key$_", int rand 1e9), 1..6 ) } ), 1..40000 ) };
use Benchmark 'timethese';
timethese( -5, {
'original' => sub {
my @list;
foreach my $id (sort {$decoded->{$b}->{key5} <=> $decoded->{$a}->{key5}} keys %{$decoded}) {
push(@list,{"key"=>$id,%{$decoded->{$id}}});
}
},
'st' => sub {
my @list;
foreach my $id (
map $_->[1],
sort { $b->[0] <=> $a->[0] }
map [ $decoded->{$_}{key5}, $_ ],
keys %{$decoded}
) {
push(@list,{"key"=>$id,%{$decoded->{$id}}});
}
},
'grt' => sub {
my $maxkeylen=15;
my @list;
foreach my $id (
map substr($_,$maxkeylen),
sort { $b cmp $a }
map sprintf('%0*s', $maxkeylen, $decoded->{$_}{key5}) . $_,
keys %{$decoded}
) {
push(@list,{"key"=>$id,%{$decoded->{$id}}});
}
},
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
574 次 |
| 最近记录: |