Question

Notre service a tendance à s’endormir la nuit sur le serveur de notre client, puis à se réveiller. Ce qui semble arriver, c'est que le tas de processus, qui représente parfois plusieurs centaines de Mo, est déplacé vers le fichier d'échange. Cela se produit la nuit, lorsque notre service n'est pas utilisé et que d'autres sont planifiés pour s'exécuter (sauvegardes de base de données, analyses AV, etc.). Lorsque cela se produit, après quelques heures d'inactivité, le premier appel au service prend jusqu'à quelques minutes (les appels suivants prennent quelques secondes).

Je suis presque certain que c'est un problème de gestion de la mémoire virtuelle et je déteste vraiment l'idée de forcer le système d'exploitation à conserver notre service dans la mémoire physique. Je sais que cela nuira aux autres processus du serveur et réduira le débit global du serveur. Cela dit, nos clients veulent simplement que notre application soit réactive. Ils se moquent de savoir si les travaux nocturnes prennent plus de temps.

Je me souviens vaguement qu'il existe un moyen de forcer Windows à conserver des pages dans la mémoire physique, mais je déteste vraiment cette idée. Je suis plutôt orienté vers un organisme de surveillance interne ou externe qui initiera des fonctionnalités de niveau supérieur (il existe déjà un planificateur interne qui fait très peu et ne fait aucune différence). S'il existait un outil tiers fournissant ce type de service, il aurait été aussi efficace.

J'aimerais entendre vos commentaires, recommandations et solutions communes à ce type de problème. Le service est écrit en VC2005 et fonctionne sur des serveurs Windows.

Était-ce utile?

La solution

Comme vous l'avez mentionné, forcer l'application à rester en mémoire n'est pas le meilleur moyen de partager des ressources sur la machine. Une solution rapide qui vous convient peut-être est de planifier simplement un événement qui réveillera votre service à une heure précise chaque matin avant que vos clients ne commencent à l'utiliser. Vous pouvez simplement le planifier dans le planificateur de tâches Windows à l'aide d'un script simple ou d'un appel EXE.

Autres conseils

Je ne dis pas que vous voulez faire cela, ou que c'est une pratique exemplaire, mais vous constaterez peut-être que cela fonctionne assez bien pour vous. Cela semble correspondre à ce que vous avez demandé.

Résumé: touchez chaque page du processus, page par page, régulièrement.

Qu'en est-il d'un thread qui s'exécute en arrière-plan et se réveille une fois toutes les N secondes. Chaque fois que la page se réveille, elle tente de lire à partir de l'adresse X. La tentative est protégée par un gestionnaire d'exceptions au cas où vous lisiez une adresse incorrecte. Puis incrémentez X de la taille d’une page.

Il y a 65 536 pages en 4Go, 49152 en 3GB, 32768 en 2GB. Divisez votre temps d'inactivité (temps mort pendant la nuit) par la fréquence à laquelle vous souhaitez (tentative) taper sur chaque page.

BYTE *ptr;

ptr = NULL;
while(TRUE)
{
    __try
    {
        BYTE b;

        b = *ptr;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        // ignore, some pages won't be accessible
    }

    ptr += sizeofVMPage;

    Sleep(N * 1000);
}

Vous pouvez obtenir la valeur sizeOfVMPage à partir de la valeur dwPageSize dans le résultat renvoyé par GetSystemInfo ().

N'essayez pas d'éviter le gestionnaire d'exceptions en utilisant if (! IsBadReadPtr (ptr)) car d'autres threads de l'application pourraient modifier les protections de la mémoire en même temps. Si vous êtes débloqué à cause de cela, il sera presque impossible d'identifier pourquoi (ce sera probablement une condition de concurrence irréversible), alors ne perdez pas de temps avec cela.

Bien sûr, vous souhaitez désactiver ce fil pendant la journée et ne l'exécuter que pendant votre temps mort.

Une troisième solution pourrait consister à faire en sorte que votre service exécute un thread qui fait quelque chose de trivial, comme incrémenter un compteur, puis dormir pendant une période assez longue, disons 10 secondes. Thios devrait avoir un effet minimal sur les autres applications, tout en maintenant au moins certaines de vos pages disponibles.

Vous devez également vous assurer que vos données sont localisées.

En d’autres termes: avez-vous vraiment besoin des 300 Mo de mémoire avant de pouvoir faire quoi que ce soit? Les structures de données que vous utilisez peuvent-elles être réorganisées de telle sorte qu’une requête particulière ne puisse être satisfaite qu’en quelques mégaoctets?

Par exemple

  • si vos 300 Mo de mémoire de tas contiennent des données de reconnaissance faciale. Peut-on organiser les données en interne de manière à ce que les données relatives aux visages masculins et féminins soient stockées ensemble? Ou les grands non sont séparés des petits-nez?

  • s'il a une sorte de structure logique, peut-il être trié? de sorte qu'une recherche binaire puisse être utilisée pour sauter beaucoup de pages?

  • s'il s'agit d'un moteur de base de données propritary en mémoire, les données peuvent-elles être mieux indexées / groupées pour ne pas nécessiter autant d'accès à la page en mémoire?

  • s’il s’agit de textures d’image, les textures couramment utilisées peuvent-elles être proches les unes des autres?

Avez-vous vraiment besoin des 300 Mo de mémoire avant de pouvoir faire quoi que ce soit? Vous ne pouvez pas traiter la demande sans toutes ces données dans la mémoire?


Sinon : planifiez la tâche à 6 pour la réactiver.

En termes de coût, la solution la moins chère et la plus simple consiste probablement à acheter plus de RAM pour ce serveur, puis à désactiver complètement le fichier d'échange. Si vous utilisez Windows 32 bits, achetez simplement 4 Go de RAM. Ensuite, tout l'espace d'adressage sera sauvegardé avec la mémoire physique et le fichier d'échange ne fera rien de toute façon.

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