Forum: PC-Programmierung Schnelle Suche in großer Datei (1GB)?


von TK (Gast)


Lesenswert?

Hallo zusammen,

ich habe hier folgenden Code (Borland C++ V6) für WIN32 OS geschrieben, 
den ich modifizieren möchte. Problem: Aus einer sehr großen Datei (ca. 
700MB..2GB) muss eine 10Byte Sequenz gesucht werden. Diese kann 
innerhalb der Datei entweder 0x,1x oder 2x auftreten. Die Sequenz kann 
nur an Vielfachen von 0x800 Adr auftreten. Mit dem Code dauert es 
trotzdem noch ca. 45s auf meinem System, bis eine Sequenz, die am Ende 
der Datei vorkommt, gefunden wird. Info: Die Datei wird an dieser Stelle 
weiter bearbeitet. Daher auch der R/W Zugriff auf die Datei.
Geht das noch schneller?
1
bool success=false;
2
DWORD adr,f_pointer;
3
WORD puffer[10];
4
unsigned long Bytes_read;
5
6
fhnd = CreateFile(f_ilename.c_str(),
7
        GENERIC_WRITE | GENERIC_READ,
8
        FILE_SHARE_WRITE | FILE_SHARE_READ,
9
        NULL,
10
        OPEN_EXISTING,
11
        FILE_ATTRIBUTE_NORMAL,
12
        NULL);
13
if (fhnd != INVALID_HANDLE_VALUE)
14
{
15
  f_len = GetFileSize(fhnd,&f_lenh);
16
  for (adr=0x800;adr<f_len;adr+=0x800)
17
  {
18
    //
19
    //  relative Positionierung mit 0x800-10,FILE_CURRENT
20
    //  ist langsamer, als die absolute Positionierung
21
    //
22
    f_pointer = SetFilePointer(fhnd,adr,NULL,FILE_BEGIN);
23
    if (f_pointer != 0xFFFFFFFF)
24
    {
25
      ReadFile(fhnd,&puffer[0],10,&Bytes_read,NULL);
26
      if ((puffer[0] == 0) &&
27
          (puffer[1] == 0x0815) &&
28
          (puffer[2] == 0x4711) &&
29
          (puffer[3] == 0xDEAD) &&
30
          (puffer[4] == 0xFEED))
31
      {
32
        success = true;
33
        break;
34
      }
35
    }
36
    else
37
    {
38
      GetLastError();
39
      break;
40
    }
41
  }
42
}

Gruß
TK

von Peter II (Gast)


Lesenswert?

TK schrieb:
> Mit dem Code dauert es
> trotzdem noch ca. 45s auf meinem System, bis eine Sequenz, die am Ende
> der Datei vorkommt, gefunden wird.

wie schnell ist dein System?

Normale Festplatte kommt kaum über 100Mbyte/s bei 2GB sind das 
mindestens 20sekunden - und wenn nebenbei noch andere dinge laufen kommt 
man schnell auf die 45 Sekunden.

Die Datei wird, auch wenn du nur ein paar Byte liest, komplett gelesen 
weil die clustergröße oft bei 2k liegt.

Lösung: SSD

von Klaus W. (mfgkw)


Lesenswert?

Möglicherweise geht es deutlich schneller, die Datei mit mmap() an den 
fraglichen Stellen in den Speicher einzublenden und über einen Zeiger 
direkt nach deiner Sequenz zu suchen.

von TK (Gast)


Lesenswert?

Hallo PeterII,

System ist ein WIN-XP32 (AMD 3GHz DualCore).
Es läuft sonst nichts mehr nebenbei.
Ich dachte auch nur daran, z.B. die for evtl in eine do-while zu ändern, 
oder evtl. bei CreateFile mit weiteren Attr. zu arbeiten. Daher meine 
Frage, ob es sinnvolle Modifizierungen an diesem Code gibt, die sich auf 
die Geschw. auswirken.

Gruß
TK

von Peter II (Gast)


Lesenswert?

TK schrieb:
> Es läuft sonst nichts mehr nebenbei.

es läuft immer etwas nebenbeil. Und die schreibst ja selber

