Python vs perl排序性能

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)

Sch*_*ern 7

你的基准是有缺陷的,你是对多个变量进行基准测试,而不是一个.它不仅仅是对数据进行排序,而且还在进行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秒而不是挂钟.数组追加和创建字符串的成本仍然包含在基准测试中,它们可以被淘汰,因此您只需对基准测试进行排序.等等.

此外,您可以使用分析器找出您的课程花费时间的位置.它们具有与基准测试库相同的原始性能警告,结果仅用于查找程序在其中使用的时间百分比,但是对于快速查看基准测试是否具有意外阻力将非常有用.

重要的是要对您认为自己的基准测试进行基准测试.


yst*_*sth 6

还有别的东西在这里发挥作用; 我可以在半秒内完成你的排序.改进不依赖于排序算法,而是减少每次比较的代码运行量; 一个施瓦茨变换得到它的三分之一秒,一个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)