[Frage] langsame Ausführungsgeschwindigkeit

andiling

IPPF-Promi
Mitglied seit
19 Jun 2013
Beiträge
5,975
Punkte für Reaktionen
2
Punkte
0
Hi,

mir ist aufgefallen, dass meine FB3490 folgende Zeilen im Skript mit nur etwa 4 KB/s Schreibgeschwindigkeit abarbeitet:

Code:
  grep -E "^0.0.0.0 " hosts.orig | while read I ; do
    set $I
    echo "address=/$2/127.0.0.1" | tr -d '\r' >> $DNSMASQFILE
  done

Ein bisschen mehr hätte ich der Box schon zugetraut. Gibt es Möglichkeiten das zu optimieren?

Auf der Box tut sich sonst nicht viel (es läuft zusätzlich nur dnsmasq und samba, wobei die zugehörigen AVM Dienste deaktiviert wurden).

Screenshot - 18.07.2015 , 16_43_56_ver001.jpg
Screenshot - 18.07.2015 , 16_41_58_ver001.jpg
 
Ich weiß ja nicht genau, was Du da "grep"pen willst ... aber -E wäre eigentlich nicht notwendig bei diesem Ausdruck (ist keine "extended syntax") und wenn Du tatsächlich nach Zeilen mit "0.0.0.0" am Beginn suchen solltest, müßtest Du die Punkte "escapen", sonst stehen sie eben für "ein beliebiges Zeichen", was einen entsprechenden Suchaufwand ergibt.
 
Moins

Du meinst...
Code:
showshringbuf sson | grep -o -E ....[0-9,a-f]{16}
...ist langsamer als...
Code:
showshringbuf sson | grep -o -E sid=[0-9,a-f]{16}
?
 
Kann man so absolut nicht sagen, aber "s.d=" anstelle von "sid=" sollte eigentlich immer langsamer sein.

Da die vier Punkte hintereinander vermutlich "wegoptimiert" werden und zu ".{4}" zusammengezogen werden, kann man das auf "ignoriere die ersten vier Zeichen und fange erst mit dem fünften an" verkürzen.

Ein "sid=" wird zu einer einzelnen Zeichenkettensuche (wir bleiben auf dieser höheren Abstraktionsebene, auf Assembler-Ebene ist ohne entsprechenden Befehlssatz das u.U. auch ein Vergleich Zeichen für Zeichen), die auch nur "match" oder "no match" liefern kann (alle Optimierungen (KMP,BMH) mal noch vollkommen außen vor).

Ein Vergleich von "s.d=" besteht aber eigentlich aus zwei Operationen, einmal dem Test auf das "s" und dann (wir unterstellen mal "naive Suche" oder "brute force") dem Test auf "d=" an der Stelle "s" +2.

So werden aus "0\.0\.0\.0", was ein einzelner Zeichenkettenvergleich wäre, am Ende u.U. vier einzelne Vergleiche jeweils eines einzelnen Zeichens an unterschiedlichen Offsets und das dürfte (solange das nicht "handgeschöpfter Assembler-Code" ist) immer langsamer sein, schon weil es i.d.R. mehrere Aufrufe der Standard-Library unter C sind.

Solche regulären Ausdrücke werden natürlich noch optimiert und es gibt verschiedene Verfahren, eine Zeichenkettensuche zu verkürzen.

Z.B. kann man sich bei der Suche nach "Sauerstoffflasche" in einem Text Zeichen für Zeichen vorwärts kämpfen (das meinte ich mit "naive Suche" oder "brute force"), man kann aber auch nach dem ersten "match" für das "S" am Beginn gleich das "e" am Ende testen.

Wenn das nicht stimmt, braucht man die Zeichen dazwischen gar nicht erst zu vergleichen (das kann dann ja nicht mehr passen, selbst wenn da tatsächlich noch "auerstoffflasch" stehen würde, fehlt am Ende das "e") und kann gleich mit dem nächsten Zeichen wieder von vorne beginnen bei der Suche nach dem "S".

Wenn man dann noch ein günstiges Pattern hat, bei dem es auch keine Wiederholungen von Zeichen gibt, kann man ggf. gleich hinter dem "nicht e" am Ende fortsetzen, wenn das dort anstelle des "e" stehende Zeichen nicht im Pattern vorkommt ... denn dann kann das ja weder vorne noch irgendwo in der Mitte stehen und das gesuchte Wort kann jetzt frühestens dahinter wieder beginnen.