> Die Datei wird an dieser Stelle weiter bearbeitet

> Ich dachte auch nur daran, z.B. die for evtl in eine do-while zu ändern,
> oder evtl. bei CreateFile mit weiteren Attr. zu arbeiten. Daher meine
> Frage, ob es sinnvolle Modifizierungen an diesem Code gibt, die sich auf
> die Geschw. auswirken.

das wird nichts bringen, 2GB im Ram suchen dauert keine Sekunde. Das 
lesen der Datei macht 99.9% der Zeit aus und da ist der Flaschenhals die 
Festplatte.

von TK (Gast)


Lesenswert?

Hallo Klaus,

mmap() kennt mein Borland nicht (ich denke das ist eine MemoryMap 
Funktion - oder?)

Gruß
TK

von TK (Gast)


Lesenswert?

Hallo PeterII,

dann werde ich wohl damit leben müssen. Danke für die Infos.

Gruß
TK

von Malte S. (maltest)


Lesenswert?

TK schrieb:
> mmap() kennt mein Borland nicht (ich denke das ist eine MemoryMap
> Funktion - oder?)

Ja. Unter Windows siehe CreateFileMapping() und MapViewOfFile().

von Der Andere (Gast)


Lesenswert?

Es wäre auszuprobieren statt der vielen kleinen Blöcke die Datei in 
großen Blöcken (mehrere MB bis zu 100 MB) zu lesen und dann im Speicher 
zu durchsuchen.
Durch die vielen kleinen Lesevorgänge wird das definitiv nicht 
schneller, weil der Plattencontroller ggf. jedesmal darauf warten muss 
bis der richtige Sektor wieder am Lesekopf vorbeikommt.
Mit einer SSD dürfte das dann völlig anders aussehen.

von Fabian O. (xfr)


Lesenswert?

Da Du die Datei sowieso komplett lesen musst, solltest Du größere Blöcke 
(z.B. 4 MB, am besten experimentieren) in einen Puffer zu lesen und 
darin nach dem Code suchen. Das reduziert die Anzahl der Systemaufrufe 
deutlich.

Das Kopieren in einen eigenen Puffer kannst Du Dir sparen, wenn Du die 
Datei wie erwähnt direkt in den Speicher einblendest (Stichwort Memory 
Mapped File). Im Win32-API heißen die Funktionen CreateFileMapping und 
MapViewOfFile.

Aber auch da musst Du Dich für einen bestimmten Ausschnitt entscheiden, 
den Du in der Schleife verschiebst, da Du in einem 32-Bit-Programm nicht 
die komplette 2GB-Datei in den Adressraum mappen kannst.

von Klaus W. (mfgkw)


Lesenswert?

Malte S. schrieb:
> TK schrieb:
>> mmap() kennt mein Borland nicht (ich denke das ist eine MemoryMap
>> Funktion - oder?)
>
> Ja. Unter Windows siehe CreateFileMapping() und MapViewOfFile().

Ja, heisst bei Windows natürlich anders.
Aber genau das meinte ich.

http://blogs.msdn.com/b/khen1234/archive/2006/01/30/519483.aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366556%28v=vs.85%29.aspx

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

TK schrieb:
> Ich dachte auch nur daran, z.B. die for evtl in eine do-while zu ändern

Wenn das einen auch nur messbaren Geschwindigkeitsunterschied ergibt, 
taugt der Compiler nichts.

von TK (Gast)


Lesenswert?

Hallo Rufus,

das mit for und do-while habe ich zwar noch nicht probiert - aber z.B. 
ist ein SetFilePointer(..,FILE_BEGIN) auch schneller als ein 
SetFilePointer(0x800,FILE_CURRENT) => merklich! Damit hätte ich auch 
nicht gerechnet, ist aber so bei mir.

an alle anderen
CreateFileMapping() / MapViewOfFile() muss ich mir mal ansehen.
Danke für den Hinweis.

Gruß
TK

von Yalu X. (yalu) (Moderator)


Lesenswert?

