10
votes

Filtream très lent sur l'application-froide

Une question très similaire a également été posée ici sur SO au cas où Vous êtes intéressé, mais comme nous le verrons, la réponse acceptée de cette question n'est pas toujours la case (et ce n'est jamais le cas pour mon utilisation de la demande).

Le code de détermination des performances est constitué d'un constructeur de filtream (pour ouvrir un fichier) et un hachage SHA1 (la mise en œuvre du framework .NET). Le code est à la fois une version C # de ce qui a été posé dans la question que j'ai liée au-dessus.

cas 1: L'application est lancée pour la première fois ou la nième fois, mais avec un jeu de fichiers cible différent. L'application est maintenant dit de calculer les valeurs de hachage sur les fichiers jamais accessibles auparavant.

  • ~ 50ms
  • Constructeur FileStream
  • Calcul de 18% de hachage

    Case 2: L'application est maintenant entièrement terminée et a recommencé à calculer de calculer hachage sur les mêmes fichiers:

    • ~ 8ms
    • 90% de calcul de hachage
    • 8% de constructeur de filtream

      problème
      Ma candidature est toujours utilisée Case 1 . Il ne sera jamais demandé de ré-calculer un hash sur un fichier déjà visité une fois.

      Donc, mon étape de détermination du taux est le constructeur de filtream! Y a-t-il quelque chose que je puisse faire pour accélérer ce cas d'utilisation?

      merci.

      P.s. Les statistiques ont été rassemblées avec un profileur JetBrains.


6 commentaires

Je vois exactement le même comportement. Utilisation de ReadallBytes et de calcul du hachage prend peu de temps, mais peut être terrible sur la mémoire (en fonction de la taille du fichier). J'ai donc essayé de passer un filtream à la ComputeHash de MD5 ($ ruisseau) et de voir des résultats complètement inacceptables. Les temps de résultat sont des ordres de grandeur dans la différence ...


@ALEX K: de la recherche sur le filtream SOURCE , on dirait qu'il existe des tonnes de directives de préprocesseur et, même dans les chemins les plus simples, l'initialisation semble être assez complexe. Vous voudrez peut-être spécifier quel constructeur spécifique vous rencontrez des problèmes et ce que votre environnement ressemble et que vous espérons que les gens (beaucoup) plus intelligents que moi puissent vous aider.


Êtes-vous correctement multithreadé? Oui, les broches sont limitées, mais lors de l'accès à de nombreux petits fichiers, vous pouvez passer la plupart du temps à attendre des données, et vous pouvez accélérer cela un peu (ou plus dans SSD) en passant à plusieurs filetés. Pas "extrême" mais 2-3 threads peut aider à réduire les temps d'arrêt.


Besoin de plus d'informations. Comment appelez-vous exactement le constructeur? Quels sont vos arguments et à quoi ressemblent-ils? Chemin absolu ou chemin relatif? Êtes-vous ngen'ing votre programme pour réduire / supprimer les frais généraux JIT? Êtes-vous en cours d'exécution dans un scénario de confiance limité ou votre application a-t-elle une confiance totale? Avez-vous essayé d'ouvrir le fichier avec FileOptionS.EntésCan ? Avez-vous essayé d'avoir activé Multicore Jit via ProfiltOntimization.StartProfile ?


@antiDuh tout ce qui prend 10 secondes n'est évidemment pas une fonction de ces options, mais un bogue, que je ne m'attends pas à être réparé.


@Danieldonnelly - Vous répondez à une question qui n'a pas été posée. Vous n'êtes pas l'affiche et l'affiche ne précisait pas avoir un problème avec des retards de 10 secondes; Le leur est un retard de 50 ms. Veuillez ne pas essayer de changer le sujet d'une autre question d'affiche; Demandez à votre choix à la place. Si vous rencontrez des difficultés, je vous suggère de lire le centre d'aide sur la manière de demander des questions productives.


5 Réponses :


1
votes

Le système de fichiers et ou contrôleur de disque cache récemment accessible des fichiers / secteurs.

L'étape de détermination de la vitesse lise le fichier, ne constrisant pas un objet filtream , et il est complètement normal qu'il sera nettement plus rapide sur la deuxième exécution lorsque les données sont dans le cache.


1 commentaires

Je ne crois pas que ce soit le cas. FileStream Constructor ne lit pas l'intégralité du fichier, la fonction de hachage appelle à cet effet. Mais c'est le constructeur qui prend 80% du temps.



-1
votes

Vous devriez essayer d'utiliser le native FileStream


1 commentaires

N'utilise pas le constructeur qui prend un fichierOPTIONS fait cela au flux déjà Si vous le transmettez FILEOPTIONS.EUVENTCAN ? EDIT: Oui, c'est-à-dire à travers la source de référence que le paramètre Enum est tourné vers le dwflagsandattributes de créeefile et la valeur de l'ENum est 0x08000000 Quelle est la même valeur que file_flag_Suite_scan



1
votes

Comme indiqué précédemment, le système de fichiers a son propre mécanisme de mise en cache qui perturbe votre mesure.

