<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[[Schnelligkeit] Festplatte einlesen und nach Pattern suchen]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich schreibe gerade ein kleineres Recovery-Programm, das durch die angegebene Festplatte läuft und nach einem selbstdefinierten Pattern sucht. Nun geht es mir um Schnelligkeit. Ich löse das bisher (mit Streams) so, dass ich einen Buffer mit der Größe des Patterns einlese, wieder zurück zur Anfangsposition setze, vergleichen, und schlussendlich ein <code>stream.get()</code> mache, und das wiederholt sich dann solange, bis die ganze Festplatte durchforstet wurde.</p>
<p>Aber ich glaube, es wäre schneller wenn ich halt einen größeren Buffer nehme und sagen wir mal ein paar Megabytes sofort einlese und dann vergleiche. Das wollte ich dann auch tun, aber da fällt mir schon auf, dass es da einige Probleme mit sich bringt. Stell dir z.B. vor, ich schreibe einen Megabyte an Daten in einen Buffer rein. Dabei enthält es das halbe Pattern, nur ganz am Ende. Und die nächste Hälfte des Patterns verbirgt sich dann sofort am Anfang des nächsten Megabytes. Wie mach ich das dann? Ich hätte mir gedacht, dass ich halt immer ein - ich sag mal - tausendes Multipel der Größe des Patterns einlese, dann kann es doch nicht mehr schiefgehen, ist das korrekt?</p>
<p>Das Programm sollte möglichst schnell sein.</p>
<p>Wie finde ich die perfekte Größe des Buffers?<br />
Wie löse ich das Problem, dass das Pattern vermutlich nur zur Hälfte im Buffer liegt?</p>
<p>Ich könnte vielleicht bei jedem Neuschreiben des Buffers einen Teil des Endes (der Größe des Patterns) an den Anfang setzen. Aber das scheint mir nicht die perfekte Lösung zu sein.</p>
<p>Wie mach ich das am besten, so, dass es am schnellsten läuft?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/339670/schnelligkeit-festplatte-einlesen-und-nach-pattern-suchen</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 23:04:21 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/339670.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 18 Sep 2016 17:38:05 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Sun, 18 Sep 2016 17:38:05 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich schreibe gerade ein kleineres Recovery-Programm, das durch die angegebene Festplatte läuft und nach einem selbstdefinierten Pattern sucht. Nun geht es mir um Schnelligkeit. Ich löse das bisher (mit Streams) so, dass ich einen Buffer mit der Größe des Patterns einlese, wieder zurück zur Anfangsposition setze, vergleichen, und schlussendlich ein <code>stream.get()</code> mache, und das wiederholt sich dann solange, bis die ganze Festplatte durchforstet wurde.</p>
<p>Aber ich glaube, es wäre schneller wenn ich halt einen größeren Buffer nehme und sagen wir mal ein paar Megabytes sofort einlese und dann vergleiche. Das wollte ich dann auch tun, aber da fällt mir schon auf, dass es da einige Probleme mit sich bringt. Stell dir z.B. vor, ich schreibe einen Megabyte an Daten in einen Buffer rein. Dabei enthält es das halbe Pattern, nur ganz am Ende. Und die nächste Hälfte des Patterns verbirgt sich dann sofort am Anfang des nächsten Megabytes. Wie mach ich das dann? Ich hätte mir gedacht, dass ich halt immer ein - ich sag mal - tausendes Multipel der Größe des Patterns einlese, dann kann es doch nicht mehr schiefgehen, ist das korrekt?</p>
<p>Das Programm sollte möglichst schnell sein.</p>
<p>Wie finde ich die perfekte Größe des Buffers?<br />
Wie löse ich das Problem, dass das Pattern vermutlich nur zur Hälfte im Buffer liegt?</p>
<p>Ich könnte vielleicht bei jedem Neuschreiben des Buffers einen Teil des Endes (der Größe des Patterns) an den Anfang setzen. Aber das scheint mir nicht die perfekte Lösung zu sein.</p>
<p>Wie mach ich das am besten, so, dass es am schnellsten läuft?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509004</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509004</guid><dc:creator><![CDATA[Pipette]]></dc:creator><pubDate>Sun, 18 Sep 2016 17:38:05 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Sun, 18 Sep 2016 18:51:03 GMT]]></title><description><![CDATA[<p>Pipette schrieb:</p>
<blockquote>
<p>Ich könnte vielleicht bei jedem Neuschreiben des Buffers einen Teil des Endes (der Größe des Patterns) an den Anfang setzen.</p>
</blockquote>
<p>ja</p>
<p>Pipette schrieb:</p>
<blockquote>
<p>Aber das scheint mir nicht die perfekte Lösung zu sein.</p>
</blockquote>
<p>wieso denn nicht?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509021</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509021</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sun, 18 Sep 2016 18:51:03 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Sun, 18 Sep 2016 18:59:45 GMT]]></title><description><![CDATA[<p>Naja, dann ist potenziell immer ein Vergleich zu viel da <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /><br />
Bei zig Tausenden von Vergleichen ist das vielleicht ein kleines Performance-Leck?<br />
Gibt es denn einen goldenen Wert, wie viele MiB ich in einem Stück einlesen soll?<br />
Oder besser gefragt: Wie findet man diesen goldenen Wert?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509023</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509023</guid><dc:creator><![CDATA[Pipette]]></dc:creator><pubDate>Sun, 18 Sep 2016 18:59:45 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Sun, 18 Sep 2016 19:10:40 GMT]]></title><description><![CDATA[<p>Das erste Fragezeichen, was mir aufpoppte, ist: wieso kapselst du das Buffering nicht ab? So, dass du quasi immer weiter ein get() machst, aber das intern gebuffert wird (falls das nicht eh schon getan wird). Ich denke da ein bisschen an die Java Streams:</p>
<pre><code>InputStream is = new BufferedInputStream(new FileInputStream(file), /*n MB*/);
while ( ... )
    is.get();
</code></pre>
<p>Da werden ja auch nur alle x Aufrufe wirklich Daten von der Platte gelesen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509024</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509024</guid><dc:creator><![CDATA[Skym0sh0]]></dc:creator><pubDate>Sun, 18 Sep 2016 19:10:40 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 03:34:12 GMT]]></title><description><![CDATA[<p>Pipette schrieb:</p>
<blockquote>
<p>stream.get()</p>
</blockquote>
<p>Pipette schrieb:</p>
<blockquote>
<p>Das Programm sollte möglichst schnell sein.</p>
</blockquote>
<p>Dann verwendest du die falsche Sprache.</p>
<p>OK, überlegen wir mal, wo die größten Flaschenhälse sind:</p>
<ol>
<li>Daten von der Festplatte in den Arbeitsspeicher übertragen (I/O-Cache)</li>
<li>Kontextwechsel</li>
<li>Dynamische Speicheranforderungen.</li>
<li>Daten unnötig hin und herkopieren.</li>
</ol>
<p>An 1) selbst kannst du nicht viel machen, außer am Kernel hacken.<br />
An 2) kannst du einiges machen, indem du diese auf ein Minimum reduzierst. Das bedeutet: immer so viele Daten wie Möglich einlesen.<br />
Ah, aber jetzt kommt es zu einem kleinen Problem: TLB-Misses. Sagen wir, du lädst 2 Mebibyte ein, dann hast du für die Adressübersetzung (wenn deine Maschine das kann) bei einer Seitengröße von 4 KiB (Betriebssystem und Arbeitsumgebung hast du ja nicht genannt) 512 Einträge. Die passen wahrscheinlich gerade so in das Workset der CPU. Wenn du jetzt immer wieder Daten einlädst bei 2 MiB, dann passen alle Übersetzungen in das Workset, und nix muss von der Seitentabelle eingeladen werden. Wenn du jetzt 16 MiB einlädst, passen die Übersetzungen nicht mehr in das Workset, und du hast TLB-Misses. Sprich, hier musst du abwägen zwischen Kontextwechsel und TLB-Misses - irgendwo hast du dann die goldene Mitte, wo du möglichst wenig Kontextwechsel bei möglichst wenig TLB-Misses hast. Als C-Programmierer würde ich die CPU fragen, wie deren DTLB-Cache aussieht, und dann, naja, sagen wir 25% oder 50% davon für meinen Buffer reservieren. Gute Kernel versuchen, ihre eigene Pollution so klein wie möglich zu halten, da kann man dann mehr Speicher reservieren. Oder gar nicht reservieren (siehe 4).<br />
Einen generellen &quot;goldenen Wert&quot; gibt es da nicht, den Zahn muss ich dir ziehen. Nur einen Mindestwert gibt es in der Regel, nämlich die verwendete Seitengröße (oft so 4 KiB). Wenn du nur mit Sektoren (oft so 512 Bytes) arbeitest, dann mappt der Kernel intern (aber das siehst du in C++ nicht) einfach 4 KiB ein, aber du hast 8 Calls, um dann jeweils 512 Bytes zu prüfen. Das ist blöd, und einen TLB-Eintrag hast du trotzdem. Wenn du mit 4 KiB arbeitest, hast du nur einen Call und einen TLB-Eintrag. Aber 4 KiB ist ja nicht die Welt, das musst du hochrechnen. Wenn deine Festplatte 64 KiB groß ist (als Beispiel), dann hast du 16 Kontextwechsel (64 / 4 = 16). Wenn du direkt mit 64 KiB arbeitest, hast du nur einen Wechsel, aber dafür 16 TLB-Einträge. Bei einer Festplatte mit 16 MiB sind wir bei 64 KiB bei 256 KW, aber immer noch 16 TLB-Einträgen. Aber bei 16 MiB nur wieder bei einem KW, aber 4096 TLB-Einträgen.</p>
<p>An 3) kannst du viel machen: <code>new</code> s weglassen, generell die Datenstrukturen der STL nicht verwenden. Aber wofür man die bei deinem Programm braucht? Keinen Plan.</p>
<ol start="4">
<li>ist ein Problem. Ein großes Problem. Du kannst jetzt anfangen, Memory-Mapped-I/O zu implementieren, aber das beißt dir in die Eier, weil du ja immer einen kleinen Teil der Daten aus dem vorherigen Block mittragen musst. Du kannst jetzt auch eine Seite direkt vor der Adresse, wo dein File Mapping stehen soll, reserveren, und da dann deine überzähligen Daten an das Ende reinkopieren, dann den nächsten Datenblock einmappen und wieder nach dem Muster suchen. Dem Kernel kannst du in der Regel sagen, wo er das Mapping reintun soll. Aber das ist kompliziert und betriebssystemabhängig, und wenn du das Mapping nicht bekommst, weil von irgendwo her async was reinkommt und dir genau die Adressen wegschnappt, die du haben willst, dann bekommst du Probleme. Aber selten passiert das. Und natürlich schauen dich C++-Programmierer immer böse an, wenn du so nicht-abstrakt an Probleme rangehst.<br />
Hat aber den Vorteil, dass du nur noch deine eigenen Kopien hast. Und an denen kannst du kaum rütteln.</li>
</ol>
<p>Hey, du hast gefragt, wie das möglichst schnell werden kann, ich gebe hier nur die Informationen weiter. Mir persönlich wäre die Geschwindigkeit ein bisschen egal, weil der Flaschenhals ja eh bei 1) liegt. Ich habe mal so ein Programm geschrieben, sogar hier mal irgendwo gepostet, und da habe ich dann einfach per <code>read</code> gearbeitet und die Kopien Kopien sein gelassen. Kommt halt darauf an, was dir Geschwindigkeit wert ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509049</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509049</guid><dc:creator><![CDATA[dachschaden]]></dc:creator><pubDate>Mon, 19 Sep 2016 03:34:12 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 05:32:59 GMT]]></title><description><![CDATA[<p>dachschaden schrieb:</p>
<blockquote>
<ol>
<li>Daten von der Festplatte in den Arbeitsspeicher übertragen (I/O-Cache)</li>
<li>Kontextwechsel</li>
<li>Dynamische Speicheranforderungen.</li>
<li>Daten unnötig hin und herkopieren.</li>
</ol>
</blockquote>
<p>So ein Schmarrn. Punkt 1 macht die Punkte 2-4 doch vollkommen irrelevant.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509051</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509051</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Mon, 19 Sep 2016 05:32:59 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 05:58:11 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>So ein Schmarrn. Punkt 1 macht die Punkte 2-4 doch vollkommen irrelevant.</p>
</blockquote>
<p>Wenn du mal bis zum Ende gelesen hättest ...</p>
<p>dachschaden schrieb:</p>
<blockquote>
<p>Mir persönlich wäre die Geschwindigkeit ein bisschen egal, weil der Flaschenhals ja eh bei 1) liegt.</p>
</blockquote>
<p>Habe den Post so geschrieben, dass er auf Leute abzielt, die auch noch den letzten Taktzyklus rauskitzeln wollen. Wie sinnvoll das ist, habe ich deutlich gemacht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509053</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509053</guid><dc:creator><![CDATA[dachschaden]]></dc:creator><pubDate>Mon, 19 Sep 2016 05:58:11 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 06:12:46 GMT]]></title><description><![CDATA[<p>dachschaden schrieb:</p>
<blockquote>
<p>dachschaden schrieb:</p>
<blockquote>
<p>Mir persönlich wäre die Geschwindigkeit ein bisschen egal, weil der Flaschenhals ja eh bei 1) liegt.</p>
</blockquote>
<p>Habe den Post so geschrieben, dass er auf Leute abzielt, die auch noch den letzten Taktzyklus rauskitzeln wollen. Wie sinnvoll das ist, habe ich deutlich gemacht.</p>
</blockquote>
<p>Dann zielst du mit deinen Maßnahmen auch voll am Stand der Technik vorbei.</p>
<p>Dass ein Programm nichts unnötiges machen sollte (also 3+4), sollte selbstverständlich sein. Deine vorgeschlagenen Gegenmaßnahmen sind jedoch Voodoo. Bei 2 verwechselst du wohl Kontextwechsel mit Cache-Misses. Daran erkennt man den echten Experten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509054</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509054</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Mon, 19 Sep 2016 06:12:46 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 07:02:27 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>Dann zielst du mit deinen Maßnahmen auch voll am Stand der Technik vorbei.</p>
</blockquote>
<p>Auf der Basis kann man auch argumentieren, dass C und C++ &quot;voll am Stand der Technik&quot; vorbeizielen, weil wir ja jetzt Java haben. Oder C#. Oder Swift oder Rust oder was auch immer.</p>
<p>SeppJ schrieb:</p>
<blockquote>
<p>Bei 2 verwechselst du wohl Kontextwechsel mit Cache-Misses. Daran erkennt man den echten Experten.</p>
</blockquote>
<p>Und du verwechselst TLB-Misses mit Cache-Misses. TLBs kennen kein Prefetch. Und selbst im 2nd Level sind die begrenzt. Mal die Daten meiner CPU:</p>
<pre><code>[TLB] Instruction TLB: 2M/4M pages, fully associative, 8 entries
[TLB] Data TLB: 4 KByte pages, 4-way set associative, 64 entries
[TLB] Data TLB: 2 MByte or 4 MByte pages, 4-way set associative, 32 entries and a separate array with 1 GByte pages, 4-way set associative, 4 entries
[Prefetch] 64-Byte prefetching
[TLB] Instruction TLB: 4KByte pages, 8-way set associative, 64 entries
[STLB] Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way associative, 1024 entries
</code></pre>
<p>Cache-Größe kann ich noch nicht einlesen, daher verlasse ich mich mal auf die Information, dass dieser 6 MiB groß ist. Sagen wir mal, 4 MIB stehen dem Userspace zur Verfügung. Der Flaschenhals ist hier deutlich der TLB-Cache, der nur 1024 Einträge (2nd Level, also 4 MiB) erfassen kann (wenn du 4 KiB-Seiten verwendest - und wenn du Hugepages mit dem Dateisystem verwenden willst, ist das nervend auf Linux und nicht möglich auf Windows).</p>
<p>&quot;Wieso? 4 MiB TLB, 4 MiB Cache, reicht doch.&quot;</p>
<p>Weil von den Übersetzungen ein Teil noch an den Kernel gehen. Wir haben also effektiv weniger Platz für Übersetzungen, als vom Cache getragen werden können. Außerdem ist das Holen einer Cache-Line nicht so tragisch wie das Holen einer Übersetzungsadresse, in der mehrmals auf den Speicher zugegriffen werden muss (weil es eben eine Tabelle ist).</p>
<p>Falls das in irgendeiner Art und Weise falsch sein sollte, bei aller Liebe, korrigiere mich. Aber sag nicht einfach, das sei Voodoo. Unnötig? Ja. Den Aufwand nicht gerechtfertigt? Ja, wahrscheinlich, es sei denn, du verwendest den Code später noch etliche Male. Aber Voodoo? <a href="http://lwn.net/Articles/250967/" rel="nofollow">Glaube ich nicht</a>.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509057</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509057</guid><dc:creator><![CDATA[dachschaden]]></dc:creator><pubDate>Mon, 19 Sep 2016 07:02:27 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 08:55:07 GMT]]></title><description><![CDATA[<p>Bitte richtig lesen, die Tipps zu 3+4 sind Voodoo. 2 ist einfach nur den Aufwand nicht wert. Optimier die Pipelines (sowohl Daten als auch Instructions), damit gewinnst du mit einfacheren Mitteln viel mehr.</p>
<p>Warum 3+4 Voodoo sind:<br />
3: Und wie machst du sonst dynamische Speicheranforderungen? Entweder du brauchst sie, oder du verwendest sie besser nicht. Aber wenn du sie brauchst, dann glaubst du doch wohl nicht im Ernst, dass der Name der Handlerstruktur einen Unterschied macht?</p>
<p>4: Was hat deine Lösung mit dem beschriebenen Problem zu tun? Weil der Voodoo-Priester mal gesehen hat, wie der weiße Mann eine Memory-mapped file benutzt hat, um etwas schneller zu machen, ist das nun das Zaubermittel für alle Performanceprobleme?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509071</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509071</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Mon, 19 Sep 2016 08:55:07 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 10:15:43 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/31691">@dachschaden</a><br />
Ich muss SeppJ Recht geben, dein Beitrag ist grösstenteils einfach nur Bullshit.<br />
Alleine wie du Kontextwechsel mit TLB-Misses vergleichst ist drollig^10. Oder dass du auf bem TLB-Cache rumreitest und den normalen Datencache dabei vollkommen ignorierst.</p>
<p>Dein Beitrag zeigt wirklich dass du von gewissen Dingen keinen Plan hast. Und über Dinge zu schreiben von denen man keinen Plan hat, das ist ein Problem. Ein grosses Problem.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509079</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509079</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 19 Sep 2016 10:15:43 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 13:35:13 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>Bitte richtig lesen, die Tipps zu 3+4 sind Voodoo. 2 ist einfach nur den Aufwand nicht wert. Optimier die Pipelines (sowohl Daten als auch Instructions), damit gewinnst du mit einfacheren Mitteln viel mehr.</p>
</blockquote>
<p>Ich gehe hier von einer einfachen <code>memmem</code> -Suche aus. Standardmittel. Wenn man hier bereits optimieren will, ist was ganz anderes fundamental kaputt.</p>
<p>SeppJ schrieb:</p>
<blockquote>
<p>3: Und wie machst du sonst dynamische Speicheranforderungen? Entweder du brauchst sie, oder du verwendest sie besser nicht. Aber wenn du sie brauchst, dann glaubst du doch wohl nicht im Ernst, dass der Name der Handlerstruktur einen Unterschied macht?</p>
</blockquote>
<p>Ich sehe so oft Leute, die dynamische Speicheranforderungen verwenden, und das wird gar nicht gebraucht. Beispiel aus dem Kopf: eine Zahl in einen String schreiben. Oder Daten von einem Socket byteweise lesen und in ein Array packen. Es geht nicht darum, keine dynamischen Speicheranforderungen zu verwenden, sondern sie nur dann zu verwenden, wenn es Sinn ergibt.</p>
<p>Wenn man keine MMFs verwenden will, ist man zur Ermittelung der Buffergröße dazu gezwungen. Die Frage ist nicht: &quot;Brauche ich dynamische Speicheranforderungen?&quot;, sondern &quot;Warum kann/will ich keine MMFs verwenden?&quot;.</p>
<p>SeppJ schrieb:</p>
<blockquote>
<p>4: Was hat deine Lösung mit dem beschriebenen Problem zu tun? Weil der Voodoo-Priester mal gesehen hat, wie der weiße Mann eine Memory-mapped file benutzt hat, um etwas schneller zu machen, ist das nun das Zaubermittel für alle Performanceprobleme?</p>
</blockquote>
<p>Ein Performanceproblem, welches hier am Deutlichsten zu sehen ist, ist die unnötige Kopie der Daten in den eigenen Buffer (C++-Streams halt). Jenes kann man eliminieren. Was dann übrig bleibt, ist die Sorge des OP, seine eigene Kopie könnte irgendwie die Performance beeinträchtigen, und die ist so gering, dass sie nun wirklich kaum zu rechtfertigen ist.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/31691">@dachschaden</a><br />
Ich muss SeppJ Recht geben, dein Beitrag ist grösstenteils einfach nur Bullshit.</p>
</blockquote>
<p>Genau das hat SeppJ nicht geschrieben (habe ich anfangs aber auch nicht korrekt gelesen). Sondern nur, dass 2 den Aufwand nicht wert ist. Und das habe ich auch von Anfang an gesagt.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Alleine wie du Kontextwechsel mit TLB-Misses vergleichst ist drollig^10</p>
</blockquote>
<p>Hm, habe mich jetzt nochmal ein bisschen informiert. Ein CW (Linux) kann 100 ns bis mehrere μs benötigen (jetzt nur der Overhead durch den Wechsel, nicht das Einladen der Daten), ein TLB-Miss auf einem Sandy-Bridge ~60 ns. Aber den CW hast du nur immer beim Einladen der Daten, den TLB-Miss hast du ständig (neue Seite wird angefangen, wirft alte Seite raus, Seite wird überprüft, neue Seite wird angefangen, wirft alte Seite raus ...). Bei konservativen 2 MiB (512 Seiten) haben wir also eine Verzögerung von 512 x 60 ns ~ 31 μs.</p>
<p>Pauschal würde ich daher mal davon ausgehen, dass TLB-Misses stärker wehtun. Wenn du dem was hinzuzufügen hast - bin für alles offen. Aber dann komm bitte mit Argumenten. *</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Oder dass du auf bem TLB-Cache rumreitest und den normalen Datencache dabei vollkommen ignorierst.</p>
</blockquote>
<p>200 Cycles (~100 ns) wegen einer Line, während der Datencache größer ist als der TLB, vs. 31 μs ... ich weiß ja nicht, aber ich glaube, ich <em>könnte</em> den Datencache berechtigterweise ignoriert haben. Allein von der Logik her: mehrere Hauptspeicherzugriffe (TLB-Miss) vs. einen (Cache-Miss) ...</p>
<p>EDIT: auch nicht vergessen: Der D-Cache kann prefetching. Die Daten muss man aber immer noch von Speicher laden. Dies kann tatsächlich langsamer sein als die CSs.</p>
<p>EDIT 2: *Das gilt auch für SeppJ. A fool can despise what he cannot get.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509085</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509085</guid><dc:creator><![CDATA[dachschaden]]></dc:creator><pubDate>Mon, 19 Sep 2016 13:35:13 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 13:10:23 GMT]]></title><description><![CDATA[<p>dachschaden schrieb:</p>
<blockquote>
<p>hustbaer schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/31691">@dachschaden</a><br />
Ich muss SeppJ Recht geben, dein Beitrag ist grösstenteils einfach nur Bullshit.</p>
</blockquote>
<p>Genau das hat SeppJ nicht geschrieben</p>
</blockquote>
<p>Ich war nur höflich. Ich habe das Gesamtpaket schon durchaus bewusst zu Anfang &quot;Schmarrn&quot; genannt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509092</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509092</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Mon, 19 Sep 2016 13:10:23 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 17:18:04 GMT]]></title><description><![CDATA[<p>Ich habe jetzt die Wikipedia Seiten für TLB (Translation lookaside buffer) und den Cache geöffnet, verstehe die Beschreibungen jedoch nicht so recht.</p>
<p>Kennt wer gute und einfache Referenzen, wo solches Architektur-Zeug (denk ich mal) genauer erleuchtet wird, damit ich der Diskussion besser folgen kann?</p>
<p>Wäre ich echt dankbar dafür, wenn es da eine einfachere Erklärung dazu gäbe.</p>
<p>Zum Thema mit dem Buffer: Ich lasse den Anwender meiner Klasse selbst entscheiden, wie groß der Buffer sein soll. Ich habs mit 1024 KiB getestet und funktioniert soweit ganz gut - auch das mit dem &quot;Ende des Buffers mit sich schleifen&quot;, funktioniert ganz gut. Ich lese einfach X Bytes aus, teste sie und schiebe den Input Stream wieder um Pattern.size() Bytes zurück. Läuft jetzt echt schneller als vorhin, danke dafür.</p>
<p>Ich erstelle übrigens ein einziges Mal einen Vektor mit der angegeben Buffergröße und überschreibe dann immer die Daten. Dabei hab ich eine <code>bytes_available()</code> -Funktion geschrieben, um zu testen, ob der Rest, den man noch einlesen muss kleiner ist, als der Buffer selbst, wenn das der Fall ist, wird der Vektor <code>resize()</code> et. Aber das ist glaub ich jetzt nicht so ein großes Performance-Leck, das kann nämlich nur ein einziges Mal im Programm vorkommen.</p>
<p>Dann habe ich aber noch eine Frage: Wäre es nicht klüger <code>std::istream::readsome()</code> zu verwenden? Der gibt mir die Anzahl an Bytes zurück, die tatsächlich eingelesen wurden und könnte somit eine Funktion wie <code>bytes_available()</code> einsparen. Das mit <code>bytes_available()</code> funktioniert übrigens mit <code>seekg()</code> und <code>tellg()</code> . Oder tut das alles nicht zur Sache?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509118</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509118</guid><dc:creator><![CDATA[Pipette]]></dc:creator><pubDate>Mon, 19 Sep 2016 17:18:04 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Mon, 19 Sep 2016 17:36:52 GMT]]></title><description><![CDATA[<p>Pipette schrieb:</p>
<blockquote>
<p>Kennt wer gute und einfache Referenzen, wo solches Architektur-Zeug (denk ich mal) genauer erleuchtet wird, damit ich der Diskussion besser folgen kann?</p>
</blockquote>
<p>Ich hab' sogar '<a href="http://lwn.net/Articles/250967/" rel="nofollow">nen Link verpflanzt</a> ... aber wenn das Zeug für dich komplettes Neuland ist, dann lass es sein.</p>
<p>Ja, ist lang. Ist auch kompliziert. Da sitzt du lange dran. Aber am Ende bist du schlauer als hustbaer. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Pipette schrieb:</p>
<blockquote>
<p>Ich lese einfach X Bytes aus, teste sie und schiebe den Input Stream wieder um Pattern.size() Bytes zurück. Läuft jetzt echt schneller als vorhin, danke dafür.</p>
</blockquote>
<p>Du brauchst Pattern.size() - 1. Sonst hättest du das Muster ja gefunden. Aber wenn du es nicht findest, fehlt dir wenigstens ein Byte. Deswegen das -1.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509122</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509122</guid><dc:creator><![CDATA[dachschaden]]></dc:creator><pubDate>Mon, 19 Sep 2016 17:36:52 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Tue, 20 Sep 2016 09:25:34 GMT]]></title><description><![CDATA[<p>dachschaden schrieb:</p>
<blockquote>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Alleine wie du Kontextwechsel mit TLB-Misses vergleichst ist drollig^10</p>
</blockquote>
<p>Hm, habe mich jetzt nochmal ein bisschen informiert. Ein CW (Linux) kann 100 ns bis mehrere μs benötigen (jetzt nur der Overhead durch den Wechsel, nicht das Einladen der Daten),</p>
</blockquote>
<p>Was interessiert es irgendwen wie lange der Context-Switch &quot;alleine&quot; dauert, wenn das nicht die Penalty ist die man im Programm dadurch real hat?<br />
Der Context-Switch haut viel stärker rein als bloss die Kosten des Switch alleine. Schliesslich fängt da dann an neuer Code zu laufen. Code der vermutlich irgendwas ganz anderes macht. Code der mit ziemlicher Sicherheit zu L1 Misses im I-Cache, D-Cache *und* TLB-Cache führt. Was erstmal selbst Zeit kostet, und dann weiters nochmal Zeit kostet wenn der ganze Ranz der dabei aus den Caches evicted wurde wieder reingelesen werden muss - was effektiv die Kosten dieser Cache-Misses verdoppelt.<br />
Und wenn der Context-Switch in einen anderen Prozess switched, dann wird's erst richtig böse. Dann werden nänmlich gleich alle TLB-Einträge ungültig die in den Usermode Adressraum zeigen. Und je nach CPU kann es nötig sein dabei den gesamten TLB für ungültig zu erklären.</p>
<p>dachschaden schrieb:</p>
<blockquote>
<p>ein TLB-Miss auf einem Sandy-Bridge ~60 ns. Aber den CW hast du nur immer beim Einladen der Daten, den TLB-Miss hast du ständig (neue Seite wird angefangen, wirft alte Seite raus, Seite wird überprüft, neue Seite wird angefangen, wirft alte Seite raus ...).</p>
</blockquote>
<p>Ich verstehe nicht worauf du hinaus willst. Wieso sollte man den TLB Miss ständig haben?<br />
Du lässt die Daten vom OS 1x in den Puffer reinkopieren, da hast du u.U. den 1. TLB Miss (pro Page). Und dann prüfst/verarbeitest du die Daten im Puffer. Dort hast du - wieder nur u.U. - den 2. Miss (pro Page). 2x (pro Page) ist &quot;ständig&quot; oder wie?</p>
<p>dachschaden schrieb:</p>
<blockquote>
<p>Pauschal würde ich daher mal davon ausgehen, dass TLB-Misses stärker wehtun. Wenn du dem was hinzuzufügen hast - bin für alles offen. Aber dann komm bitte mit Argumenten. *</p>
</blockquote>
<p>Aus deinem Beitrag ist ziemlich klar zu erkennen dass du selbst kaum bis gar keine Versuche zu dem Thema angestellt hast. Und jetzt willst du von mir &quot;Argumente&quot;? Eins hab ich dir oben gegeben: du kannst nicht einfach haufenweise Dinge ignorieren, dann sowas sagen wie &quot;ich glaube X haut mehr rein als Y und wenn jmd. anderer Meinung ist dann will ich aber gute Argumenten hören&quot;. Speziell nicht bei einem Thema wo man sich so super-einfach verschätzen kann.<br />
Mach doch einfach ein paar Versuche zu dem Thema. Und dann berichte deine Resultate und die Interpretation dieser Resultate.</p>
<p>dachschaden schrieb:</p>
<blockquote>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Oder dass du auf bem TLB-Cache rumreitest und den normalen Datencache dabei vollkommen ignorierst.</p>
</blockquote>
<p>200 Cycles (~100 ns) wegen einer Line, während der Datencache größer ist als der TLB, vs. 31 μs ... ich weiß ja nicht, aber ich glaube, ich <em>könnte</em> den Datencache berechtigterweise ignoriert haben. Allein von der Logik her: mehrere Hauptspeicherzugriffe (TLB-Miss) vs. einen (Cache-Miss) ...</p>
</blockquote>
<p>Ach das ist schon anstrengend.<br />
Dir ist bekannt dass die meisten CPUs kein Prefetching über Pagegrenzen hinweg können, oder?<br />
D.h. du hast trotz Prefetching potentiell pro Page einen D-Cache Miss.<br />
Genau so wie du potentiell pro Page einen TLB-Cache Miss hast.<br />
Fällt dir was auf?<br />
Oder überleg' dir mal weiter wie gross der (shared!) L3 Cache von üblichen CPUs ist, und dann guck viele Einträge der (per <s>Core</s>HW-Thread!) TLB-Cache fassen kann, und für wie viel Speicher das reicht (unter der Annahme dass jede Page zu 100% verwendet wird).<br />
Fällt dir vielleicht jetzt was auf?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509130</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509130</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 20 Sep 2016 09:25:34 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Tue, 20 Sep 2016 07:00:19 GMT]]></title><description><![CDATA[<p>Naja, bevor dachschaden mal wieder eine neue Speicherverwaltung baut, frage ich mal dumm.</p>
<p>Welchen Pattern-Matching Algorithmus wird hier verwendet? Vielleicht lässt sich ja da noch was drehen.</p>
<p><a href="https://de.wikipedia.org/wiki/String-Matching-Algorithmus" rel="nofollow">https://de.wikipedia.org/wiki/String-Matching-Algorithmus</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509142</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509142</guid><dc:creator><![CDATA[Bitte ein Bit]]></dc:creator><pubDate>Tue, 20 Sep 2016 07:00:19 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Tue, 20 Sep 2016 11:39:32 GMT]]></title><description><![CDATA[<p>dachschaden schrieb:</p>
<blockquote>
<p>SeppJ schrieb:</p>
<blockquote>
<p>Dann zielst du mit deinen Maßnahmen auch voll am Stand der Technik vorbei.</p>
</blockquote>
<p>Auf der Basis kann man auch argumentieren, dass C und C++ &quot;voll am Stand der Technik&quot; vorbeizielen, weil wir ja jetzt Java haben. Oder C#. Oder Swift oder Rust oder was auch immer.</p>
</blockquote>
<p>völliger schwachsinn... wieso ist java neuer als c++ ?<br />
glaube sogar c++ hat den neueren standard. (bin mir gerade nicht ganz sicher...)</p>
<p>was soll das also bedeuten? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<p>zu mal selbst wenn c++ &quot;älter&quot; wäre ist das nicht das selbe wie &quot;voll am Stand der Technik vorbei&quot;.</p>
<p>denn c++ hat durchaus seine berechtigung gegenüber java und ich z.B. brauche kein java, kann es(keine laufzeitumgebung) und will es auch nicht nutzen.</p>
<p>also was soll deine aussage bedeuten macht für mich gar keine sinn...?</p>
<p>außerdem dynamische speicherverwaltung hat nicht den vorteil das sie schneller oder sonst was ist (wie du ja schon gemerkt hast), sonder dafür das sicherer und fehlerunanfälliger entwickelt werden kann und du keine angst haben musst ein delete zuviel oder zuwenig oder ähnliches zu haben. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<p>dachschaden schrieb:</p>
<blockquote>
<p>Und wie machst du sonst dynamische Speicheranforderungen? Entweder du brauchst sie, oder du verwendest sie besser nicht. Aber wenn du sie brauchst, dann glaubst du doch wohl nicht im Ernst, dass der Name der Handlerstruktur einen Unterschied macht?</p>
</blockquote>
<p>na ja kommt sicher immer konkret auf das problem an.</p>
<p>aber ich hab gelernt solage du keinen grund hast die stl-container nicht zu benutzen dann mach es und optimiert wird nachdem programmieren wenn das programm nicht schnell genug ist...</p>
<p>ich möchte ja eine übersichtliche, wartbare und erweiterbare lösung haben, das was du beschreibst will eig niemand da es nicht wartbar geschweige denn nachvollziehbar ist<br />
(aber ok es läuft 1 millisekunde bzw mehr oder weniger schneller wow, hast schonmal was von wirtschaftlichkeit gehört? - nicht jedes programm muss das schnellste sein)</p>
<p>aber wenn du ein kleines programm schreibst nimm die stl-container...<br />
warum nicht weil dein programm ansonsten 1millisekunde eher fertig ist ?</p>
<p>du dafür aber fehleranfälliger programmierst und vorraussichtlich auch mehr zeit brauchst...</p>
<p>lg</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509160</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509160</guid><dc:creator><![CDATA[WASWEISSICHSCHON]]></dc:creator><pubDate>Tue, 20 Sep 2016 11:39:32 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Tue, 20 Sep 2016 13:08:07 GMT]]></title><description><![CDATA[<p>So, jetzt habe ich mal das Programm implementiert. Dem TE möchte ich die Lösung natürlich nicht direkt verraten, aber hier mal ein paar Kenndaten:</p>
<p>- Gentoo Linux 4.6.0<br />
- In C geschrieben<br />
- kein Support für Windows (könnte ich einfügen, aber dann müsste ich Teile von Backend-Code einbinden, den ich gar nicht veröffentlichen will)<br />
- Daten werden wie beschrieben über <code>mmap</code> eingeladen und ausgeladen.<br />
- für das Speicher-Mapping wird <code>PROT_READ | PROT_WRITE</code> und <code>MAP_PRIVATE | MAP_NORESERVE | MAP_32BIT</code> verwendet (weil wir den reservierten Bereich unten im Speicher haben wollen)<br />
- für das File-Mapping wird <code>PROT_READ</code> und <code>MAP_SHARED | MAP_NORESERVE</code> verwendet, das Mapping wird direkt nach dem Speichermapping gesetzt.<br />
- die Tests fanden mit /dev/sds6 statt (Systempartition - ich wusste gar nicht, dass ich da Shakespeare druff hatte, aber egal).<br />
- um den Test nicht zu verfälschen (siehe unten) wurden nur die ersten 512 MiB der Partition eingelesen<br />
- die Daten befanden sich bereits im I/O-Cache (Arbeitsspeicher), es wurde hier also nicht das Einladen mitgemessen.<br />
- die CPU-Daten habe ich bereits gepostet.</p>
<p>Ein paar Punkte am Rande:</p>
<ul>
<li><code>mmap</code> mappt nur dann Daten von der Festplatte, wenn der Kernel es muss - sprich, das eigentliche Laden wird nicht in den Calls gemacht, sondern während auf die Speicherbereiche ( <code>memmem</code> ) zugegriffen wird.<br />
- eine Iteration hat somit zwei CS (Kontextwechsel - <code>mmap</code> und <code>munmap</code> )</li>
</ul>
<p>Es wurde gemessen:</p>
<p><code>mmap</code> mit 256 Mebibyte Bufferlänge. Durchschnittliches Ergebnis: 722 Millionen Cycles, 4 CS<br />
<code>mmap</code> mit 64 Mebibyte Bufferlänge. Durchschnittliches Ergebnis: 730 Millionen Cycles, 16 CS<br />
<code>mmap</code> mit 4 Mebibyte Bufferlänge. Durchschnittliches Ergebnis: 705 Millionen Cycles, 256 CS<br />
<code>mmap</code> mit 2 Mebibyte Bufferlänge. Durchschnittliches Ergebnis: 700 Millionen Cycles, 512 CS<br />
<code>mmap</code> mit 1 Mebibyte Bufferlänge. Durchschnittliches Ergebnis: 700 Millionen Cycles, 1024 CS<br />
<code>mmap</code> mit 64 Kibibyte Bufferlänge. Durchschnittliches Ergebnis: 715 Millionen Cycles, 16384 CS</p>
<p>Das Programm habe ich jetzt schnell zusammengeschrieben, und es sind auch vermutlich noch ein paar Bugs drin. Aber einen groben Überblick sollte es schon liefern: Kontextwechsel wiegen offenbar nicht so schwer wie die Verunreinigung des Caches bis zum (<em>von mir prophezeiten</em>) Threshold von 2 Mebibyte.</p>
<p>Gerade habe ich keine Zeit mehr, daran weiterzuarbeiten. Aber die Tage werde ich es mir nochmal genauer anschauen.</p>
<p>WASWEISSICHSCHON schrieb:</p>
<blockquote>
<p>völliger schwachsinn... wieso ist java neuer als c++ ?</p>
</blockquote>
<p>Mein Eindruck war immer, dass die Hauptkritik der Java-Leute an C++ war, dass dieses viel zu kompliziert, weswegen man dann was eigenes gebaut hat. Eine Ironie, dass die <a href="http://www.heise.de/ix/artikel/Direkteinspritzer-958569.html" rel="nofollow">Komplexitätsberge, die Java inzwischen auftürmt</a>, C++ in den Schatten stellt .</p>
<p>WASWEISSICHSCHON schrieb:</p>
<blockquote>
<p>denn c++ hat durchaus seine berechtigung gegenüber java und ich z.B. brauche kein java, kann es(keine laufzeitumgebung) und will es auch nicht nutzen.</p>
</blockquote>
<p>Das war das Argument von SeppJ, dem ich nicht beipflichte. C hat auch seine Berechtigung, ob einige Leute meinen (ich schaue niemanden an hier), dass es voll am Stand der Technik vorbeigeht.</p>
<p>WASWEISSICHSCHON schrieb:</p>
<blockquote>
<p>außerdem dynamische speicherverwaltung hat nicht den vorteil das sie schneller oder sonst was ist (wie du ja schon gemerkt hast), sonder dafür das sicherer und fehlerunanfälliger entwickelt werden kann und du keine angst haben musst ein delete zuviel oder zuwenig oder ähnliches zu haben. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
</blockquote>
<p>Schonmal einen Allokator programmiert? Oder zumindest mal in den Code von einem geblinzelt?</p>
<p>Beides kann ich bejahen. Und mein Allokator hat keines der genannten Probleme, hat keine Userspace-Locks, und kann sogar, wenn Support dafür besteht, für kleinere Allokationen diese einfacher auf dem Stack anlegen (für gewöhnlich auf alles unter 4 KiB getrimmt). Er ist wohl auf Bulk-Allokationen ausgerichtet - 10-mal Resizing wird dich mit dem Ding mehr kosten als mit Standardmitteln (CW wegen), aber wenn du die vermeidest, ist das Ding rasend.</p>
<p>EDIT: @Bitte ein Bit, das noch: verwende <code>memmem</code> , ich habe aber vor Jahren eine Boyer-Moore-Implementierung gebaut, die könnte ich, wenn ich Zeit habe, auch noch mal einbauen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509169</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509169</guid><dc:creator><![CDATA[dachschaden]]></dc:creator><pubDate>Tue, 20 Sep 2016 13:08:07 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Tue, 20 Sep 2016 13:42:31 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>Ich hab das Programm jetzt auch fertig implementiert, sind sicherlich noch einige Dinge da, die man besser hätte machen können. Aber naja. Ich wills mit euch teilen. Würde mich freuen, wenn sich jemand den Code mal ansehen will und mir noch weitere Ratschläge gibt, wie man das Programm noch besser gestalten kann. Das Programm ist ein Kommandozeilenwerkzeug und ich habe es so gebaut, dass man wirklich alles selber einstellen kann. Die Namen der Optionen sind vielleicht nicht immer perfekt gewählt, aber das liegt an meinen mangelnden Englischkenntnissen. Ist auch wirklich kein großes Ding, sind rund 200 - 300 Zeilen. Und es klappt wunderbar! Ich habe mal testhalber nach dem Muster ' <code>#include &lt;iostream&gt;</code> ' gesucht und habe tatsächlich einen Haufen (eigentlich alles) gefunden.</p>
<p><a href="https://github.com/pipettes/filter" rel="nofollow">filter on github</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509173</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509173</guid><dc:creator><![CDATA[Pipette]]></dc:creator><pubDate>Tue, 20 Sep 2016 13:42:31 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Tue, 20 Sep 2016 14:57:31 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/31691">@dachschaden</a><br />
<s>Zwei</s>Ein paar Dinge die mir dazu einfallen.</p>
<ol>
<li>
<p>Memory Mapping verursacht potentiell haufenweise Context-Switches, nicht bloss einen pro Map und einen pro Unmap Aufruf. Und zwar wenn man auf Daten zugreift bevor sie gelesen werden konnten. Wenn die Daten alle aus dem File-Cache/Block-Cache des OS kommen wird das vermutlich selten passieren. Je nachdem wo die Daten die da verarbeitet werden herkommen wird das im Realeinsatz allerdings sehrwohl passieren.</p>
</li>
<li>
<p>Ein Kontextwechsel von &quot;ich tu was&quot; zu &quot;ich tu nix&quot; und ein zweiter wieder zurück zu &quot;ich tu wieder was&quot; tut lange nicht so sehr weh wie ein &quot;echter&quot; Kontextwechsel von &quot;ich tu was&quot; zu &quot;ich tu was anderes&quot;. Soll heissen: Wäre interessant wie das ganze skaliert wenn du im Hintergrund Prozesse mit niedrigere Priorität laufen hast die die CPU komplett auslasten.<br />
(Dein Test ist natürlich aussagekräftig für Fälle wo das Programm die Maschine für sich alleine hat, aber das muss ja nicht das einzige Szenarion sein an dem man interessiert ist.)</p>
</li>
<li>
<p>Davon abgesehen bezweifle ich dass <code>mmap</code> hier überhaupt das Mittel der Wahl ist - ich bin fast sicher dass man mit einer selbstgestrickten Producer-Consumer Queue noch ein paar Zyklen rausholen kann. Obwohl sich das dann vermutlich auch nur im &quot;zahlt sich nicht aus&quot; Bereich abspielen wird.</p>
</li>
<li>
<p><a href="https://gcc.gnu.org/projects/prefetch.html" rel="nofollow">PREFETCH</a>?</p>
</li>
</ol>
]]></description><link>https://www.c-plusplus.net/forum/post/2509180</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509180</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 20 Sep 2016 14:57:31 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Tue, 20 Sep 2016 16:41:15 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<ol start="3">
<li>Davon abgesehen bezweifle ich dass <code>mmap</code> hier überhaupt das Mittel der Wahl ist</li>
</ol>
</blockquote>
<p>Ich denke auch dass Memory Mapping hauptsächlich bei Random Access glänzt.<br />
Das beschriebene Problem sieht mir doch ziemlich sequentiell aus, und auch das OS kommt nicht drumherum die Daten erstmal<br />
vom langsamen Datenträger einzulesen. Wenn man unnötige Kopien im Speicher sparen will, macht es evtl. mehr Sinn keine<br />
Funktionen mit internem Buffering zu verwenden, sondern die Daten direkt (unbuffered) in den Speicherbereich einzulesen wo sie weiterverarbeitet werden.<br />
Was die Buffergrösse angeht würde ich mir erstmal ein paar sinnvolle Größen überlegen (Blockgrösse auf Datenträger, Speicherseiten-Grösse, Default-Werte<br />
für Funktionen mit internem Buffering) und dann experimentell eine geeignete bestimmen. Erst wenn ich damit am Limit angelangt bin würde ich schauen ob<br />
sich mit irgendwelcher Thread- und Kontextswitch-Magie vielleicht noch etwas herausholen lässt - ich glaube allerdings dass diese potentiellen Effekte von<br />
den Datenträgerzugriffen derart dominiert werden (auch bei schneller SSD), dass sie kaum messbar sind.</p>
<p>Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509204</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509204</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Tue, 20 Sep 2016 16:41:15 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Wed, 21 Sep 2016 00:02:32 GMT]]></title><description><![CDATA[<p>Ja. Jain. Bei <code>mmap</code> und Random IO bin ich nicht unbedingt deiner Meinung. Aber das Thema hatten wir schon.</p>
<p>Ansonten ... ja.<br />
Das <s>grösste</s> schlimmste Bottleneck hier ist wohl der Datenträger - es sei dann man hat ne superschnelle SSD-Karte die mehrere GB/s raushaut.<br />
Das zweit<s>grösste</s>schlimmste Bottleneck ist dann die CPU. Aber nicht der TLB oder sonstwas, sondern einfach der Suchalgorithmus. Der Test von dachschaden kommt auf mehr als 1 Cycle/Byte, d.h. weniger als 4 GB/s auf nem 4GHz Chip. Und das ist weit entfernt von der Hauptspeicherbandbreite (üblicherweise &gt;= 20 GB/s).</p>
<p>Alles andere kommt danach.</p>
<p>Das hat dachschaden aber auch nie bestritten. Er hat es bloss in einen Thread gepostet wo es wohl um alles andere als um die letzten 5% Performance geht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509229</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509229</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Wed, 21 Sep 2016 00:02:32 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Tue, 20 Sep 2016 20:38:10 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Ja. Jain. Bei <code>mmap</code> und Random IO bin ich nicht unbedingt deiner Meinung. Aber das Thema hatten wir schon.</p>
</blockquote>
<p>Bei völlig zufälligen Zugriffen (wohl eher selten) würde ich da auch zurückrudern, sagen wir mal Random Access mit sequentiellen Abschnitten dazwischen.<br />
So was wie ein B-Baum auf Platte könnte davon gut profitieren (öfter Blöcke auf dem Pfad zum Blattknoten bereits im OS-Cache).<br />
Apropos SSD, im Labor nähern sich so einige Flashspeicher-Konstruktionen mit über 10GiB/s Durchsatz schon gefährlich an den Arbeitsspeicher an...<br />
wer weiss was uns da noch erwartet in ein paar Jahren <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509236</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509236</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Tue, 20 Sep 2016 20:38:10 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Wed, 21 Sep 2016 06:29:11 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Und zwar wenn man auf Daten zugreift bevor sie gelesen werden konnten.</p>
</blockquote>
<p>Hm, gut, stimmt, da habe ich mich unklar ausgedrückt. Was ich meinte, waren die CS, die man direkt zu verantworten hat - oder besser, die, die man vermeiden kann.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Wenn die Daten alle aus dem File-Cache/Block-Cache des OS kommen wird das vermutlich selten passieren.</p>
</blockquote>
<p>Das wiederum halte ich für ein Gerücht - zumindest was die Häufigkeit angeht.</p>
<pre><code>int main(void)
{
    const size_t max_pages = 40;

    int fd;
    uint8_t x;
    uint8_t*file;
    uint64_t rdtsc_before,rdtsc_after;
    size_t i;

    fd = open(&quot;/dev/sda6&quot;,O_RDONLY);
    if(fd == -1)
    {
        fprintf(stderr,&quot;Kein gültiges Device, verschwinde\n&quot;);
        goto LABEL_NO_FD;
    }

    file = mmap(NULL,4096 * max_pages,PROT_READ,MAP_SHARED | MAP_NORESERVE,fd,0);
    if(file == MAP_FAILED)
        goto LABEL_NO_MAP;

    for(i = 0;i &lt; max_pages;i++)
    {
        rdtsc_before = rdtsc();
        x = file[4096 * i];
        rdtsc_after = rdtsc();

        printf(&quot;%lu|%lu|\n&quot;,i,rdtsc_after - rdtsc_before);
    }

LABEL_NO_MAP:
    close(fd);
LABEL_NO_FD:
    return 0;
}
</code></pre>
<p>Hier wird ein einzelnes Byte vom gemappten Device in <code>x</code> gespeichert. Habe sichergestellt, dass das Lesen nicht wegoptimiert wird. Den Teil der Platte hat der Kernel immer im I/O Cache, das kann man auch ganz leicht sicherstellen, indem man das Programm immer wieder aufruft.</p>
<p>Die Ausgabe:</p>
<pre><code>0|9940|
1|36|
2|24|
3|32|
4|24|
5|24|
6|28|
7|28|
8|24|
9|28|
10|28|
11|28|
12|24|
13|24|
14|24|
15|28|
16|2808|
17|7256|
18|24|
19|24|
20|24|
21|24|
22|24|
23|24|
24|24|
25|24|
26|24|
27|28|
28|28|
29|24|
30|24|
31|24|
32|24|
33|3320|
34|24|
35|28|
36|24|
37|24|
38|24|
39|24|
</code></pre>
<p>Beim ersten Zugriff gibt es einen Page Fault, der wird vom Kernel abgefangen (CS), dann werden die Daten eingemappt. Beim zweiten Zugriff gibt es keinen Wechsel mehr, die Daten sind bereits drin.<br />
Lustig fand ich an der Stelle die Heuristik des Kernel - ich habe immer gedacht, der Kernel lädt immer nur die Seite ein, auf die zugegriffen wird, aber die Anzahl an Seiten, die der Kernel einmappt, scheint zu variieren.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Wäre interessant wie das ganze skaliert wenn du im Hintergrund Prozesse mit niedrigere Priorität laufen hast die die CPU komplett auslasten.</p>
</blockquote>
<p>Kann ich testen. Wobei ich im Hintergrund einen Emulator, einen Browser und den VLC laufen hatte. Wird aber wahrscheinlich nicht ausgereicht haben, um in dieser Hinsicht aussagekräft zu sein.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>Davon abgesehen bezweifle ich dass <code>mmap</code> hier überhaupt das Mittel der Wahl ist - ich bin fast sicher dass man mit einer selbstgestrickten Producer-Consumer Queue noch ein paar Zyklen rausholen kann.</p>
</blockquote>
<p>Werden wir sehen. Ich will erst mal schauen, ob <code>read</code> nicht schneller ist. Aber wie gesagt, erst in den nächsten Tagen.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<ol start="4">
<li><a href="https://gcc.gnu.org/projects/prefetch.html" rel="nofollow">PREFETCH</a>?</li>
</ol>
</blockquote>
<p>1. Meine Erfahrungen mit manuellem Prefetch waren bisher ... mäßig, aber:<br />
2. Das ist dann eine Sache des Algorithmus (sprich <code>memmem</code> ). welches keine intelligente Mustersuche implementiert. Mein Beispiel war jetzt vor allem darauf ausgelegt, zu zeigen, dass die Buffergroße, so wie ich gesagt hatte - nicht einfach nur groß sein sollte, sondern dass es da auch andere Faktoren gibt.</p>
<p>Ich konnte auch einfach einen Zugriff auf jeden Seitenanfang durchführen und dann wiederholen, das lässt sich erstmal wesentlich einfacher optimieren als die Mustersuche, und wir würden trotzdem sehen, was am Ende schneller ist. Oder siehst du was, was dem widerspräche?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509244</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509244</guid><dc:creator><![CDATA[dachschaden]]></dc:creator><pubDate>Wed, 21 Sep 2016 06:29:11 GMT</pubDate></item><item><title><![CDATA[Reply to [Schnelligkeit] Festplatte einlesen und nach Pattern suchen on Wed, 21 Sep 2016 09:26:16 GMT]]></title><description><![CDATA[<p>dachschaden schrieb:</p>
<blockquote>
<p>Ich konnte auch einfach einen Zugriff auf jeden Seitenanfang durchführen und dann wiederholen, das lässt sich erstmal wesentlich einfacher optimieren als die Mustersuche, und wir würden trotzdem sehen, was am Ende schneller ist. Oder siehst du was, was dem widerspräche?</p>
</blockquote>
<p>Wenn du ganz gezielt nur die Auswirkung des TLB messen willst vermutlich nicht. Was du dadurch allerdings machst, ist die Auswirkung des Datencache aus der Messung grösstenteils zu entfernen.</p>
<p>Aber du könntest z.B. ne XOR Prüfsumme rechnen. Das lässt sich auch halbwegs einfach optimieren.</p>
<p>dachschaden schrieb:</p>
<blockquote>
<p>Lustig fand ich an der Stelle die Heuristik des Kernel - ich habe immer gedacht, der Kernel lädt immer nur die Seite ein, auf die zugegriffen wird, aber die Anzahl an Seiten, die der Kernel einmappt, scheint zu variieren.</p>
</blockquote>
<p>Wenn der Kernel immer nur die eine Seite laden würde, dann wäre Memory-Mapping vermutlich die langsamste Art IO zu machen. Vergleichbar eben wie wenn man unbuffered 4K IOs der Reihe nach an den Datenträger schickt - mit einem syscall pro IO.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2509258</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2509258</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Wed, 21 Sep 2016 09:26:16 GMT</pubDate></item></channel></rss>