Ticket UUID: 2983ca30985bf194f5db6a028c938301ea31d158
Title: Implémenter le stockage des fichiers
Status: Fixed Type: Feature_Request
Severity: Important Priority: Immediate
Subsystem: Resolution: Fixed
Last Modified: 2015-04-17 21:27:15
Version Found In:
Target version:
User Comments:
bohwaz added on 2014-04-20 23:03:36:
  *  Possibilité de joindre des documents à un membre, une opération comptable, etc.
  *  Les documents sont stockés dans la base de données, une copie locale (cache statique) est stockée en fichier
  *  Pour la consultation des documents un lien symbolique est créé temporairement (genre 6 heures) vers le cache statique, le temps de télécharger le document mais pour pas qu'il reste accessible tout le temps

bohwaz added on 2014-04-20 23:40:30:
Voici des tests de rapidité sur un fichier de 64Mo (requête curl récupérant le fichier sur le serveur HTTP intégré à PHP) :

* Lire le fichier directement depuis le système de fichier (ligne par ligne) : 290ms
* Lire le fichier directement depuis SQLite3 avec $db->openBlob() ligne par ligne : 350ms (17% plus lent)
* Créer un lien symbolique depuis le fichier physique et rediriger vers le lien : 65ms (78% plus rapide)
* Lire le fichier depuis SQLite3 et l'écrire dans un fichier de cache ligne par ligne : 1150ms

La méthode SQLite3 utilise 3Mo de mémoire de plus que les deux autres (forcément faut charger la lib SQLite3, mais normalement elle est déjà en mémoire avec les autres requêtes). Par contre aucune différence d'occupation de mémoire entre juste lire le fichier depuis la DB et aussi l'écrire dans un fichier de cache.

Dans ce cas si on considère deux options :
1. stocker le fichier dans la DB et toujours le lire depuis là, sans cache, directement en PHP.
2. stocker le fichier dans la DB et le stocker en cache à la première consultation puis le servir via un symlink potentiellement recréé à chaque utilisation.

La solution 2 est 4 fois plus lente à la première consultation, mais 5 fois plus rapide ensuite.

La meilleure solution me semble donc être l'option 2 : certes la première consultation est lente mais ensuite le gain est très appréciable niveau réactivité entre attendre moins d'un dixième de seconde et devoir attendre un tiers de seconde : le délai est clairement ressenti dans l'expérience utilisateur.

bohwaz added on 2014-04-21 14:18:52:
Essai avec readfile: 90ms

bohwaz added on 2015-01-23 01:28:18:
Conclusion des benchmarks :
- pour enregistrer le blob dans un fichier de cache : stream_copy_to_stream est plus rapide qu'itérer sur les lignes du fichier et les écrire une à une
- lire le blob ligne par ligne depuis SQLite (avec fread) est plus rapide de 30% que l'enregistrer en cache
- pour lire le fichier de cache, X-SendFile est plus rapide (de 4 fois) que readfile qui est plus rapide (de 10 fois) que lire et afficher le fichier ligne par ligne avec fread

Utiliser X-SendFile est ~20% plus lent que servir le fichier directement avec Apache. Utiliser readfile est 57% plus lent que servir le fichier avec Apache. Mais ça reste de l'ordre de ~80ms pour un fichier de 57Mo.

Donc : pour envoyer le fichier au client il faut utiliser x-sendfile ou readfile. Pour stocker le fichier en cache il faut utiliser stream_copy_to_stream depuis openBlob.