Ich habe das mal ausprobiert, allerdings nicht mit Windows, sondern mit
Linux und nicht mit Borland C++, sondern mit GCC und nicht mit WinAPI-
sondern mit Standard-I/O-Funktionen (fopen, fseek und fread). Hier sind
die gemessenen Zeiten (jeweils nach Leeren der Lesepuffer im RAM):

1
  interne SSD                 2.0s
2
  externe HD über USB 3.0     9.0s
3
  externe HD über USB 2.0    25.1s

Diese Zeiten entsprechen praktisch exakt denen für das bloße Lesen der
kompletten Datei. Das ist auch nicht verwunderlich, da die fseek-Sprünge
kleiner als die Blockgröße (4KiB) sind. Deswegen würde vermutlich auch
Memory-Mapping keinen Vorteil bringen. Die ca. 2,5 Millionen 16-Bit-
Vergleiche fallen gegenüber dem Einlesen der Datei überhaupt nicht ins
Gewicht.

Schau doch mal nach, wie lange bei dir das reine Einlesen der Datei
dauert. Vielleicht ist deine Festplatte ja auf Grund eines Treiber- oder
Schnittstellenproblems tatsächlich so langsam. Dann weißt du immerhin,
dass es nicht an deiner Software liegt.

von Peter II (Gast)


Lesenswert?

Yalu X. schrieb:
> externe HD über USB 2.0    25.1s

wie groß war die Datei? Bei 1GB sind das 40Mbyte/s - das schafft man 
kaum durch USB2.0

von Klaus W. (mfgkw)


Lesenswert?

Yalu X. schrieb:
> Deswegen würde vermutlich auch
> Memory-Mapping keinen Vorteil bringen.

Es kann schon etwas ausmachen, weil einmal Umkopieren im Speicher 
entfallen wird.
Versuch macht kluch...

von Peter II (Gast)


Lesenswert?

Klaus W. schrieb:
> Es kann schon etwas ausmachen, weil einmal Umkopieren im Speicher
> entfallen wird.

Arbeitsspeicher kopiert mit weit über 1Gbyte/s - kann also nicht 
wirklich entscheidend sein.

von Carl D. (jcw2)


Lesenswert?

Ob fread() aber ohne kopieren direkt Seiten aus dem OS-File-Cache in den 
Prozess mapped, ist fraglich. Mit MemoryMappedFile hat man den 
direktesten Zugang zu den Daten und sieht das einfach als Array an. Und 
das OS tut seinen Teil, die Daten an der richtigen Stelle im Speicher 
auftauchen zu lassen. Speicherkopieren ist natürlich kein Vergleich zum 
Plattenzugriff, aber allein die vereinfachte Programmierung hat was. 
Gelesen wird natürlich mit Anlegen eines Mappings noch garnichts, erst 
bei Zugriff werden die betroffenen Speicherseiten von der Platte geholt.

von Kaj (Gast)


Lesenswert?

TK schrieb:
> das mit for und do-while habe ich zwar noch nicht probiert - aber z.B.
> ist ein SetFilePointer(..,FILE_BEGIN) auch schneller als ein
> SetFilePointer(0x800,FILE_CURRENT) => merklich!
Mag ja sein, aber du sprachest von der Schleife. Und da ist es voellig 
wurst ob du eine for, while, oder do-while schleife nimmst. Aber ja, 
wenn da tatsaechlich merkliche unterschiede rauskommen, schmeiss den 
Compiler weg und besorg dir einen vernueftigen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter II schrieb:
> wie groß war die Datei? Bei 1GB sind das 40Mbyte/s - das schafft man
> kaum durch USB2.0

Mir kam die Geschwindigkeit auch etwas hoch vor. Von meinem alten PC bin
ich nur etwa 32MB/s gewohnt.

Die Dateigröße ist 1024^3+10+1 Byte = 1073741835 Byte. Sie setzt sich
aus 1Gi Nullen, dem String "0123456789" und einem LF am Ende zusammen.