Das sind aber wirklich alles Optimierungen, die nicht unbedingt bei jedem simplen regulären Ausdruck schon greifen müssen ... das kommt u.a. auch auf die Bibliothek an, mit der das realisiert wird und natürlich auf die Komplexität der gesuchten Zeichenketten.
 
Es geht darum, dass aus einer heruntergeladenen Datei

Code:
# [Misc A - Z]
0.0.0.0 fr.a2dfp.net

dann

Code:
address=/fr.a2dfp.net/127.0.0.1

wird.

Ich habe den Befehl jetzt wie folgt angepasst

Code:
  grep "0\.0\.0\.0 " $PREFIX.orig | while read I ; do

aber an der Performance hat es nichts geändert.
 
Das geht (wenn ich nicht etwas fundamental falsch verstanden habe) alles mit einem einzelnen Kommando: sed

Das kann man mit der Option -n dazu bringen, daß nur solche Zeilen wieder ausgegeben werden, bei denen man das mit einem "p"-Kommando oder der "p"-Option beim "s"-Kommando explizit will.

Mit einem Aufruf von
Code:
sed -n -e 's|^0\.0\.0\.0 \(.*\)$|address=/\1/127.0.0.1|p' <inputfile
hättest Du schon mal alle Zeilen mit 0.0.0.0 aus der Datei extrahiert und auch sofort in Deine gewünschte Form umgewandelt. (Als Idee verstehen, kann Syntaxfehler enthalten.)

Wenn das "tr"-Kommando nur dazu dienen sollte, ein "DOS-Zeilenende" zu erzeugen (CRLF anstelle von LF), geht das auch noch in demselben Kommando. Wenn Du dann diese Ausgabe direkt als "append" an Dein $DNSMASQFILE schreibst, könnte das auch schon reichen, ich würde aber (bei einer externen Datenquelle) die resultierende Datei noch einmal durch "uniq" jagen, damit da keine Dubletten enthalten sind, die außer zusätzlichem Aufwand nichts bringen. Ich weiß aber auch nicht, welches Programm (dnsmasq?) damit dann weiterarbeiten soll und wie dieses Programm dann eine solche Filterliste(?) im Einzelfall be-/verarbeitet. Wenn das Programm daraus einen binären Suchbaum baut, kannst Du soviele Dubletten darin haben, wie Du willst.

EDIT: Enthielt Syntaxfehler :) ... nachdem ich die (üblichen) Slashes als Trennzeichen durch den senkrechten Strich ersetzte, damit da der Schrägstrich im Wert verwendet werden kann, habe ich einen Backslash (als Escape für die runde Klammer) zuviel in | geändert ... jetzt ist es korrigiert.

EDIT2: Quatsch mit Sauce, das "tr" soll ja die CRs entfernen ... das geht mit demselben sed-Kommando (s) natürlich auch, sogar besser ... das "wie" überlasse ich hier aber Deiner Phantasie bzw. Deiner Suche/Lektüre, bin als "Rezeptschreiber" (meint nicht den Apotheker, sondern mehr die Richtung Küche ... obwohl das bestimmt ähnliche Wurzeln hat) eher nicht so glücklich.

EDIT3: Wie das so ist, setzt man immer eigene Erfahrungen bei anderen voraus ... daher ist der Vorschlag für "uniq" nicht so richtig klar. Da damit nur aufeinanderfolgende identische Zeilen entfernt werden, muß die Eingabe natürlich sortiert vorliegen. Je nach Größe der Eingabedatei hat das dann wieder Auswirkungen auf die gesamte Performance.
 
Zuletzt bearbeitet:
@PeterPawn: Vielen Dank für die Wegweiser... klasse!

Neuer Versuch:
Code:
sed -n -e '/^#/d;/^\r\s*$/d;/^127\.0\.0\.1/d;/^::1/d;s|^0\.0\.0\.0 \(.*\)$|address=/\1/127.0.0.1|;s|\r||p' $PREFIX.orig >> $DNSMASQFILE

Die Abarbeitung geht in wenigen Sekunden - so wie es sein soll.

Ein Nachteil des Einzeilers ist aber, dass er alle Zeilen mitnimmt, auch wenn sie nicht mit 0.0.0.0 anfangen. Ich habe jetzt eine Art Blacklist vorangestellt, gibt es auch eine Möglichkeit, nur eben die auszugeben, die dem pattern entsprechen (quasi Whitelist)?

