Question

Je profiler un programme multithread en cours d'exécution avec un nombre différent de threads autorisés. Voici les résultats de la performance de trois points du même travail d'entrée.

1 thread:
  Total thread time: 60 minutes.
  Total wall clock time: 60 minutes.

10 threads:
  Total thread time: 80 minutes. (Worked 33% longer)
  Total wall clock time: 18 minutes.  3.3 times speed up

20 threads
  Total thread time: 120 minutes. (Worked 100% longer)
  Total wall clock time: 12 minutes.  5 times speed up

Comme il faut plus de temps de fil pour faire le même travail, je me sens les fils doivent être disputaient les ressources.

Je l'ai déjà examiné les quatre piliers (cpu, mémoire, diskio, réseau) sur la machine de l'application et le serveur de base de données. Mémoire était la ressource originale soutenu, mais qui est maintenant fixé (plus de 1G libre en tout temps). CPU oscille entre 30% et 70% sur le test de 20 fil, donc beaucoup là-bas. diskio est pratiquement pas sur la machine de l'application, et minimale sur le serveur de base de données. Le réseau est vraiment génial.

J'ai également le code-nervurées avec Redgate et ne voient pas les méthodes d'attente sur les serrures. Il aide que les fils ne partagent pas les instances. Maintenant, je vérifie les articles plus nuancés comme la connexion de base de données établissant / mise en commun (si 20 threads tentent de se connecter à la même base de données, ont-ils attendre les uns des autres?).

Je suis en train d'identifier et de répondre à l'affirmation des ressources, de sorte que la course de 20 fils ressemblerait à ceci:

20 threads
  Total thread time: 60 minutes. (Worked 0% longer)
  Total wall clock time: 6 minutes.  10 times speed up

Quelles sont les sources les plus probables (autres que le grand 4) que je devrais regarder pour trouver cette affirmation?


Le code qui exécute chacune de fil est d'environ:

Run ~50 compiled LinqToSql queries
Run ILOG Rules
Call WCF Service which runs ~50 compiled LinqToSql queries, returns some data
Run more ILOG Rules
Call another WCF service which uses devexpress to render a pdf, returns as binary data
Store pdf to network
Use LinqToSql to update/insert. DTC is involved: multiple databases, one server.

Les services WCF sont en cours d'exécution sur la même machine et qui sont apatrides et capables de gérer plusieurs requêtes simultanées.


La machine a de 8 cpu.

Était-ce utile?

La solution

Ce que vous décrivez est que vous voulez une évolutivité d'un 100% qui est une relation 1: 1 entre l'augmentation du fil s et la diminution du temps de wallcklock ... c'est usally un but, mais difficile à atteindre ...

Par exemple, vous écrivez qu'il n'y a pas de conflit de mémoire, car il est de 1 Go d'espace libre ... ceci est mon humble avis une hypothèse erronée ... des moyens de contention de mémoire que si deux threads tentent d'allouer de la mémoire, il pourrait arriver que l'on doit attendre que l'autre ... une autre ponint garder à l'esprit sont les interruptions qui se produisent par GC qui gèle temporairement toutes les discussions ... le GC peut être Customzed un peu via la configuration (gcServer) - voir http://blogs.msdn.com/b/clyon/archive/2004/09/08 /226981.aspx

Un autre point est le service WCF appelé ... si elle ne peut pas intensifier -par exemple le PDF rendering- alors qui est aussi une forme de discorde par exemple ...

La liste de discorde possible est « sans fin » ... et à peine toujours sur les zones évidentes que vous avez mentionnés ...

EDIT - selon les commentaires:

Quelques points à vérifier:

  • mise en commun de connexion
    quel fournisseur utilisez-vous? comment est-il configuré?
  • PDF rendu
    contention possible serait mesuré quelque part dans la bibliothèque que vous utilisez ...
  • Linq2SQL
    Vérifiez les plans d'exécution pour toutes ces questions ... il se peut que certains prennent toute sorte de serrure et donc peut-être créer une affirmation DB-côté serveur ...

EDIT 2:

Fils
Sont ces fils du ThreadPool? Si oui, alors vous ne serez pas l'échelle: - (

EDIT 3:

threads ThreadPool sont mauvaises pour les tâches en cours d'exécution longue qui est le cas dans votre scénario ... Pour plus de détails voir

De http://www.yoda.arachsys.com/csharp/ fils / printable.shtml

Les opérations de longue durée devraient utiliser des fils nouvellement créés; court en cours d'exécution des opérations peut profiter de la piscine de fil.

Si vous voulez des performances extrêmes, alors il pourrait être utile de vérifier CQRS et le réel exemple du monde décrit comme LMAX .

Autres conseils

Au lieu de mesurer le temps total de fil, de mesurer le temps pour chacune des opérations que vous faites qui font d'E / S de quelque sorte (base de données, disque, réseau, etc.).

Je suppose que vous allez constater que ces opérations sont celles qui prennent plus lorsque vous avez plus de fils, et ce parce que l'affirmation est à l'autre bout de cette E / S. Par exemple, la base de données peut être sérialisation demandes de la cohérence des données.

yes, there's resource contention. All the threads have to read/write data to the same memory bus, directed to the same RAM modules, for example. It doesn't matter how much RAM is free, it matters that the reads/writes are carried out by the same memory controller on the same RAM modules, and that the data is carried over the same bus.

If there's any kind of synchronization anywhere, then that too is a contended resource. If there's any I/O, that's a contended resource.

You're never going to see a N x speedup when going from 1 to N threads. It's not possible because ultimately, everything in the CPU is a shared resource on which there will be some degree of contention.

There are plenty of factors preventing you from getting the full linear speedup. You're assuming that the database, the server the database is running on, the network connecting it to the client, the client computer, the OS and drivers on both ends, the memory subsystem, disk I/O and everything in between is capable of just going 20 times faster when you go from 1 to 20 threads.

Two words: dream on.

Each of these bottlenecks only has to slow you down by a few percent, then the overall result will be something like what you're seeing.

I'm sure you can tweak it to scale a bit better, but don't expect miracles.

But one thing you might look for is cache line sharing. Do threads access data that is very close to the data used by other threads? How often can you avoid that occurring?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top