6 Stimmen

Ist es möglich, kurze Ints (16-Bit) in PHP zu verwenden?

Hintergrund: Ich habe ein großes 2D-Array mit ganzen Zahlen, das ich in PHP für jede Apache-Anfrage in den Speicher laden muss. Ich möchte, dass es weniger Speicherplatz benötigt.

PHP speichert Ints in PHP_INT_SIZE Bytes, was auf den meisten Systemen 32 Bit entspricht. Alle Ganzzahlen sind kleiner als 2^16, d.h. sie könnten ein kurzes Int (z.B. in C). Liege ich richtig in der Annahme, dass die Speicherung von ints als kurz würde die Hälfte des RAM nehmen?

Im Idealfall würde ich das gerne tun können:

$s = (short) 1234; // takes up 2 bytes instead of 4

Mehr Informationen:

  • Das Array beansprucht etwa 100 MB RAM und wird durch Einfügen einer 30 MB var_export() abladen
  • Das Array wird in einen Cron-Prozess geschrieben. Nur das Lesen muss speichereffizient (und schnell) sein
  • Die einzigen Operationen, die ich mit den ganzen Zahlen durchführen muss, sind der Vergleich aller Zahlen (<, >, ===) und das Lesen einiger weniger Zahlen (ähnlich wie bei der Floyd-Warshall-Algorithmus )
  • Das Lesen der einzelnen Werte aus einer DB ist viel zu langsam, da pro Anfrage mehrere hundert Millionen Werte gelesen werden.

Einige verrückte Ideen:

  • Verwenden Sie pack() / auspacken() aber das würde die Werte immer noch als 32-Bit-Ints speichern, wenn sie ausgepackt werden
  • Speichern Sie die Werte als Pixel in einem Bild und verwenden Sie PHPs GD-Bibliothek um sie zu lesen (wäre das zu langsam)
  • Verwenden Sie shmop_read() und die Apache-Prozesse sollen sich das Array
  • Memcached könnte funktionieren, aber ich habe keine Erfahrung damit und ich vermute, es wäre um ein Vielfaches langsamer als ein natives PHP-Array
  • C++ lernen und eine PHP-Erweiterung schreiben
  • PHP neu kompilieren (oder HipHop ?) 2 Bytes für Ints zu verwenden
  • Verwenden Sie Igbinär (nützlich, hat aber das gleiche Problem wie pack())

4voto

BarsMonster Punkte 6385

Den letzten Ansatz würde ich nicht empfehlen :-)

Für die schnelle Lösung, würde ich 2 Ihre Integer in 1 PHP-Integer mit diesem packen:

$big = $int1 + ($int2<<16);

And uppack as:

$int1 = $big & 65535;
$int2 = ($big>>16) & 65535;

Außerdem gibt es ein dickes Lob für die Verwendung von Shared Memory. Dies wird Ihre APP viel schneller machen.

2voto

Artefacto Punkte 93200

Das ist keine Aufgabe, für die PHP entwickelt wurde.

Ich empfehle Ihnen, eine Anwendung zu schreiben, die die Daten im Speicher hat und die Berechnungen damit durchführt, und dann eine Schnittstelle in PHP einzurichten, um die Ergebnisse zu erhalten.

Die Integer-Größe von PHP ist auf den meisten 64-Bit Unix-ähnlichen Plattformen tatsächlich 64-Bit.

Der gemeinsam genutzte Speicher ist keine gute Option, da Sie die Daten immer noch in den Speicherbereich von PHP kopieren müssen.

Eine Erweiterung zu schreiben, die alles im Speicher hält und direkt darauf zugreift, ist zwar möglich, aber nicht sehr praktisch, da man ohnehin Shared Memory (oder einen anderen IPC-Mechanismus) verwenden müsste, da man normalerweise mehrere PHP-Prozesse laufen lässt.

1voto

user187291 Punkte 52315

Ich würde das Array in einem binär gepackten Format generieren und speichern und die Zahlen nur extrahieren, wenn Sie sie brauchen.

function elem($n) {
    global $buf;
    return (ord($buf[$n << 1]) << 8) | ord($buf[$n << 1 | 1]);
}

$buf = file_get_contents(binary file generated by cron);
if(elem(2) > elem(10)).....

können Sie es raffinierter machen, indem Sie eine Klasse schreiben, die ArrayAccess implementiert, so dass Sie einfach myPackedArray[x] anstelle von elem(x) im restlichen Code verwenden können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X