Ein Problem sind allerdings Zeilen, die z.B. so sind:
Code:
0.0.0.0 stat.active24stats.nl #[Tracking.Cookie]
Hier bekomme ich dann folgende ungültige Syntax:
Code:
address/stat.active24stats.nl #[Tracking.Cookie]/127.0.0.1
Mit
Code:
s| #.*||
als Teil von
Code:
sed -n -e '/^#/d;/^\r\s*$/d;/^127\.0\.0\.1/d;/^::1/d;s/ #.*//;s|^0\.0\.0\.0 \(.*\)$|address=/\1/127.0.0.1|;s|\r||p' $PREFIX.orig >> $DNSMASQFILE
löscht er mir aber die ganze Zeile. Da habe ich wohl ein Verständnisproblem?!?
 
Zuletzt bearbeitet:
Ein Nachteil des Einzeilers ist aber, dass er alle Zeilen mitnimmt, auch wenn sie nicht mit 0.0.0.0 anfangen.
Dann hast Du schon da etwas falsch gemacht. Man kann halt schlecht selbst testen ... woher kommt denn das File?

Ich habe jetzt eine Art Blacklist vorangestellt, gibt es auch eine Möglichkeit, nur eben die auszugeben, die dem pattern entsprechen? (quasi Whitelist)
Das ist die eigentliche Idee am "-n" beim Aufruf ... da hast Du bei einem Fehler im Pattern nicht nach diesem gesucht, sondern einen (falschen/unnötigen) Workaround versucht.

Auch löscht
Code:
/^\s*$/d
auf meinem Linux System die Leerzeilen aber nicht auf der Fritzbox?!?
Das ist eben alles aus der Busybox und immer ein klein wenig anders. Da muß man eben ein wenig probieren, das sed der Busybox mag auch keine "extended regular expressions" (\s gehört dazu). Das ließe sich sicherlich z.B. mit einem
Code:
/^[ \t]*$/d
lösen, wenn da nicht sehr komische "white spaces" drin stehen.

Ein anderes Problem sind allerdings Zeilen, die z.B. so sind:
Code:
0.0.0.0 stat.active24stats.nl #[Tracking.Cookie]
Dafür dienen ja die "capture groups" im Kommando (das sind die Gruppen in den "escaped parenthesis") ... wenn Du in der Maske das entsprechend "hinten kürzt" (z.B. nur alle Zeichen ungleich "blank" und "tab" dort einbeziehst anstelle von "."), kannst Du die erste Capture-Group (\1 in der Ersetzung) gleich so gestalten, daß der Teil ab der Raute gar nicht mehr auftaucht. Deine "Filter" als "Blacklist" für die Eingabedatei sind ohnehin unnötig (s.o.).

Allerdings solltest Du das eben (mit "normaler regex-Syntax") direkt auf der Box (oder unter einem anderen Linux dann eben auch mit der Busybox und den dort enthaltenen Applets) testen ... wie geschrieben, wenn Du nicht wirklich weitere Verarbeitungen vornehmen willst, reicht ein einziger sed-Aufruf vollkommen aus. Ggf. mit mehreren Kommandos, wobei ich Dir da auch eher zu mehrfacher Angabe von -e raten würde als zum Semikolon - das ist immer etwas unübersichtlicher und es hat sich eigentlich - eben weil es geht und keinen Unterschied macht - eingebürgert, unabhängige Kommandos jeweils gesondert nach einem -e zu verwenden. Bei Abhängigkeiten (z.B. beim Arbeiten mit dem "hold space") geht das natürlich nicht ... aber das Aufteilen unabhängiger Kommandos verdeutlicht auch noch einmal das sed-Prinzip, daß ein solches Kommando immer auf den gesamten Stream angewendet wird und solche Sachen wie "+1,3s/a/b/g", die auf einem "current line pointer" basieren, mit sed eben nicht funktionieren.

EDIT: Jetzt habe ich den "Fehler" im ersten Kommando in #7 auch gesehen ... wenn Du bei "s|\r||p" das "p" hinter dem Kommando angibst, wird eben jede Zeile ausgegeben, die ein \r enthielt und wo das gelöscht wurde. Du darfst Dir die Arbeit mit dem sed nicht wie mit einem "normalen Editor" vorstellen, wo Du alles löschen mußt aus der Eingabedatei, was Du nicht haben willst (zumindest nicht hier in Deinem Falle). Wenn Du beim "s" die richtige Maske (Pattern) verwendest, brauchst Du nicht ein einziges "d"-Kommando, weil nur die Zeilen, die auf das "s"-Kommando mit dem "p" am Ende "matchen", überhaupt in der Ausgabe landen.