Um sicher zu gehen, dass bei der Übertragung nicht geschummelt wird,
habe ich eine neue Datei erstellt, die statt der Nullen Zufallswerte
enthält. Den Rechner habe ich vor dem Test mitsamt der externen
Festplatte komplett aus- und wieder eingeschaltet, so dass sämtliche
Hardware- und Softwarepuffer gelöscht sein sollten. Die Zeiten sind
jetzt 27,6s für das Testprogramm und 27,3s für cat file >/dev/null.
Das wären aber immer noch 39MB/s.

Wo liegt denn die theoretische Grenze bei USB High Speed?

Aber wie auch immer: Es scheint auf jeden Fall möglich zu sein, selbst
mit einer langsamen Festplatte die vom TE gemessenen 45s deutlich zu
unterbieten, was darauf hindeutet, dass da irgendwo noch ein anderes
Problem ist.

von Peter II (Gast)


Lesenswert?

Yalu X. schrieb:
> Wo liegt denn die theoretische Grenze bei USB High Speed?
bei wiki steht was von 60Mbyte/s - im netzt findet man aber nur werte 
zwischen 30 und 35Mbyte/s was ich auch kenne.


> Aber wie auch immer: Es scheint auf jeden Fall möglich zu sein, selbst
> mit einer langsamen Festplatte die vom TE gemessenen 45s deutlich zu
> unterbieten, was darauf hindeutet, dass da irgendwo noch ein anderes
> Problem ist.
er schreibt das nebenbei auch in der Datei geschrieben wird. Lass doch 
mal ein Prozess nebenbei Daten anfügen. Schon spielt die Zugriffszeit 
eine entscheidende Rolle und sind bei den 45s.

von Malte S. (maltest)


Lesenswert?

1
#define _DEFAULT_SOURCE
2
3
#include <errno.h>
4
#include <fcntl.h>
5
#include <stdlib.h>
6
#include <stdio.h>
7
#include <string.h>
8
#include <time.h>
9
#include <unistd.h>
10
11
#include <sys/mman.h>
12
#include <sys/stat.h>
13
14
char pattern[] = {
15
    0x74, 0xe0, 0xb1, 0xa5, 0xf7, 0x41, 0xaf, 0xe8, 0xa9, 0x79
16
};
17
18
void flush_caches() {
19
    sync();
20
21
    int fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
22
    if (fd == -1) {
23
        fprintf(stderr, "Warning: Cannot open /proc/sys/vm/drop_caches: %s\n", strerror(errno));
24
        if (geteuid() != 0) {
25
            fprintf(stderr, "Run this program as root to allow for proper flushing\n");
26
        }
27
        return;
28
    }
29
    if (write(fd, "3\n", 2) == -1) {
30
        fprintf(stderr, "Warning: Writing to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno));
31
    }
32
    close(fd);
33
}
34
35
int main(int argc, char** argv) {                                                                                                                                                                                                                                              
36
    if (argc != 2) {                                                                                                                                                                                                                                                           
37
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);                                                                                                                                                                                                                    
38
        return EXIT_FAILURE;                                                                                                                                                                                                                                                   
39
    }                                                                                                                                                                                                                                                                          
40
                                                                                                                                                                                                                                                                               
41
    int fd = open(argv[1], O_RDWR);                                                                                                                                                                                                                                            
42
    if (fd == -1) {                                                                                                                                                                                                                                                            
43
        fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));                                                                                                                                                                                                  
44
        return EXIT_FAILURE;                                                                                                                                                                                                                                                   
45
    }                                                                                                                                                                                                                                                                          
46
    struct stat st;                                                                                                                                                                                                                                                            
47
    if (fstat(fd, &st) == -1) {                                                                                                                                                                                                                                                
48
        fprintf(stderr, "fstat() failed!?: %s\n", strerror(errno));                                                                                                                                                                                                            
49
        close(fd);                                                                                                                                                                                                                                                             
50
        return EXIT_FAILURE;                                                                                                                                                                                                                                                   
51
    }                                                                                                                                                                                                                                                                          
52
                                                                                                                                                                                                                                                                               
53
    char* data = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);                                                                                                                                                                                           
