Oplossing voor Php memory size exhausted t.b.v. een Stream

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • sparkle
  • Registratie: November 2004
  • Laatst online: 12-08-2024
Voor een website waar ik aan werk moet ik een video beveiligd kunnen afspelen, zodat de oorspronkelijke URL niet kan worden achterhaald.

Dit beveiligingsmechanisme werkt en wordt gedaan op basis van een cookie check.

De HTML5 video player die de video afspeelt vraagt de video op in chunks via de Content-Range request header die door mijn back-end gehonoreerd moet worden omdat er anders "Content length mismatch" errors ontstaan.

Dit werkt ook. Enkel het probleem is dat het aanbieden van de data stream erg veel memory verbruikt. Daarom krijg ik de volgende fout:
"Allowed memory size of 262144 bytes exhausted (tried to allocate 576 bytes)"
De stream bied ik aan via de onderstaande code die in een callback wordt aangeroepen. Werkt voor de rest prima. Waar ik naar opzoek ben is een methode die niet veel memory opslokt, maar de data "als het ware" direct doorstuurt naar de client, zodat ik niet last krijg van deze fout.

PHP:
1
2
3
4
5
6
$stream = GuzzleHttp\Stream\Stream::factory(fopen($path, 'r'));
$stream->seek($offset);
while (!$stream->eof()) {
echo $stream->read($length);
}
$stream->close();


Wat ik al heb geprobeerd is de chunks een max length te geven, waardoor het gereserveerde memory nooit hoger oploopt dan het door mezelf gedefinieerde aantal bytes. Enkel kan Chrome hiermee overweg en Firefox en Safari helaas niet.

Iemand advies betreffende deze kwestie?

Beste antwoord (via sparkle op 13-02-2016 14:15)


  • DJMaze
  • Registratie: Juni 2002
  • Niet online
sparkle schreef op dinsdag 09 februari 2016 @ 11:54:
Iemand advies betreffende deze kwestie?
Je hele probleem is GuzzleHttp.
Deze voldoet aan de PSR-7 en daar zit een enorme fout in waardoor eigenlijk het hele bestand in het geheugen moet.
https://evertpot.com/psr-7-issues

Gebruik gewoon:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if ($i = ob_get_level()) {
    # Clear buffering:
    while ($i-- && ob_end_clean());
    if (!ob_get_level()) header('Content-Encoding: ');
}
ob_implicit_flush();

$fp = fopen($path, 'rb');
fseek($fp, $offset);
while ($length && !feof($fp)) {
    $chunk = min(8192, $length);
    echo fread($fp, $chunk);
    $length -= $chunk;
}
fclose($fp);


edit:
Ik ben er op gewezen dat ik copyrighted code heb gepost.
Dat klopt, ik ben zelf de eigenaar van die code :)
https://bitbucket.org/djm...default#bootstrap.php-271
Stond voorheen op googlecode totdat die de deur sloot
http://poodle-wcms.google...hare/poodle/bootstrap.php

[ Voor 56% gewijzigd door DJMaze op 16-02-2016 16:18 . Reden: Flush buffering toegevoegd ]

Maak je niet druk, dat doet de compressor maar

Alle reacties


Acties:
  • 0 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 16:03
Al eens een flush geprobeerd na elke echo:
http://php.net/manual/en/function.flush.php

Dan hoeft je binnen PHP je chunks niet te bufferen, maar kan je de uitvoer gelijk doorsturen naar je client.

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • +1 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Ik vind 256 kB juist niet 'erg veel'. Waarom zet je de memory_limit niet wat hoger?

Acties:
  • 0 Henk 'm!

  • tommieonos
  • Registratie: Oktober 2011
  • Laatst online: 12:11
CurlyMo schreef op dinsdag 09 februari 2016 @ 12:04:
Al eens een flush geprobeerd na elke echo:
http://php.net/manual/en/function.flush.php

Dan hoeft je binnen PHP je chunks niet te bufferen, maar kan je de uitvoer gelijk doorsturen naar je client.
Dit. Wat er nu gebeurt is dat je de stream tot het einde leest om hem dan pas op te sturen naar de browser.
Php buffert standaard alle output tot het klaar is met uitvoeren.

Acties:
  • 0 Henk 'm!

  • naam
  • Registratie: Oktober 2007
  • Laatst online: 15:56
