2013-04-19 1 views
1

Supposons que nous ayons une application erlang qui implique des milliers de processus. Supposons qu'il y ait une seule ressource X qui peut être un tuple, une liste, ou tout autre terme erlang, que tous ces processus peuvent avoir besoin de lire/extraire quelque chose, à tout moment.

Un exemple d'une telle occurrence, disons, un système d'API, dans lequel les processus client peuvent avoir besoin de lire et d'écrire sur une machine distante. Ant il arrive que vous ne voulez pas, pour chaque demande de lecture/écriture, une nouvelle connexion à créer. Donc, ce que vous faites, vous créez un pool de connexions, considérez-les comme un pool de canaux/sockets/canaux ouverts.

Maintenant, ce pool de ressources doit être partagé par des milliers de processus de sorte que, pour chaque demande de lecture ou d'écriture, vous souhaitiez que ce processus récupère tout canal/ressource ouvert disponible. La question est, et si j'ai un processus (un seul processus) détenir cette information, que ce soit dans son dictionnaire de processus ou dans sa boucle de réception. Cela signifierait que tous les processus devraient envoyer un message à ce processus chaque fois qu'ils ont besoin d'une ressource gratuite. Ce processus unique aurait une énorme boîte aux lettres à tout moment en raison de la forte demande pour cette seule ressource.

OU Je pourrais utiliser une table ETS et avoir une seule ligne, disons #resources{key=pool,value= List_of_openSockets_or_channels}. Mais cela signifierait que tous nos processus tenteraient de faire une lecture à partir de la table ETS pour la même ligne à (probabilité élevée) les mêmes instants instantanés.

Comment la table ETS gérerait-elle, si 10 000 processus atttempt une lecture, pour la même ligne/enregistrement de lui, en même temps/à peu près au même moment? et pourtant, si j'utilise un processus, sa boîte aux lettres, si 10 000 processus lui envoient un message, en même temps, pour la même ressource (et qu'il faudrait répondre à chaque demandeur). Et rappelez-vous que cette action peut se produire si souvent. Quelle option (dis-concernant les problèmes de disponibilité du processus descendant bla bla), fournirait un débit plus élevé, de sorte que les processus obtiendraient ce dont ils ont besoin plus rapidement?

Existe-t-il un autre meilleur moyen de gérer les structures de données à forte demande dans la machine virtuelle Erlang de manière à fournir un accès très rapide à des millions de processus, même s'ils ont tous besoin de cette ressource?Débit de récupération de données - Recherche ETS par rapport à la messagerie inter-processus

+0

Dans d'autres langues, peut-être, ce serait dans une variable globale. –

+0

Je suppose que vous avez déjà joué avec l'option ''{read_concurrency, true}' d'ETS? Si vous n'avez pas beaucoup de commutateurs entre les opérations de lecture et d'écriture, cela pourrait aider. –

+0

merci @Robert, j'ai déjà regardé cette option, mais, voyez-vous, j'ai un problème de comparaison entre 'ETS' et' Process messaging'. Comment expliquez-vous les deux? Certainement, l'un d'entre eux peut être une meilleure option, mais, théoriquement, avant de faire des tests, comment pensez-vous que chacun se comporte, compte tenu de votre expérience en erlang? –

Répondre

3

Réponse courte: profil. Essayez différentes approches et vérifiez le comportement de votre système.

Tout d'abord, je regarderais l'option {read_concurrency, true} d'ETS. De the documentation:

{read_concurrency, Boolean()} Réglage des performances. La valeur par défaut est false. Lorsque cette propriété est définie sur true, la table est optimisée pour les opérations de lecture simultanées . Lorsque cette option est activée sur un système d'exécution avec le support SMP , les opérations de lecture deviennent beaucoup moins coûteuses; en particulier sur les systèmes avec plusieurs processeurs physiques. Cependant, la commutation entre les opérations d'écriture en lecture et devient plus coûteuse. Vous voulez généralement activer cette option lorsque les opérations de lecture simultanées sont beaucoup plus fréquentes que les opérations d'écriture ou lorsque les lectures et écritures simultanées sont en grandes lectures et écritures (c'est-à-dire beaucoup de lectures non interrompues par écritures, et beaucoup de écrit non interrompu par des lectures). En général, ne souhaite pas activer cette option lorsque le modèle d'accès commun correspond à quelques opérations de lecture entrelacées avec quelques opérations d'écriture répétées. Dans ce cas, vous obtiendrez une dégradation des performances en activant cette option . L'option read_concurrency peut être combinée avec l'option write_concurrency.Vous souhaitez généralement les combiner lorsque de grandes rafales de lecture simultanées et de grandes rafales d'écriture simultanées sont commun.

Deuxièmement, je regarderais cache possibilités. Les processus lisent-ils cette information une seule fois ou plusieurs fois? S'ils y accèdent plusieurs fois, vous pouvez le lire une fois et le stocker dans votre état de processus. Troisièmement, vous pouvez essayer de répliquer et distribuer cette information à travers votre système. Divide et impera.

+0

merci @Roberto –

2

Si vous utilisez l'approche de processus, afin d'éviter que toutes les demandes de lecture sérialisées dans la file d'attente de messages du processus 'serveur', doivent être répliquées. Utiliser une table ETS avec read_concurrency me semble plus naturel et c'est quelque chose que j'ai utilisé lors du développement de la version parallèle de Dialyzer. Cependant, l'accès ETS n'a jamais été un goulot d'étranglement dans ce cas.

+0

Merci @aronisstav –

Questions connexes