54
    if (data == MAP_FAILED) {                                                                                                                                                                                                                                                  
55
        fprintf(stderr, "mmap() failed: %s\n", strerror(errno));                                                                                                                                                                                                               
56
        close(fd);                                                                                                                                                                                                                                                             
57
        return EXIT_FAILURE;                                                                                                                                                                                                                                                   
58
    }                                                                                                                                                                                                                                                                          
59
                                                                                                                                                                                                                                                                               
60
    flush_caches();                                                                                                                                                                                                                                                            
61
    time_t t0 = time(NULL);                                                                                                                                                                                                                                                    
62
    for (off_t i = 0; i < st.st_size - sizeof(pattern); i += 0x800) {                                                                                                                                                                                                          
63
        if (memcmp(data + i, pattern, sizeof(pattern)) == 0) {                                                                                                                                                                                                                 
64
            printf("Pattern found at offset %0zx\n", i);                                                                                                                                                                                                                       
65
        }                                                                                                                                                                                                                                                                      
66
    }                                                                                                                                                                                                                                                                          
67
    printf("mmap: %lu seconds\n", time(NULL) - t0);                                                                                                                                                                                                                            
68
                                                                                                                                                                                                                                                                               
69
    munmap(data, st.st_size);                                                                                                                                                                                                                                                  
70
                                                                                                                                                                                                                                                                               
71
    char buf[sizeof(pattern)];                                                                                                                                                                                                                                                 
72
    flush_caches();                                                                                                                                                                                                                                                            
73
    t0 = time(NULL);
74
    for (off_t i = 0; i < st.st_size - sizeof(pattern); i += 0x800) {
75
        if (lseek(fd, i, SEEK_SET) == (off_t)-1) {
76
            fprintf(stderr, "lseek() failed: %s\n", strerror(errno));
77
            close(fd);
78
            return EXIT_FAILURE;
79
        }
80
        ssize_t nread = read(fd, buf, sizeof(buf));
81
        if (nread == -1) {
82
            fprintf(stderr, "read() failed: %s\n", strerror(errno));
83
            close(fd);
84
        }
85
        else if (nread < sizeof(buf)) {
86
            fprintf(stderr, "Short read at %zx, ignoring this block!\n", i);
87
        }
88
89
        if (memcmp(buf, pattern, sizeof(pattern)) == 0) {
90
            printf("Pattern found at offset %0zx\n", i);
91
        }
92
    }
93
    printf("read: %lu seconds\n", time(NULL) - t0);
94
95
    close(fd);
96
}

Pattern found at offset 7ffff800
mmap: 19 seconds
Pattern found at offset 7ffff800
read: 18 seconds

Die getestete Datei ist ein 2 GiB großer Ausschnitt aus /dev/urandom, 
das gesuchte Muster ist halt das, was an der letzten Vergleichsstelle in 
der Datei zu finden war.
Test lief mit interner HD. Das Leeren der Caches benötigt root-Rechte, 
es macht allerdings mit oder ohne keinen nennenswerten Unterschied.

EDIT:
Die mmap()-Variante ist einfach kürzer. Bei 32-Bit wird das so 
allerdings nicht klappen, da muss dann auch mehrfach gemappt werden. 
Außerdem hat mmap so seine Überaschungen, wenn z.B. ein anderer Prozess 
die Datei inzwischen verkleinert hat (SIGBUS und tschüss).

: Bearbeitet durch User
von flolix (Gast)


Lesenswert?

@maltest:
Du stoppst die Zeit (t0 = time(NULL);) erst NACH dem mmap Aufruf!

gruß flolix

von Malte S. (maltest)


Lesenswert?

flolix schrieb:
> Du stoppst die Zeit (t0 = time(NULL);) erst NACH dem mmap Aufruf!

Recht du hast. Gerade mal noch einen Satz gettimeofday()s um mmap() 
gebaut...mmap() braucht zwischen 5 und 6 µs.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter II schrieb:
> Yalu X. schrieb:
>> Wo liegt denn die theoretische Grenze bei USB High Speed?
> bei wiki steht was von 60Mbyte/s - im netzt findet man aber nur werte
> zwischen 30 und 35Mbyte/s was ich auch kenne.