Cependant, le constructeur filtream effectue plusieurs tâches qui, la première fois coûtent cher et nécessitent l'accès du système de fichiers (donc quelque chose qui pourrait ne pas être dans le cache de données). Pour des raisons explicatives, vous pouvez consulter le code et voir que les classes compatibilité sont utilisées pour détecter l'utilisation des sous-traitants. Avec cette classe, la réflexion est fortement utilisée à la fois directement (pour accéder à l'assemblage actuel) et indirectement (pour les sections protégées contre les CAS, les demandes de liaison de sécurité). Le moteur de réflexion a son propre cache et nécessite l'accès au système de fichiers lorsque son propre cache est vide.

Il se sent un peu étrange que les deux mesures soient si différentes. Nous avons actuellement quelque chose de similaire sur nos machines équipées d'un logiciel antivirus configuré avec une protection en temps réel. Dans ce cas, le logiciel antivirus est au milieu et le cache est touché ou manqué la première fois en fonction de la mise en œuvre de ce logiciel.

Le logiciel antivirus peut décider de vérifier de manière agressive certains fichiers d'image, tels que PNGS, en raison des vulnérabilités connues du décodage. Ces vérifications introduisent un ralentissement supplémentaire et des comptes le temps dans la classe la plus externe. Net, c'est-à-dire la classe filtream .

Profilage à l'aide de symboles natifs et / ou avec le débogage du noyau, devrait vous donner plus d'idées.

Basé sur mon expérience, ce que vous décrivez ne peut être atténué car il existe plusieurs couches cachées de notre contrôle. Selon votre utilisation, ce qui n'est pas parfaitement clair pour moi en ce moment, vous pouvez activer la demande dans un service, vous pouvez donc servir toutes les demandes suivantes plus rapidement. Alternative, vous pouvez lotter plusieurs demandes dans un seul appel pour atteindre un coût réduit amorti.


0 commentaires

3
votes

... mais avec un jeu de fichiers cible différent.

phrase clé, votre application ne sera pas en mesure de tirer parti du cache du système de fichiers. Comme il l'a fait dans la deuxième mesure. Les informations de répertoire ne peuvent pas venir de RAM car ce n'était pas encore lu, le système d'exploitation doit toujours revenir sur le lecteur de disque et c'est lent.

Seul meilleur matériel peut accélérer. 50 MSEC parle de la quantité de temps standard nécessaire pour un lecteur de broche, 20 msc est à peu près aussi bas que de tels disques peuvent aller. Le temps de recherche du lecteur est la limite mécanique dure. C'est facile à battre aujourd'hui, SSD est largement disponible et raisonnablement abordable. Le seul problème avec c'est que lorsque vous vous êtes habitué, vous ne revenez jamais :)


0 commentaires

1
votes

Suggestion hors piste, mais c'est quelque chose que j'ai fait beaucoup et que nos analyses 30% - 70% plus rapidement:

Caching


Écrivez un autre morceau de code qui:

  • itérer sur tous les fichiers;
  • calculer le hachage; et,
  • Stockez-le dans un autre index fichier.

    Maintenant, n'appelez pas un filtream constructeur pour calculer le hachage lorsque votre application commence. Au lieu de cela, ouvrez le fichier d'index plus petit (beaucoup) et lisez le hachage précalculé.

    En outre, si ces fichiers sont loges, etc. Les fichiers fraîchement créés chaque fois que votre application ne démarre, ajoutez du code dans le créateur de fichier pour mettre à jour également le fichier d'index avec le hachage du fichier nouvellement créé.

    De cette façon, votre application peut toujours lire le hasch à partir du fichier d'index uniquement.


    Je suis d'accord avec la suggestion de @ Hanspassant d'utiliser des SSD pour que votre disque se lit plus rapidement. Cette réponse et sa réponse sont complémentaires. Vous pouvez mettre en œuvre les deux pour maximiser les performances.


8 commentaires

Mon problème est que cela prend 15 secondes pour charger un simple PNG de 8 Ko.


@Danieldonnelly: les données de la taille de 8 kb ne sont pas suffisamment grandes pour prendre 15 secondes pour charger. Il se peut que votre disque dur soit accessible par plusieurs programmes. Pour cela, essayez de mettre vos données sur un autre lecteur et de voir si le temps d'accès revient à presque instantané. De plus, votre lecteur est-il sur le réseau?


Nope pas sur le réseau. C'est bizarre que tous les autres programmes de ma machine fonctionnent, à l'exception d'une tentative de charger une petite texture et que j'ai codé dans C # avec monogame. Cela m'a fait arrêter le projet et n'utilisez plus C # si je recommence. Les images que j'ai besoin générées à la volée sont des rendus de latex d'une petite quantité de texte. Même le latex rend plus rapide: 2 secondes, qui est acceptable pour ma demande sous la mise en cache comme vous le dites, mais 10-15 secondes d'attente n'est pas utilisable. Je viens de commencer à utiliser monogame afin que mon environnement soit 100% la dernière version de tout.


@Danieldonnelly: Veuillez éditer la question et ajouter le code complet de la vôtre ... comme exemple de cas de la situation. C'est un comportement extrêmement étrange. Pourrait-il être dû à toute bibliothèque indigène que vous utilisez?


Ils m'ont bloqué de poser des questions. Chaque fois qu'ils ne m'ont pas inutilisé, je pose une question parfaite, puis être banni à nouveau. Voir mon histoire. Donc, je ne peux pas poser une question. Même si je suis 100% capable de créer un exemple de travail minimal et de l'expliquer parfaitement en anglais.


Puis-je vous envoyer un exemple de travail minimal? J'ai essayé 5 extraits de code différents, mais le communalisme et l'échec de chacun se trouvent dans l'appel de Solestream.


@Danieldonnelly: Pendant que vous ne pourrez peut-être pas en demander une nouvelle, vous pourrez peut-être modifier cette question et ajouter votre code. Est-ce possible?


@DisplayName - Ce n'est pas une bonne idée. Daniel ne devrait pas modifier la question de quelqu'un d'autre à se servir. S'il ne peut pas poser une question en raison d'une faible représentante, après des interactions répétées, alors c'est un signe qu'il ne participe pas à la bonne foi.