EDIT2: Offenbar sind ja in der Eingabe die Zeilen mit CR/LF getrennt, damit sind "white spaces" natürlich auf "blank", "tab" und "cr" zu erweitern.
 
Zuletzt bearbeitet:
Dankeschön, ich werde mir das später noch zu Gemüte führen.

Hier nur der guten Ordnung halber das ganze Script wie es im Moment ist:
(den Fehler will ich mir dann anhand der Tips selber suchen, trägt zum Verständnis bei)
Code:
#!/bin/sh
#
# Update list of mvps hosts

PREFIX="hosts"
LISTURL="http://winhelp2002.mvps.org/hosts.txt"
DNSMASQPATH="/var/media/ftp/FRITZ/dnsmasq/lists/"
DNSMASQFILE=$PREFIX.conf

run_install() {
  rm -f $DNSMASQFILE

  echo "#" > $DNSMASQFILE
  echo "# $DNSMASQFILE generated $(date)" >> $DNSMASQFILE
  echo "# do not edit this file, your changes will get lost" >> $DNSMASQFILE
  echo "#" >> $DNSMASQFILE 

  sed -n -e '/^\r\s*$/d;/^#/d;/127\.0\.0\.1/d;/::1/d;s| #.*||;s|^0\.0\.0\.0 \(.*\)$|address=/\1/127.0.0.1|;s|\r||p' $PREFIX.orig >> $DNSMASQFILE
}

cd $DNSMASQPATH
wget -qO $PREFIX.orig $LISTURL
rc=$?

if [ $rc -eq 0 ]; then

  if [ -f $PREFIX.md5 ]; then

    OLD=$(cat $PREFIX.md5)
    NEW=$(md5sum $PREFIX.orig)

    if [ "$OLD" != "$NEW" ]; then
      md5sum $PREFIX.orig > $PREFIX.md5
      run_install
    fi

  else
    md5sum $PREFIX.orig > $PREFIX.md5
    run_install
  fi
fi

Das Script ist Bestandteil von mehreren, die der Reihe nach abgearbeitet werden (im Nachfolgenden kommt eines, dass geänderte Dateien ins speziell für solche Dateien erstellte config dir von dnsmasq kopiert und dann den Service neustartet).

Bisher hatte ich für das Adblocking immer die Blacklist der Kindersicherung der Fritzbox genutzt. Die unterbindet allerdings berechtigterweise Aufrufe zu IP-Adressen, was konsequent bei einigen Apps und Programmen zu Problemen führt. Manche greifen eben auf einen ganzen Bereich von IP-Adressen zurück, was das Anklicken von einzelnen Adressen in der Liste ad absurdum führt. (Hinzu kommt, dass bei einer Neueinrichtung alles weg ist und die Arbeit von vorne beginnt)

Meine ursprüngliche Variante mit grep hat funktioniert und es wäre auch kein Problem, wenn die Box zwei Minuten für die Abarbeitung braucht, ich versuche aber Aufgaben immer so optimal wie möglich zu lösen und räume meinen Code auch hinterher immer auf, versuche ihn besser zu strukturieren, allgemeingültig zu machen, etc...
 
(den Fehler will ich mir dann anhand der Tips selber suchen, trägt zum Verständnis bei)
https://www.youtube.com/watch?v=2NTEBK8erAQ

PS: Das Kommando "md5sum" hat auch einen "check"-Modus ... wenn man das entsprechend aufruft, zeigt der exit-Code an, ob der aktuelle Wert für eine Datei mit einem gespeicherten (eigentlich mit mehreren, da dann immer eine Eingabedatei mit den alten Werten komplett abgearbeitet wird) übereinstimmt. Da dann eine fehlende Eingabedatei für den Vergleichswert ebenfalls "$? -ne 0" liefert, kann man diese beiden Fälle (Datei ist geändert / erster Aufruf und noch kein Hash für die "alte") dann wieder zusammenführen, was den Teil nach dem "wget" auch drastisch kürzt.
 
Zuletzt bearbeitet:
Moin

Von mir gibts auch noch was. :D