Die 60MB/s sind die Bruttodatenrate (480Mbit/s). Im Vergleich zu
Ethernet u.ä. scheint das USB-Protokoll aber einen sehr großen Overhead
zu haben.

> er schreibt das nebenbei auch in der Datei geschrieben wird. Lass doch
> mal ein Prozess nebenbei Daten anfügen. Schon spielt die Zugriffszeit
> eine entscheidende Rolle und sind bei den 45s.

Ich habe ihn so verstanden, dass er erst nach der Suche beginnt, neue
Daten in die Datei zu schreiben.

von Peter II (Gast)


Lesenswert?

Yalu X. schrieb:
> Ich habe ihn so verstanden, dass er erst nach der Suche beginnt, neue
> Daten in die Datei zu schreiben.

es scheint wohl ein 2.Prozess zu geben, der darin rumschreibt.

> FILE_SHARE_WRITE | FILE_SHARE_READ,

von Yalu X. (yalu) (Moderator)


Lesenswert?

Peter II schrieb:
> Yalu X. schrieb:
>> Ich habe ihn so verstanden, dass er erst nach der Suche beginnt, neue
>> Daten in die Datei zu schreiben.
>
> es scheint wohl ein 2.Prozess zu geben, der darin rumschreibt.
>
>> FILE_SHARE_WRITE | FILE_SHARE_READ,

Ja, wenn das tatsächlich so ist, braucht man nicht mehr weiter nach der
Bremse zu suchen.

Der TE schreibt allerdings auch:

TK schrieb:
> Mit dem Code dauert es trotzdem noch ca. 45s auf meinem System, bis
> eine Sequenz, die am Ende der Datei vorkommt, gefunden wird. Info: Die
> Datei wird an dieser Stelle weiter bearbeitet. Daher auch der R/W
> Zugriff auf die Datei.

Da die Datei "an dieser Stelle weiter bearbeitet" wird, schließe ich
daraus, dass die Suche abgeschlossen ist, bevor der erste Schreibzugriff
erfolgt.

TK schrieb:
> Es läuft sonst nichts mehr nebenbei.

Vielleicht ist auch einfach nur seine Festplatte stark fragmentiert. Bei
meinen Tests war die externe Festplatte noch relativ leer, weswegen ich
davon ausgehe, dass die Gigabyte-Datei weitgehend zusammenhängend
abgelegt wurde.

: Bearbeitet durch Moderator
von TK (Gast)


Lesenswert?

Hallo zusammen,

ich komme kaum mit dem Mitlesen hinterher!
Nochmal zur Info:
Ich suche zuerst nach dem Muster, wenn ich es gefunden habe, schreibe 
ich hinter diesem Muster etwas in die Datei. Mir geht es hauptsächlich 
darum die Zeit für die Suche zu reduzieren! Momentan habe ich mich etwas 
mit dem CreateFileMapping() und dem MapViewOfFile() beschäftigt. 
Allerdings klappt das noch nicht so, wie es soll (AccessViolation).
Im übrigen habe ich die Zeit für eine 1GB-Datei OHNE Vorkommen der 
Sequenz nochmals mit 47s gemessen (bei dem Code wie Anfangs angegeben).
Gut - die Festplatte kann durchaus stark fragmentiert - obwohl nur 
halbvoll - sein, damit möchte ich mich jetzt nicht beschäftigen.

Gruß
TK

von Peter II (Gast)


Lesenswert?

TK schrieb:
> Im übrigen habe ich die Zeit für eine 1GB-Datei OHNE Vorkommen der
> Sequenz nochmals mit 47s gemessen (bei dem Code wie Anfangs angegeben).
> Gut - die Festplatte kann durchaus stark fragmentiert - obwohl nur
> halbvoll - sein, damit möchte ich mich jetzt nicht beschäftigen.

solltest du aber.

wie lange dauert ein

copy Datei.ext NUL

von c-hater (Gast)


Lesenswert?

TK schrieb:

> Problem: Aus einer sehr großen Datei (ca.
> 700MB..2GB)

Das ist nicht "sehr groß", das ist höchstens groß.

