AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

String kopieren, was ist schneller?

Ein Thema von SearchBot · begonnen am 8. Jan 2015 · letzter Beitrag vom 9. Jan 2015
Antwort Antwort
Seite 1 von 2  1 2   
SearchBot

Registriert seit: 27. Jun 2004
Ort: N-W vom Bodensee
272 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#1

String kopieren, was ist schneller?

  Alt 8. Jan 2015, 10:32
Hallo,

ich suche eine Optimierung.
Folgendes Projekt habe ich da: 150MB String, genaugenommen rund 10000 Zeilen mit je ca. 18kB Zeilenlänge, von denen ich aber nur rund 1800 Zeichen brauche, und von denen auch nur 30 Zeichen pro Zeile

Mit den optimierten (und leicht umgebauten) Fastcode-Challenge-Routinen von StringReplace setze ich mir in wenigen Sekunden rund 30000 Marker im String, nach diesen Markern steht die Info, die ich brauche.

Delphi-Quellcode:
var TeilString, Riesenstring: AnsiString; p:integer;
//Marker ist ein einzelnes Char, zB #9
p:=PosEx(Marker,RiesenString);
repeat
 Teilstring:=copy(Riesenstring,p,1800);
 RiesenString[p]:=#32; //löschen des Markers
 p:=PosEx(Marker,RiesenString);
 //..Mache was mit dem Teilstring.. (3x weitere copy mit anderen Markern)
until p=0;
Das Copy braucht ne Weile und 150MB extra (offenbar für eine Arbeitskopie des Strings).
Gibt es was schnelleres als Copy? CopyBlock vielleicht?
Gerne auch ohne, daß nochmal 150MB im Speicher benötigt werden, weshalb ich auch auf gleiche Stringtypen achte, damit hoffentlich keine zeitaufwändige Konvertierung im Hintergrund nötig ist.

Derzeit benötigt meine Routine rund 50s für 100 Zeilen...

Danke schonmal fürs mitdenken
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.934 Beiträge
 
Delphi 12 Athens
 
#2

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 11:04
Ich habe jetzt gerade kein XE verfügbar, aber unter XE2 entspricht das Copy im Wesentlichen einem Move-Befehl. Eine Kopie des RiesenString kann ich im erzeugten Code auch nicht finden.

Du verwendest doch hoffentlich das PosEx aus AnsiStrings und nicht das aus StrUtils?

Warum nutzt du eigentlich nicht den dritten Parameter von PosEx für die Startposition der Suche? Wie es jetzt ist, beginnt die Suche immer am Anfang des RiesenString. Deshalb musst du auch den Marker ausblenden. Abgesehen davon ist das von der Performance her eher ungünstig. So wäre es deutlich geschickter:

Delphi-Quellcode:
p:=PosEx(Marker,RiesenString, 1);
repeat
 Teilstring:=copy(Riesenstring,p,1800);
  // Annahme: der nächste Marker kann erst nach dem Teilstring kommen
 p:=PosEx(Marker,RiesenString, p + 1800);
 //..Mache was mit dem Teilstring.. (3x weitere copy mit anderen Markern)
until p=0;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 11:18
Warum werden überhaupt die Marker im String gesetzt?
Wenn die Position einmal ermittelt wurde, kann der Teilstring doch sofort verarbeitet werden.
Warum wird zur Weiterverarbeitung eine Kopie gemacht?
Benötigt wird doch nur ein Pointer(PAnsiChar) auf das erste Zeichen und die Anzahl der zu verarbeitenden Zeichen.

Bei solch großen Dateien bietet es sich an mit Memory Mapped Files (MMF) zu arbeiten.
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#4

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 11:33
Den Teilstring muss man auch nicht kopieren. Wenn ich weiß, wo der anfängt, und wie lang er ist (1800 Zeichen), kann ich alle weiteren Operationen mit dieser Information machen. Und zuerst Marker zu verteilen, die man hinterher eh wieder rauslöscht, ist vielleicht auch nicht das Gelbe vom Ei.

Anhand welcher Kriterien werden die Marker denn gesetzt?

