解决方案
这解决了我的 Perl 代码的所有问题(加上额外的实现代码....:-))总之,Perl 和 Python 都同样出色。
use WWW::Curl::Easy;
感谢所有回复的人,非常感谢。
编辑
看来我正在使用的 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";
结果是:
Time taken 74.2324419021606 seconds.
我的 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
结果是:
20.3471381664
在这两种情况下,排序时间都是亚秒级的。所以首先我为这个误导性的问题道歉,这是我永远不要做出假设的另一个教训....:-)
我不确定现在如何处理这个问题最好。也许有人可以提出用 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
}
]
假设我们有一个包含大约 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));
}
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)
对于 perl 代码,我尝试使用以下调整:
use sort '_quicksort'; # use a quicksort algorithm
use sort '_mergesort'; # use a mergesort algorithm
最佳答案
您的基准测试存在缺陷,您正在对多个变量而不是一个变量进行基准测试。它不仅对数据进行排序,还进行 JSON 解码、创建字符串以及附加到数组。您无法知道有多少时间花在整理上,又有多少时间花在做其他事情上。
更糟糕的是,Perl 中有几种不同的 JSON 实现,每一种都有自己不同的性能特征。更改底层 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";
(我将 Python 版本留作练习)
从这里您可以提高您的技术。您可以使用 CPU 秒而不是挂钟。数组附加和创建字符串的成本仍然包含在基准测试中,它们可以被消除,所以你只是基准测试排序。等等。
此外,您可以使用 a profiler找出您的程序将时间花在哪里。这些与基准测试库具有相同的原始性能警告,结果仅对找出程序在何处使用的时间百分比有用,但事实证明,它对于快速查看基准测试是否有意外拖累很有用。
重要的是对您认为的基准进行基准测试。
关于Python 与 perl 排序性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31752670/