> muss eine 10Byte Sequenz gesucht werden. Diese kann
> innerhalb der Datei entweder 0x,1x oder 2x auftreten. Die Sequenz kann
> nur an Vielfachen von 0x800 Adr auftreten

Hilft garnix. Du musst die komplette Datei lesen. Und zwar sequentiell, 
ohne nutzlose und sinnlos zeitfressende Seeks. Erst wenn das mögliche 
Vorkommen der gesuchten Sequenz auf Vielfache von 0x2000 beschränkt 
wäre, könnten Seeks vielleicht einen Vorteil bringen. Wahrscheinlich 
liegt die Grenze aber noch viel höher, vielleicht so ca. bei 0x10000.

>       if ((puffer[0] == 0) &&
>           (puffer[1] == 0x0815) &&
>           (puffer[2] == 0x4711) &&
>           (puffer[3] == 0xDEAD) &&
>           (puffer[4] == 0xFEED))

Das ist Mist. Auf modernen Maschinen kann man locker 128Bit am Stück 
vergleichen. Und 16Bit-Zugriffe sind sogar schon seit Jahrzehnten 
langsamer als nötig.

Allerdings: dieser Mist spielt wohl im Vergleich zum IO-Kram sowieso 
keine nennenswerte Rolle, kann man also in diesem Fall wohl einfach so 
lassen, wie es ist.

von oszi40 (Gast)


Lesenswert?

Wenn einer weiß, wie man eine solch große 2GB Ramdisk erzeugt, wäre das 
auch eine Idee zur Beschleunigung. Allerdings ist D-RAM vergesslich, 
sobald Strom weg ist!!!

von Peter II (Gast)


Lesenswert?

oszi40 schrieb:
> Wenn einer weiß, wie man eine solch große 2GB Ramdisk erzeugt, wäre das
> auch eine Idee zur Beschleunigung. Allerdings ist D-RAM vergesslich,
> sobald Strom weg ist!!!

auf so einen Computer?
> WIN-XP32 (AMD 3GHz DualCore).

Da ist eine 32GB SSD vermutlich einfacher.

von Malte S. (maltest)


Lesenswert?

oszi40 schrieb:
> Wenn einer weiß, wie man eine solch große 2GB Ramdisk erzeugt, wäre das
> auch eine Idee zur Beschleunigung. Allerdings ist D-RAM vergesslich,
> sobald Strom weg ist!!!

mount -t tmpfs -o size=2G none /some/where

Aber...

Peter II schrieb:
> auf so einen Computer?
>> WIN-XP32 (AMD 3GHz DualCore).
>
> Da ist eine 32GB SSD vermutlich einfacher.

Ist natürlich die Frage, wiveiel RAM der hat. Bei mehr als 3 GiB wäre 
ein Wechsel des OS ohnehin angebracht ;-)

von oszi40 (Gast)


Lesenswert?

> SSD vermutlich einfacher.

Stimmt und ist nicht so vergesslich. Fragt sich nur, ob es unbedingt 
eine solch kleine 32GB sein muß, daß er sie bald gegen eine größere 
tauschen wird. Eine schnelle SSD für das System beschleunigt alle 
Prozesse, eine kleine NUR für diese ein Datei wäre rausgeschmissenes 
Geld. Zur Orientierung :https://www.alternate.de/SSD

von Amateur (Gast)


Lesenswert?

Etwas zur Suche auf unterster Ebene:

Wird die Sequenz 123456 gesucht und das erste Zeichen [0] ist 2, so 
lohnt es nicht, noch die Zeichen Nummer [1]...[5] zu überprüfen.

Es hilft also wenn Du erst mal nur das erste Zeichen überprüfst und nur 
in positivem Falle Dich mit den folgenden beschäftigst.

von Peter II (Gast)


Lesenswert?

Amateur schrieb:
> Wird die Sequenz 123456 gesucht und das erste Zeichen [0] ist 2, so
> lohnt es nicht, noch die Zeichen Nummer [1]...[5] zu überprüfen.
>
> Es hilft also wenn Du erst mal nur das erste Zeichen überprüfst und nur
> in positivem Falle Dich mit den folgenden beschäftigst.

