2015-03-10 5 views
7

Ich verwende Windows   7 - 64 Bit, mit der neuesten XAMPP-Version, die eine 32-Bit-PHP-Version hat.Optimiert PHP stillschweigend aufeinanderfolgende fseek-Befehle in einem fseek-Befehl?

In einem Test http://php.net/manual/en/function.fseek.php#112647 für eine sehr große Datei (größer als PHP_MAX_INT 2147483647) Ich bin jetzt ziemlich sicher, dass die nacheinandere folgende fseeks vor auf dem Dateizeiger ausgeführt aufsummiert werden.

Ich habe zwei Fragen:

  1. Kann ich diese zusammenfassend mit angemessenen Mitteln brechen (oder nur mit der in der Verbindung oben genannte Problemumgehung)?

  2. Ist diese Aggregation in PHP passiert (wie ich vermute, obwohl ich nicht weiß, wo in PHP) oder in Windows   7?

Answering mir: Der Versuch, zwei Lösungen mit mehreren sucht nicht auf meinem System nicht funktioniert. Stattdessen setzen sie den Filepointer unter PHP_MAX_INT auf verschiedene Positionen . (32-Bit-PHP kann nur versuchen, bis zu PHP_MAX_INT + 8192. Lesen von dort noch möglich ist, aber ich weiß nicht, wie weit.)

Deshalb ist die Frage nach meinem speziellen Fall veraltet ist, wie 32 -Bit PHP kann nur bis zu PHP_MAX_INT + 8192, was auch immer Sie tun. I lassen Sie die Frage, weil zwei Leute wählten es, und könnte in einer allgemeinen Antwort interessiert sein.

Ich legte hier einen Bug-Report:
https://bugs.php.net/bug.php?id=69213
Ergebnis: Mit einer PHP-Version 64-bit es funktionieren kann, aber ich habe es nicht ausprobiert.

+0

Hinweis: Ich habe SplFileObject nicht wie von jemand anderem vorgeschlagen getestet, da ich dem PHP-Handbuch vertraue, dass SplFileObject nur eine Ebene über den üblichen Suchbefehlen usw. sein sollte. Und ich bin bereits für diese spezielle Aufgabe nach Perl migriert. (Was selbst der Typ auf der PHP-Seite versteht.) Ich werde keinen 64-Bit-PHP-Build bereitstellen, solange es nicht Mainstream ist. Und ich wandle nicht komplett auf Perl um, nur um ein paar sehr große Dateien zu lesen und zu schreiben. (Und es ist sehr schwierig für mich, einen konzeptuellen Vorteil in SplFileObject zu sehen. Obwohl die Betreuer als "enthusiastisch" bezeichnet werden.) – John

Antwort

1

Es tut es nicht. Es tut tatsächlich etwas sogar dümmer. Hier ist ein Ausschnitt aus dem PHP-Quellcode:

 switch(whence) { 
      case SEEK_CUR: 
       offset = stream->position + offset; 
       whence = SEEK_SET; 
       break; 
     } 

Dies ist in den Eingeweiden der Implementierung für PHP fseek. Was hier passiert ist: Wenn Sie PHP anweisen, von der aktuellen Position aus zu suchen, wird dies in eine "äquivalente" Suche vom Anfang der Datei übersetzt. Dies funktioniert nur, wenn diese Offset-Berechnung nicht überläuft; Wenn das der Fall ist, offset ist eine vorzeichenbehaftete Ganzzahl, das ist undefiniertes Verhalten.

Und, okay, das ist da, weil PHP Streams intern puffert, also müssen sie etwas tun. Aber das muss nicht so sein.

Sie sind wahrscheinlich am besten dran, wenn Sie versuchen, Ihre Arbeit in einer Sprache zu erledigen, die tatsächlich das tut, was Sie sagen.

+0

Das sollte eigentlich kein Problem sein, da Lese- und Schreibpunktänderungen auf Offsets reduziert werden aktuelle Positionen und das Diskettensystem wird nicht unnötige Suchen durchführen; es wird nur den Kopf suchen, wo es lesen und schreiben muss. In diesem Sinne verändert das Suchen ohne Lesen oder Schreiben nur vorzeichenbehaftete Ganzzahlen. –

+1

Nehmen Sie Ihre kernfarbene Brille ab. Diese Semantik bedeutet, dass kein PHP-Programm mehr als "ZEND_LONG_MAX" -Bytes in eine Datei hineinsuchen kann, selbst wenn das Dateisystem und das Betriebssystem dazu in der Lage sind. Weil die Implementierung von SEEK_CUR von PHP ein undefiniertes Verhalten im formellen C-Standard-Sinn enthält. PHP wird nicht tun, was der Programmierer in diesem Fall gesagt hat, und das sollte * inakzeptabel * sein. – Alex

+0

@Alex: Das passt zu dem, was ich herausgefunden habe, indem ich verschiedene Zielsuchwerte ausprobiere. (Siehe letzten Eintrag im PHP-Bug-Bericht, den ich verlinkt habe.) Also akzeptiere ich diese Antwort. Wenn der Bug (oder der alte Code) vorhanden ist, hat dies für den Endbenutzer keine Auswirkungen, wenn auf anderen Ebenen andere Optimierungen oder Fehler vorhanden sind, da diese anderen Ebenen niemals die angenommenen Werte erhalten. Ich nehme an. Ich bin nicht dabei. Wie geschrieben, benutze ich Perl für die einzelne große Dateiaufgabe :) Vielleicht könnten Sie einen Fehlerbericht mit den Codezeilen schreiben, die Sie gefunden haben, und vielleicht wird es verbessert. :) – John

0

Wenn eine Aggregation stattfinden würde, müsste dies wahrscheinlich als Opcode-Optimierung erfolgen oder müsste auf niedrigem Niveau über einen Puffer erfolgen.

Ich kann auf dem niedrigen Niveau antworten. fseek() in PHP wird mit PHP-Streams implementiert. Es ist in ext/standard/file.h deklariert und in .c definiert. Seine Implementierung ruft php_stream_seek() auf, das zu _php_stream_seek() in streams.c aufruft.Die Low-Level-Implementierung von diesem wird durch die Plain-Streams-Wrapper behandelt, in welchem ​​Fall Aufrufe durch entweder zu zend_seek oder zend_fseek, die wiederum nur zu 32 oder 64-Bit-Suchanfragen durchsuchten.

Also ... wenn eine Aggregation passiert, scheint es in den Opcode-Optimierungen oder noch weiter unten in der OS oder Hardware zu sein. Festplatten implementieren Out-of-Order-Abrufen, um die Suchabstände zu reduzieren, und Dateisystempuffersysteme können Suchvorgänge reduzieren, die keine Nebenwirkungen haben. Wenn Sie sich Gedanken über die Lesezeit der Festplatte machen, wird diese zuerst automatisch gehandhabt. Wenn Sie daran interessiert sind, vielleicht das Gedächtnis zu überlisten (indem Sie unnötigerweise große Entfernungen im Puffer suchen), könnten Sie einen anderen Ansatz in Erwägung ziehen. Siehe: http://www.cs.iit.edu/~cs561/cs450/disksched/disksched.html für weitere Informationen darüber, wie Festplatten Zeitverschwendung vermeiden.

Ich hoffe, das hilft.

Verwandte Themen