Wo nach Konstanten wie 127.0.0.1 oder 0.0.0.0 gesucht wird, brauchts keine RegEx.
Außerdem wäre eine wirklich treffende RegEx länger als das Gesuchte.
Denn für 0.0.0.0 reicht ein grep -o -E ^[0,.]{7} nicht, viel zu Ungenau und zähl mal die Zeichen diseses RegEx.
Dann lieber konkret nach 0.0.0.0 suchen, ohne RegEx.
...dasselbe gilt für: 127.0.0.1

Sprich: In diesem Fall plediere ich für eine Simplifizierung
 
Zuletzt bearbeitet:
Denn für 0.0.0.0 reicht ein grep -o -E ^[0,.]{7} nicht, viel zu Ungenau und zähl mal die Zeichen diseses RegEx.
Da ich das jetzt schon wiederholt bei Dir so gesehen habe ... das Komma trennt nicht zwischen der "0" und dem "." (ob der nicht ohnehin als \. geschrieben werden müßte in der "range", müßte ich auch erst probieren ... denkbar wäre natürlich, daß er dort - wo er als "wildcard" ja keinen Sinn macht - automatisch als "character" gesehen wird). In diesem Falle wird jedenfalls dieses Komma ganz simpel Bestandteil des erlaubten Zeichenumfangs an dieser Stelle und so matcht dann eben "0,0,0,0" dort ebenfalls, genauso wie ",,0.0,0" usw. - auch habe ich das in dieser Form (mit Angabe der gewünschten Anzahl) bei andiling gar nicht gesehen?

Wenn das mal jemand auf der Kommandozeile so nachbauen will, muß er sehr genau aufpassen, was da wann mit einem "escape" (dem Backslash) versehen werden muß, damit der gewünschte Effekt erzielt wird (gilt hier in erster Linie für die geschweiften Klammern) - daß es in einem Shell-Skript(!) wieder etwas anders aussieht/aussehen kann, ist ein offenes Geheimnis.

Dann lieber konkret nach 0.0.0.0 suchen, ohne RegEx.
Genau das macht eine "Suche" nach "0\.0\.0\.0" aber eigentlich ... der "escaped"-Punkt (ohne Backslash wäre es eben "ein beliebiges Zeichen") und die Nullen bilden eine einzelne Zeichenkette der Länge 7.

Und hier auf eine "regex"-Verwendung zu verzichten (die "capture group" ist ja das "Herzstück" der Lösung) wäre eher nicht sinnvoll (meine Meinung), viel effektiver kann man das (mit Bordmitteln eines AVM-Images!) eher nicht lösen ... wobei es da sicherlich auch immer mehrere Wege gibt (ist bei Shell-Code prinzipiell so) und man ggf. solche Sachen dann "gegeneinander antreten" lassen müßte - weil theoretische Überlegungen noch lange nicht immer zutreffen müssen.
 
Ach deswegen...
Dankeschön, jetzt blättern wieder die Schuppen von den Augen.
OK.
Escapen (\.) scheint innerhalb der Klammern nicht notwendig zu sein.
Ist wohl aber auch kein Fehler, ich checke mal auf Backslash im Ergebnis: echo "0.0.0\0"|grep -o -E [0-9\\\.]{7}
...sieht komisch aus, aber ist korrekt.
 
Zuletzt bearbeitet:
Danke für die vielen wertvollen Hinweise... beim zweiten Anlauf hat es dann auch geklappt... ich habe mich da wohl irgendwie vorher verrannt.

Code:
#!/bin/sh
#
# Update list of hosts

PREFIX="hosts"
LISTURL="http://winhelp2002.mvps.org/hosts.txt"
PATTERN="s|\r||;s| #.*||;s|^0\.0\.0\.0 \(.*\)$|address=/\1/127.0.0.1|p"
DNSMASQPATH="/var/media/ftp/FRITZ/dnsmasq/lists/"
DNSMASQFILE=$PREFIX.conf

run_install() {
  rm -f $DNSMASQFILE

  echo "#" > $DNSMASQFILE
  echo "# $DNSMASQFILE generated $(date)" >> $DNSMASQFILE
  echo "# do not edit this file, your changes will get lost" >> $DNSMASQFILE
  echo "#" >> $DNSMASQFILE 

  sed -n -e "$PATTERN" $PREFIX.orig >> $DNSMASQFILE
}

cd $DNSMASQPATH
if (wget -qO $PREFIX.orig $LISTURL) &&(! md5sum -c $PREFIX.md5)
then
    md5sum $PREFIX.orig > $PREFIX.md5
    run_install