GlowMouse schreef op dinsdag 09 februari 2016 @ 12:10:
Ik vind 256 kB juist niet 'erg veel'. Waarom zet je de memory_limit niet wat hoger?
Dit is de oplossing. Ik vermoed dat die 256kB niet eens genoeg is om uberhaupt guzzle te kunnen laden, laat staan deze iets te laten lezen.

Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
sparkle schreef op dinsdag 09 februari 2016 @ 11:54:
Iemand advies betreffende deze kwestie?
Je hele probleem is GuzzleHttp.
Deze voldoet aan de PSR-7 en daar zit een enorme fout in waardoor eigenlijk het hele bestand in het geheugen moet.
https://evertpot.com/psr-7-issues

Gebruik gewoon:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if ($i = ob_get_level()) {
    # Clear buffering:
    while ($i-- && ob_end_clean());
    if (!ob_get_level()) header('Content-Encoding: ');
}
ob_implicit_flush();

$fp = fopen($path, 'rb');
fseek($fp, $offset);
while ($length && !feof($fp)) {
    $chunk = min(8192, $length);
    echo fread($fp, $chunk);
    $length -= $chunk;
}
fclose($fp);


edit:
Ik ben er op gewezen dat ik copyrighted code heb gepost.
Dat klopt, ik ben zelf de eigenaar van die code :)
https://bitbucket.org/djm...default#bootstrap.php-271
Stond voorheen op googlecode totdat die de deur sloot
http://poodle-wcms.google...hare/poodle/bootstrap.php

[ Voor 56% gewijzigd door DJMaze op 16-02-2016 16:18 . Reden: Flush buffering toegevoegd ]

Maak je niet druk, dat doet de compressor maar


Acties:
  • 0 Henk 'm!

  • sparkle
  • Registratie: November 2004
  • Laatst online: 12-08-2024
Sorry voor de late reactie.
"Allowed memory size of 262144 bytes exhausted (tried to allocate 576 bytes)"
Ik vermoed dat ik deze fout krijg omdat het geheugen al vol zit en de extra 576 bytes niet gereserveerd kan worden.

Het video bestand kon enkel worden afgespeeld als ik mijn memory_limit op oneindig (-1) zet of op de grootte van het video bestand (in dit geval zo een 400mb). Uiteraard zie ik dit niet als oplossing omdat mijn server dan gegarandeerd vol loopt bij bezoekers die simultaan de video afspelen.

@DJMaze:
Hartstikke dank voor de toelichting en de oplossing. Het probleem is nu verholpen!

Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
sparkle schreef op vrijdag 12 februari 2016 @ 16:17:
@DJMaze:
Hartstikke dank voor de toelichting en de oplossing. Het probleem is nu verholpen!
Graag gedaan. Is je probleem nu verholpen door het antwoord van CurlyMo omdat je dat hebt gemarkeerd?
Zo ja, dan was deze handiger: http://php.net/ob_implicit_flush

Maak je niet druk, dat doet de compressor maar


Acties:
  • +1 Henk 'm!

  • CurlyMo
  • Registratie: Februari 2011
  • Laatst online: 16:03
Of je nu ob_implicit_flush gebruikt of flush of wat voor een methode. Het gaat erom dat je begrijpt wat het achterliggende probleem is (bufferen waar je dat niet zou moeten doen) en hoe je dit zou kunnen oplossen :)

Sinds de 2 dagen regel reageer ik hier niet meer


Acties:
  • 0 Henk 'm!

  • sparkle
  • Registratie: November 2004
  • Laatst online: 12-08-2024
DJMaze schreef op vrijdag 12 februari 2016 @ 22:23:
[...]

Graag gedaan. Is je probleem nu verholpen door het antwoord van CurlyMo omdat je dat hebt gemarkeerd?
Zo ja, dan was deze handiger: http://php.net/ob_implicit_flush
Goed dat je me hierop wees. Want ik had verkeerd geklikt.

Jouw oplossing was toereikend. Had al geëxperimenteerd met flush en ob_implicit_flush o.b.v. Guzzle, maar dit had geen succes.

Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
sparkle schreef op zaterdag 13 februari 2016 @ 14:17:
Jouw oplossing was toereikend. Had al geëxperimenteerd met flush en ob_implicit_flush o.b.v. Guzzle, maar dit had geen succes.
Aha, jij ook bedankt!
Ik weet dat er een probleem is met PSR-7, maar ik wist niet 100% zeker of Guzzle had afgeweken van de PSR om het probleem te tackelen.
Nu weet ik ook zeker dat ik alles met PSR-7 gewoon moet vermijden :)

[ Voor 3% gewijzigd door DJMaze op 13-02-2016 22:37 ]

Maak je niet druk, dat doet de compressor maar

Pagina: 1