Question

J'ai des messages à venir dans mon programme avec une résolution de milliseconde (entre zéro et quelques centaines de messages d'une milliseconde).

Je voudrais faire une analyse. Plus précisément, je veux maintenir de multiples fenêtres de roulement des comptes de messagerie, mis à jour sous forme de messages entrent en jeu. Par exemple,

  • Nombre de messages dans la dernière seconde
  • Nombre de messages dans la dernière minute
  • Nombre de messages dans la dernière demi-heure divisé par Nombre de messages dans la dernière heure

Je ne peux pas maintenir un compte simple comme « 1017 messages dans la dernière seconde » , puisque je ne sais quand un message est plus de 1 seconde et donc ne devrait plus être dans la compter ...

Je pensais que de maintenir une file d'attente de tous les messages, à la recherche du message le plus jeune qui est plus d'une seconde, et déduisant le compte de l'indice. Cependant, cela semble que ce serait trop lent, et il mangera beaucoup de mémoire.

Que puis-je faire pour garder une trace de ces comptes dans mon programme afin que je puisse obtenir efficacement ces valeurs en temps réel?

Était-ce utile?

La solution

Ceci est plus facile manipuler par un tampon cyclique.

Un tampon cyclique a un nombre fixe d'éléments, et un pointeur vers elle. Vous pouvez ajouter un élément à la mémoire tampon, et quand vous le faites, vous incrémenter le pointeur sur l'élément suivant. Si vous avez passé la mémoire tampon de longueur fixe vous commencez dès le début. Il est un espace et le temps moyen efficace de stocker des éléments « dernier N ».

Dans votre cas, vous pouvez avoir un tampon cyclique de 1000 compteurs, chacun comptant le nombre de messages au cours d'une milliseconde. Ajout de tous les compteurs 1000 vous donne le nombre total lors de la dernière seconde. Bien sûr, vous pouvez optimiser la partie des rapports en mettant à jour progressivement le nombre, à savoir le déduire forment compter le numéro que vous écrasez lorsque vous insérez puis ajoutez le nouveau numéro.

Vous pouvez alors un autre tampon cyclique qui a 60 emplacements et compte le nombre total de messages en quelques secondes entières; une fois par seconde, vous prenez le nombre total de la mémoire tampon de milliseconde et d'écrire le nombre dans la mémoire tampon ayant une résolution de secondes, etc.

Voici C-like pseudocode:

int msecbuf[1000]; // initialized with zeroes
int secbuf[60]; // ditto
int msecptr = 0, secptr = 0;
int count = 0;
int msec_total_ctr = 0;
void msg_received() { count++; }
void every_msec() {
  msec_total_ctr -= msecbuf[msecptr];
  msecbuf[msecptr] = count;
  msec_total_ctr += msecbuf[msecptr];
  count = 0;
  msecptr = (msecptr + 1) % 1000;
}
void every_sec() {
  secbuf[secptr] = msec_total_ctr;
  secptr = (secptr + 1) % 60;
}

Autres conseils

Vous voulez lissage exponentiel , autrement connu comme une moyenne mobile pondérée exponentielle. Prenez un EWMA du temps depuis le dernier message est arrivé, puis diviser ce temps en une seconde. Vous pouvez exécuter plusieurs d'entre eux avec des poids différents pour couvrir efficacement plus des intervalles de temps. En effet, vous utilisez une fenêtre infiniment longue alors, de sorte que vous n'avez pas à vous soucier des données venant à échéance; les poids en réduisant le font pour vous.

Pour la dernière millisecord, garder le comte. Lorsque la tranche de millisecord va à la suivante, et réinitialiser le nombre ajouter le nombre à un réseau de tampon de roulement milliseconde. Si vous gardez cela cummulative, vous pouvez extraire le nombre de messages / seconde avec une quantité fixe de mémoire.

Lorsqu'une 0,1 seconde tranche (ou une autre petite valeur à côté de 1 minute) se fait, résumer derniers 0,1 * 1000 des éléments de la matrice de tampons de laminage et placer que dans le prochain tampon de laminage. De cette façon, vous KAN garder le petit tampon de roulement millisecord (1000 articles pour 1 s max recherche) et le tampon pour la recherche de la minute aussi (600 articles).

Vous pouvez faire le tour suivant pour minutes entières de 0,1 minutes d'intervalle. Toutes les questions posées peuvent être demandées en additionnant (ou lors de l'utilisation cummulative, retranchant deux valeurs) quelques entiers.

Le seul inconvénient est que la dernière valeur de s wil remplacer tous les ms et la valeur de chaque minute seulement 0,1 secand la valeur de l'heure (et les dérivés avec le% en dernier 1/2 heure) tous les 0,1 minute. Mais au moins vous gardez votre utilisation de la mémoire à distance.

La fenêtre d'affichage de roulement ne peut mettre à jour si rapide, permet de dire que vous voulez le mettre à jour 10 fois par seconde, donc pendant 1 seconde la valeur de données, vous auriez besoin de 10 valeurs. Chaque valeur contiendrait le nombre de messages qui a montré en ce que 1/10 de seconde. Appelons ces bacs valeurs, chaque bac peut contenir un dixième de la valeur des données d'une seconde. Toutes les 100 millisecondes, un des bacs et un obtient mis au rebut nouveau bac est réglé sur le nombre de messages qui ont apparaissent dans ces 100 millisecondes.

Vous auriez besoin d'un tableau de 36K bacs pour contenir des informations valeur d'une heure au sujet de votre taux de message si vous voulez conserver une précision de 1/10 de seconde pour toute heure. Mais cela semble exagéré.

Mais je pense qu'il serait plus raisonnable d'avoir la précision déposer que le temps INTEVAL grossit.

Peut-être que vous continuez à 1 seconde la valeur de données précises à 100 millisecondes, 1 minutes valeur de données précises à la seconde, 1 heure de valeur de données précises à la minute, et ainsi de suite.

  

Je pensais que de maintenir une file d'attente de tous les messages, à la recherche du message le plus jeune qui est plus d'une seconde, et déduisant le compte de l'indice. Cependant, cela semble que ce serait trop lent, et il mangera beaucoup de mémoire.

Une meilleure idée serait maintenir une liste chaînée des messages, en ajoutant de nouveaux messages à la tête (avec un horodatage), et les popping de la queue comme ils expirent. Ou même pas les pop - il suffit de garder un pointeur sur le message le plus ancien qui est entré dans les délais voulus, et avancer vers la tête lorsque ce message arrive à expiration (ce qui vous permet de garder une trace des délais se multiplient avec une liste)

Vous pouvez calculer le nombre en cas de besoin en marchant de la queue à la tête, ou tout simplement stocker le compte séparément, incrémenter chaque fois que vous ajoutez une valeur à la tête, et décrémenter chaque fois que vous avancez la queue.

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