Thread Schleifengeschwindigkeit (20 answers)
Opened by RPerl at 2009-05-30 17:02

sid burn
 2009-05-30 22:55
#122117 #122117
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
2009-05-30T18:21:07 RPerl
Die "schuldige" Funktion hab ich ja eigentlich schon:
Code (perl): (dl )
sub ip_add_num

Hi, nein das ist nicht die Schuldige Funktion. Ich habe folgenden Code geschrieben:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
use Net::IP;

for ( 1 .. 200 ) {
    my $ip = new Net::IP('217.229.0.134 - 217.229.0.150') or die;
    my @ips = ();

    while ($ip) {
        push @ips, $ip->ip();
        ++$ip;
    }
}


Und einmal Profiled. Das ergebnis ist allgemein gesagt das die meiste Zeit in "Math::BigInt" verschwendet wird.

43.6s ist die Zeit die der Sourcecode benötigt, und davon fallen schon 32.5 Sekunden in den Math::BigInt Namensraum. Also knapp 75% der Zeit wird dort verschwendet.

In Net::IP werden 10.8 sekunden Zeit verbraucht. Also knapp 24% der gesamten Zeit.

Wenn du Net::IP verbessern möchtest dann musst du folgende Subroutinen Optimieren:

Net::IP::ip_bincomp => ~4s
Net::IP::ip_bintoint => ~2s
Net::IP::ip_binadd => ~2s

Sinvoller wäre es aber Math::BigInt zu verbessern. Leider hat Perl anscheind kein gutes Modul womit man große Zahlen effizent bearbeiten kann. Zwar sind die Math::* Module Portable (da alles pure Perl) aber grotten langsam. Und sind hier auch der Punkt warum das ganze am meisten ausbremst. Man kann zwar auch GMP verwenden das eigentlich in C geschrieben ist, und man kann Math::BigInt sogar sagen das er dieses nutzen soll wenn es verfügbar ist.

Code (perl): (dl )
use Math::BigInt lib => 'GMP'


Dann würde er "Math::BigInt::GMP" nutzen wenn verfügbar oder wenn nicht wieder zum Perl Only zurück fallen. Allerdiengs macht das nicht viel unterschied. 40.2s ausführungszeit anstatt 43.6s sekunden, und 29s in Math::BigInt anstatt 32.5 sekunden.

Wenn du zumindest von dem bisschen Profitieren möchtest dann musst du das ganze so laden. Und natürlich auch "Math::BigInt::GMP" installiert haben.

Code (perl): (dl )
1
2
use Math::BigInt lib => 'GMP';
use Net::IP;


Ansonsten muss man das Ergebnis weiter durchschauen. Zwar wird knapp 4 sekunden in Net::IP::ip_bincomp verschwendet, allerdiengs nicht weil die sub so langsam ist (durchschnitt braucht diese nur 97 mikroskunden pro durchlauf) sondern weil die funktion so oft aufgerufen wird.

Alleine fast 40.000 mal aus Net::IP::ip_range_to_prefix heraus. Von daher stimmt die Liste der drei Funktionen oben eigentlich nicht. Aber eins steht fest, wenn du die engpässe finden möchtest musst du Profilen.

Ansonsten müsste man schauen ob überhaupt so viele aufrufe an Net::IP::ip_bincomp nötig sind, ob man es nicht vielleicht cachen kann. Oder ob vielleicht ein anderer Algorithmus nicht sinvoller wäre etc.

Zumindest steht fest, wenn du das ganze schneller haben willst müsste man
1) Eine schnelle Implementation haben womit man in Perl große Zahlen bearbeiten kann. (So eine Bibliothek ist mir nicht bekannt und habe danach schonmal vergeblich gesucht)

2) Erst dann schauen ob man Net::IP verbessern könnte. z.B. mehr ergebnisse cachen oder die anzahl der aufrufe an Math::BigInt verringern

3) Oder eben Net::IP umschreiben das es eine Bibliothek aus Punkt 1) benutzt

4) Andere Programmiersprache nutzen. Python ist hier z.B. nicht so Crap wie Perl.

Durch eine simple umstellung der Schleife wirst du jedenfalls absolut gar nichts erreichen.
Last edited: 2009-05-30 23:27:47 +0200 (CEST)
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de

View full thread Schleifengeschwindigkeit