Geändert von Dejan Vu ( 8. Jan 2015 um 11:36 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 11:59
Eventuell muss man auch mal etwas anders denken.

Warum willst du die Datenquelle überhaupt ändern (Marker setzen)? Das sind Meta-Informationen, die du zur Verarbeitung benötigst und die haben in der Datenquelle nichts zu suchen.

Es reicht doch vollkommen die Position im Text zu kennen und die Länge, dann kann man mit diesen Informationen sehr hübsch sich den Teilstring aus der Datenquelle holen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#6

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 12:31
Frei nach Wheeler: Jedes Problem in der Informatik kann durch eine weitere Indirektionsstufe gelöst werden

Die Zeiger&Länge Lösung erscheint mir sinnvoll, besonders wenn du wiederholt auf die Teilstrings zugreifen musst. Damit baust du dir praktisch einen Index auf dem Hauptstring.

Wenn du nur einmal darauf zugreifen musst, kannst du den Teilstring auch wirklich gleich verarbeiten (#3).
  Mit Zitat antworten Zitat
SearchBot

Registriert seit: 27. Jun 2004
Ort: N-W vom Bodensee
272 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#7

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 18:47
Hallo und danke für Euer Interesse

Für alle: Riesenstring ist eine XML-Datei, genaugenommen eine Tabelle mit rund 10000 Zeilen und 572 Spalten - aus der ich nur 3 Spalten benötige...

Wahrscheinlich schieße ich mir sowieso von hinten durch die Brust ins Auge, oder so.
Aktuell ist aber dies die schnellste Lösung für mein Projekt und ich habe die letzte 4 Wochen schon allerlei probiert...

Ich habe es auch schon mit XML-Nodes und so versucht, aber verworfen, weil es zu lange Verarbeitungszeiten gibt. Wahrscheinlich habe ich auch was falsch gemacht - ist aber jetzt nicht das Thema
Daher ist mir der String-Überflieger lieber.

Eine Kopie des RiesenString kann ich im erzeugten Code auch nicht finden.

Du verwendest doch hoffentlich das PosEx aus AnsiStrings und nicht das aus StrUtils?

Warum nutzt du eigentlich nicht den dritten Parameter von PosEx für die Startposition der Suche?
Die Kopie wird offenbar vom Copy-Befehl erzeugt. Ich beobachte dazu den freien Speicher vor und nach dem Befehl, um das festzustellen

Genaugenommen verwende ich das PosEx aus der optimierten FastCode-Unit. Dieser ist in Assembler geschrieben und verwendet AnsiStrings(..wobei mir jetzt gerade auffällt, daß ich die Unit AnsiStrings noch garnicht kenne?!).

Den dritten Parameter hatte ich vergessen, als ich meinen Post fern von meinem Delphi an einem anderen PC eingetippt habe. Den versuche ich auch gerade zu verwenden, um mich portionsweise durch den Riesenstring zu schieben, klappt aber grad noch nicht so wie gewünscht (ein müdes Hirn macht mehr Denkfehler )...

1) Warum werden überhaupt die Marker im String gesetzt?
Wenn die Position einmal ermittelt wurde, kann der Teilstring doch sofort verarbeitet werden.
2) Warum wird zur Weiterverarbeitung eine Kopie gemacht?
3) Benötigt wird doch nur ein Pointer(PAnsiChar) auf das erste Zeichen und die Anzahl der zu verarbeitenden Zeichen.

4) Bei solch großen Dateien bietet es sich an mit Memory Mapped Files (MMF) zu arbeiten.
1) Weil das am schnellsten geht und zeitgleich den Riesenstring etwas verkleint (StringReplace). Im kurzen Teilstring kann ich sie dann meine 3 Zielfelder direkt finden und rauskopieren. Dachte mir, daß das schnellergeht, als wenn ich immer den Riesenstring durchs Copy laufen lasse. Zumal ich nach dem ersten Durchlauf noch 10000 weitere Zeilen vor mir habe...

2) Eine Kopie macht offenbar der Befehl copy, wenn ich mit dem Taskmanager den "Verwendungsverlauf des physikalischen Speichers" beobachte. Daher suche ich ja eine Alternative zu Copy, wenn es geht.

3) Aah, mit Pointern hab ichs nicht so... Die Positionen bekomme ich ja leicht raus, aber es geht ja um das zeitaufwändige rauskopieren...

4) Ursprünglich bekomme ich die Datei als MemoryStream. Dann schiebe ich das geschwind in einen StringStream, dessen DataString ich dann in meinen Riesenstring (der schlicht s heißt, aber des Verständnisses wegen ich so ausführlich benenne) setze, um die Bearbeitungen durchzuführen.
MMF ist für mich jetzt ein neues Stichwort, danke schön

Den Teilstring muss man auch nicht kopieren. Wenn ich weiß, wo der anfängt, und wie lang er ist (1800 Zeichen), kann ich alle weiteren Operationen mit dieser Information machen. Und zuerst Marker zu verteilen, die man hinterher eh wieder rauslöscht, ist vielleicht auch nicht das Gelbe vom Ei.

