2009-08-20 8 views
2

J'ai besoin de lire de petites séquences de données à partir d'un fichier de 3,7 Go. Les positions que j'ai besoin de lire sont non adjacentes, mais je peux commander les E/S afin que le fichier soit lu du début à la fin.Comment tirer parti de la mise en file d'attente du disque IO

Le fichier est stocké sur un SAN iSCSI qui doit être capable de gérer/optimiser les E/S en file d'attente. La question est, comment puis-je faire une demande en un coup de toutes les données/positions dont j'ai besoin en une seule fois? C'est possible? Je ne pense pas async IO est une option, car les lectures sont très petites (20-200 octets)

Actuellement le code ressemble à ceci:

using (var fileStream = new FileStream(dataStorePath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
{ 
    for (int i = 0; i < internalIds.Count();i++) 
    { 
     fileStream.Position = seekPositions[i].SeekPosition; 
     ... = Serializer.DeserializeWithLengthPrefix<...>(fileStream, PrefixStyle.Base128); 

    } 
    ... 
} 

Je cherche des moyens d'améliorer ce que je/O parce que j'obtiens des performances de lecture légèrement inférieures. Tous les temps de recherche de déplacement de la tête semblent être additionnés.

Répondre

1

Avez-vous exécuté Performance Monitor (à partir de Microsoft Sysinternals) à ce sujet?

Je ne sais pas quel est le problème, mais je vais essayer de deviner. Si vous lisez un SAN, je pense que les accès au disque entraînent des demandes de réseau sous le capot. La première lecture envoie une requête pour rechercher, lire et mettre en mémoire tampon les données, puis le sérialiseur construit les objets. Au moment où votre deuxième demande est envoyée, les disques SAN ont continué à tourner, vous devez donc attendre que les données soient mises en place.

Avez-vous essayé le multithreading? Je suis curieux de connaître les performances si vous configurez une file d'attente de sections de fichiers que vous devez traiter dans un ordre séquentiel, faites tourner quelques threads, ouvrez-les séparément (FileSharing.Read pour qu'ils puissent tous accéder au fichier en même temps) et puis laissez-les commencer à saisir le travail de la file d'attente. Générez les résultats dans une autre collection. Si l'ordre est important pour la sortie, vous triez la sortie selon l'ordre d'origine dans lequel vous les avez mis en file d'attente.

--- EDIT ---

Avez-vous essayé le ReadFileScatter API? Here's a P-invoke signature from pinvoke.net.

+0

+1 pour comprendre la question. Je crois que c'est exactement ce qui se passe, au moment où la deuxième lecture doit être faite, les disques ont déjà filé, d'où la raison pour laquelle je cherche un moyen de faire la queue matérielle. – andreialecu

+0

J'aurais pensé que Windows a géré la mise en file d'attente matérielle pour vous. Vous ne pouvez certainement pas obtenir médiévale avec le disque dur sur la base C#. Vous pouvez seulement dire "allez ici et lisez X octets". J'expérimenterais différents modèles d'accès avec plusieurs threads.Peut-être que ce serait plus rapide si 2 fils lisaient A et B, puis C et D; ou peut-être A et M, puis B et N. –

+0

L'API ReadFileScatter semble prometteuse. Ajout d'un texte de présentation à ma réponse. –

0

Créez un unique en tâche de fond en tant que proxy de disque. Envoyez-lui toutes vos opérations de lecture, faites-le trier et fusionnez les lectures. Si deux régions ou plus sont proches, lisez le secteur complet qui les contient et prenez des sous-sections des données. Renvoie les données de manière asynchrone.

+0

Les lectures sont déjà ordonnées, et FileStream lui-même fait déjà ce type de mise en mémoire tampon par défaut - raison pour laquelle les performances ne sont pas tout à fait terribles. Voir le lien suivant pour confirmer que la mise en mémoire tampon se produit effectivement: http://blogs.msdn.com/brada/archive/2004/04/15/114329.aspx – andreialecu

0

Pour la petite histoire:

Dans les environnements vous pouvez demander POSIX plusieurs zones d'un fichier avec un (sys-) appel à l'aide de la fonction readv. Une autre partie d'un environnement POSIX serait une E/S non bloquante.