das macht der Compiler schon selber. Im solche Kleinigkeiten muss man 
sich nicht kümmern.

von guest0815 (Gast)


Lesenswert?

hi,

also ich verstehe nix von borlandpascal, aber ist das eine
lineare suche ???

wenn ja würde ich mal über einen sinnvollen suchalgo nachdenken
... datei in der mitte teilen und gleichzeitig nach vorn und hinten
suchen ... oder wenn das pattern nur im letzen drittel vorkommen kann,
brauchst du ja auch nur das letzte drittel durchsuchen ... sowas
in der art halt ... stichworte für google würde ich pattern matching
oder sowas in der art versuchen ...

von Malte S. (maltest)


Lesenswert?

[ ] Du hast mehr als den Betreff dieses Threads gelesen.

von Peter II (Gast)


Lesenswert?

guest0815 schrieb:
> wenn ja würde ich mal über einen sinnvollen suchalgo nachdenken
> ... datei in der mitte teilen und gleichzeitig nach vorn und hinten
> suchen ... oder wenn das pattern nur im letzen drittel vorkommen kann,
> brauchst du ja auch nur das letzte drittel durchsuchen ... sowas
> in der art halt ... stichworte für google würde ich pattern matching
> oder sowas in der art versuchen ...

und wenn er nicht weiß wo es steht (was zu vermuten ist, sonst würde er 
nicht suchen)?

Und gleichzeitig auf einer normales Festplatte zu suchen ist das 
langsamste was man machen kann, dann muss der Lesekopf ständig den 
Sektor ändern.

von Amateur (Gast)


Lesenswert?

>das macht der Compiler schon selber. Im solche Kleinigkeiten muss man
>sich nicht kümmern.

Per default?

von Peter II (Gast)


Lesenswert?


von c.m. (Gast)


Lesenswert?

Peter II schrieb:
> Amateur schrieb:
>> Per default?
>
> ja
>
> https://de.wikipedia.org/wiki/Kurzschlussauswertung

hm. ich weiß noch aus einer implementierung des lzw algorithmus zu 
meiner schulzeit (~vor 25 jahren), das ein blankes "repz cmpsb" 
langsamer war als die prüfung des ersten bytes auf übereinstimmung und 
anschließender stringsuche.

aber da ging es auch nicht um feste adressen, sondern darum das gesamte 
file byteoffset-weise nach strings zu durchsuchen.

von TK (Gast)


Lesenswert?

So, ich habe jetzt mal CreateFileMapping() / MapViewOfFile() 
implementiert und kann jetzt die Suche in einer 1GB Datei OHNE Vorkommen 
der Sequenz von ursprünglich 47s auf jetzt 16s reduzieren. Das ist doch 
mal ein Wort. Danke an Klaus Wachtler und die anderen, die den Hinweis 
auf diese Funktionen gegeben haben.

Ich denke, für mich ist hiermit die Frage (und damit der Thread) 
beantwortet.

Gruß
TK

von bluppdidupp (Gast)


Lesenswert?

FILE_FLAG_SEQUENTIAL_SCAN bei CreateFile als Hint mit angeben, könnte 
ggf. auch nicht verkehrt sein:
"Specifying the FILE_FLAG_SEQUENTIAL_SCAN flag can increase performance 
for applications that read large files using sequential access. 
Performance gains can be even more noticeable for applications that read 
large files mostly sequentially, but occasionally skip forward over 
small ranges of bytes."

von Roland P. (pram)


Lesenswert?

Hallo,

Was ist das für eine Datei?
Suchst du darin öfters?
Durch welche Prozesse wird die Datei verändert?

Auf was ich hinaus will, kann man die Datei nicht 1x lesen und sich 
jeden 0x0800-sten Wert in eine extra Datei als Index schreiben?

Für mich hört sich das so an, als suchst du nach den Marker eines 
Datenloggers o.ä.
Evtl beschreibst du dein Problem etwas über den Tellerrand hinaus, so 
dass hier vielleicht noch der ein oder andere interessante Impuls kommt

Gruß
Roland

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.