fi

Dass ich anstatt verschiedener -e dann Semikolons verwendet hatte, lag schlichtweg an dem Hintergedanken, den finalen String dann über eine Variable einzubinden. Ich kann das Skript dann beliebig kopieren und muss nur die Variablen anpassen (bzw. kann den allgemeinen Teil dann auslagern).

(Ich werde dann die ganzen Skripte mal posten)
 
@andiling:
Ich will nicht "maulen" ... aber die ersten beiden "s"-Kommandos kriegst Du mühelos auch noch weg. :mrgreen: Dann spielt auch die Frage "Semikolon oder -e" keine wirkliche Rolle mehr.

Wenn ich mich nicht verhauen habe, sollte das in etwa so gehen:
Code:
s|^0\.0\.0\.0 \([^ \t\r]*\).*\r\?$|address=/\1/127.0.0.1|p

Bei mir sieht das sowohl richtig als auch "schnell" aus:
Code:
root@FB7490:~ $ s=$(date +%s);wget -O - http://winhelp2002.mvps.org/hosts.txt | sed -n -e 's|^0\.0\.0\.0 \([^ \t\r]*\).*\r\?$|address=/\1/127.0.0.1|p' | sort | wc -l;echo "$(( $(date +%s) - $s )) seconds"
Connecting to winhelp2002.mvps.org (216.155.126.40:80)
-                    100% |**********************************************|   500k  0:00:00 ETA
13671
[COLOR="#B22222"]3 seconds[/COLOR]
Inkl. Sortierung und "Durchzählen" < 4 Sekunden ... alles auf einer 7490, also identischem Prozessor (keine Dubletten gefunden - nebenbei bemerkt ;)).
 
Das ist natürlich "maulen" auf hohem Niveau... ;)

Frage zum Verständnis: Wo ist der Unterschied in der Performance? Vielleicht weil mehrere expressions nacheinander und nicht hintereinander abgearbeitet werden? (sed ist jetzt Neuland für mich)

Was mir aufgefallen ist: Wenn sort mit -u läuft, dauert das Ganze deutlich länger. Das Sortieren geht wohl flott, das Aussortieren dauert dann wohl?!?
 
Vielleicht weil mehrere expressions nacheinander und nicht hintereinander abgearbeitet werden?
Für jedes Kommando wird der komplette Stream herangezogen, d.h. es werden (müßte man in die Quellen schauen) vermutlich drei Durchläufe mit den drei (semikolon-getrennten) Kommandos durchgeführt, wobei eigentlich bei genauerer Überlegung (damit z.B. der "hold space" überhaupt greifen kann, auch wenn er hier nicht genutzt wird) doch eher von der Anwendung der drei Kommandos nacheinander auf jeweils eine Zeile des Streams auszugehen wäre.

Hat mich bisher noch nie so richtig beschäftigt ... macht es denn einen echten Unterschied in der Dauer? Mir ging es auch weniger um die Performance (da spielt ja bei meiner "Messung" sogar die Download-Geschwindigkeit mit hinein, das war also nicht wirklich ernst gemeint) als vielmehr um die unnötigen Operationen (ein einzelnes (internes) sed-Kommando vs. drei) ... selbst wenn man diese unnötigen Operationen unbedingt ausführen will, würde ich das immer so machen, daß zuerst die "Selektion" erfolgt (eben alles mit 0.0.0.0 am Beginn) und dann nur noch auf diese Zeilen auch die anderen Operationen angewandt werden. Das verringert die Anzahl der zu verarbeitenden Zeilen im vorliegenden Fall zwar nur unwesentlich ... aber bei einigen Mio. Datensätzen, von denen man am Ende nur 100 braucht, macht das den Kohl schon fett.

Das Sortieren geht wohl flott, das Aussortieren dauert dann wohl?
Sortieren läuft sicherlich mit entsprechenden Optimierungen, für "unique" ist vermutlich ein erneuter zeilenweiser Durchlauf durch die Datei erforderlich - wenn nicht doch bereits beim Einfügen in den Ergebnisbaum der nachfolgende (bzw. bei bestimmten Sortierverfahren auch der vorhergehende) Node (bzw. Leaf) geprüft wird und bereits dabei die Duplikate nicht in den Baum eingefügt werden. Auch dafür bräuchte es den Blick in die Quellen der Busybox ... soo spannend finde ich das jetzt auch wieder nicht. ;)
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.