Anhand welcher Kriterien werden die Marker denn gesetzt?
Im Grunde weiß ich nicht genau, ob er immer so lang ist. Daher setze ich die Marker, um für meinen dritten Wert die Endposition in der aktuellen Zeile zu finden.
Wie am Anfang beschrieben suche ich bestimmte Spalten. Jede Zielspalte bekommt einen anderen Marker, um diese Werte dann schnell wieder zu finden.
Eigentlich lösche ich nur den "Zeilen-Ende"-Marker, weil das mit dem PosEx-Offset noch nicht so klappt. Daran will ich nachher weiter basteln
Mit der Fastcode-StringReplace-Funktion, die ich zu diesem Zweck etwas umgebaut habe, werden die 150MB in gefühlten 2 Sekunden an den 10000 Stellen markiert, was ich 3x mache (also rund 6 Sekunden Vorbereitungszeit - das ist ok, finde ich).

1) Warum willst du die Datenquelle überhaupt ändern (Marker setzen)?
2) Es reicht doch vollkommen die Position im Text zu kennen und die Länge, dann kann man mit diesen Informationen sehr hübsch sich den Teilstring aus der Datenquelle holen.
1) Die Datenquelle wird nicht verändert, ich arbeite ja mit einer Kopie. Und die zerschnibble ich, was ich eben daraus brauche

2) genau. Und das Rausholen des Teilstrings möchte ich beschleunigen, schneller als der Befehl Copy, wenn das geht - und das geht bestimmt irgendwie...

Die Zeiger&Länge Lösung erscheint mir sinnvoll, besonders wenn du wiederholt auf die Teilstrings zugreifen musst. Damit baust du dir praktisch einen Index auf dem Hauptstring.

Wenn du nur einmal darauf zugreifen musst, kannst du den Teilstring auch wirklich gleich verarbeiten (#3).
Ja, sobald er schnellst möglich aus dem Riesenstring separiert ist.

Vielleicht möchtet ihr die umgebaute FastCode-StringReplace noch sehen?
Original: AnsiStringReplaceJOHIA32Unit3.pas
Ich habe sie dahingegend erweitert, daß nach jedem Fund und Replace ein anderer String gesucht wird - in diesem Fall mittels eine Zahl; also sozusagen ein StringReplace mit Counter. Passend, weil jedes Tabellenfeld zB A99, A100, A101... heißt. Das macht die ursprüngliche Routine etwas langsamer, aber ist im Vergleich immernoch superschnell
Angehängte Dateien
Dateityp: pas FastStrings.pas (19,6 KB, 11x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 19:05
1) Warum willst du die Datenquelle überhaupt ändern (Marker setzen)?
2) Es reicht doch vollkommen die Position im Text zu kennen und die Länge, dann kann man mit diesen Informationen sehr hübsch sich den Teilstring aus der Datenquelle holen.
1) Die Datenquelle wird nicht verändert, ich arbeite ja mit einer Kopie. Und die zerschnibble ich, was ich eben daraus brauche

2) genau. Und das Rausholen des Teilstrings möchte ich beschleunigen, schneller als der Befehl Copy, wenn das geht - und das geht bestimmt irgendwie...
Du schreibst etwas (Merker) dort hinein, wo sich deine Daten befinden. Ob das die 200.000 Kopie der Original-Daten ist spielt keine Geige. Es ist die Datenquelle, wo du deine Daten gleich herausziehen möchtest.

Also schreibe dort keinen Merkel rein, sondern merke dir die Position und die Länge. Wenn du die Daten dann brauchst, dann einfach ab der Position in der Länge die Daten aus dieser Datenquelle herausnehmen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#9

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 19:24
Ich habe es auch schon mit XML-Nodes und so versucht, aber verworfen, weil es zu lange Verarbeitungszeiten gibt. Wahrscheinlich habe ich auch was falsch gemacht - ist aber jetzt nicht das Thema
Bei so großen XML-Dateien sind Bei Google suchenSAX-Parser nicht uninteressant ... insbesondere wenn du später doch noch ein paar andere Infos aus der XML-Datei brauchst
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.123 Beiträge
 
Delphi 10.3 Rio
 
#10

AW: String kopieren, was ist schneller?

  Alt 8. Jan 2015, 19:35
hmm warum "saust" du nicht einfach mit 2 PChars da durch.

Wenn Du an der richtigen Stelle bist von PCharDest := PCharSource bis du aus dem Bereich bist..

sonst immer nur nette inc's des PChars... nix ist schneller...

Oder habe ich da was falsch verstenden?
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz