Question

Disons que vous souhaitez rédiger une méthode haute performance qui traite un grand ensemble de données. Pourquoi les développeurs ne devraient-ils pas avoir la possibilité d'allumer la gestion de la mémoire manuelle au lieu d'être obligé de passer à C ou C ++?

void Process()
{
    unmanaged
    {
        Byte[] buffer;
        while (true)
        {
            buffer = new Byte[1024000000];

            // process

            delete buffer;
        } 
    }   
}
Était-ce utile?

La solution

Parce que vous permettre de supprimer manuellement un bloc de mémoire alors qu'il peut encore y avoir des références (et le temps d'exécution n'a aucun moyen de savoir que sans faire de cycle GC) peut produire des pointeurs pendants, et ainsi casser sécurité de la mémoire. Les langues GC sont généralement en sécurité par la mémoire par conception.

Cela dit, en C #, en particulier, vous pouvez déjà faire ce que vous voulez:

void Process()
{
    unsafe
    {
        byte* buffer;
        while (true)
        {
            buffer = Marshal.AllocHGlobal(1024000000);

            // process

            Marshal.FreeHGlobal(buffer);
        } 
    }   
}

Notez que, comme en C / C ++, vous avez l'arithmétique du pointeur complet pour les types de pointeurs bruts en C # - donc buffer[i] ou buffer+i sont des expressions valides.

Autres conseils

Si vous avez besoin de performances élevées et de contrôle détaillé, vous devriez peut-être écrire ce que vous faites en C ou C ++. Toutes les langues ne sont pas bonnes pour toutes choses.

Édité pour ajouter: une seule langue ne sera pas bonne pour toutes choses. Si vous additionnez toutes les fonctionnalités utiles de tous les bons langages de programmation, vous obtiendrez un très gros gâchis, bien pire que C ++, même si vous pouvez éviter l'incohérence.

Les fonctionnalités ne sont pas gratuites. Si une langue a une fonctionnalité, les gens sont susceptibles de l'utiliser. Vous ne pourrez pas apprendre assez bien C # sans apprendre les nouvelles routines de gestion de la mémoire manuelle C #. Les équipes de compilateur vont la mettre en œuvre, au prix des autres fonctionnalités du compilateur utiles. La langue est susceptible de devenir difficile à analyser comme C ou C ++, ce qui conduit à une compilation lente. (En tant que gars C ++, je suis toujours étonné quand je compile l'un de nos projets C #. La compilation semble presque instantanée.)

Les caractéristiques sont en conflit les uns avec les autres, parfois de manière inattendue. Le C90 ne peut pas faire aussi bien que FORTRAN aux calculs de matrice, car la possibilité que les pointeurs soient aliasés empêchent certaines optimisations. Si vous autorisez l'arithmétique du pointeur dans une langue, vous devez accepter ses conséquences.

Vous suggérez une extension C # pour permettre la gestion de la mémoire manuelle, et dans quelques cas, ce serait utile. Cela signifierait que la mémoire devrait être allouée de manière distincte, et il faudrait que la mémoire soit gérée manuellement à partir de la mémoire gérée automatiquement. Soudain, vous avez compliqué la gestion de la mémoire, il y a plus de chances pour un programmeur de bousiller, et le gestionnaire de mémoire lui-même est plus compliqué. Vous gagnez un peu de performance qui compte dans quelques cas en échange de plus de complications et de gestion de la mémoire plus lente dans tous les cas.

Il se peut qu'à un moment donné, nous aurons un langage de programmation qui est bon à presque toutes les fins, des scripts au craquement des chiffres, mais il n'y a rien de populaire qui se trouve à proximité. En attendant, nous devons être disposés à accepter les limites de l'utilisation d'une seule langue, ou du défi d'en apprendre plusieurs et de basculer entre eux.

Dans l'exemple que vous avez publié, pourquoi ne pas simplement effacer le tampon et le réutiliser?

Le collecteur de déchets .NET est très très bon pour déterminer quels objets ne sont plus référencés et libérer la mémoire associée en temps opportun. En fait, le collecteur de ordures a un tas spécial (le grand tas d'objet) dans lequel il place de gros objets comme celui-ci, qui est optimisé pour les traiter.

En plus de cela, ne pas permettre de libérer explicitement les références supprime simplement une foule de bugs avec des fuites de mémoire et des pointeurs pendants, ce qui conduit à un code beaucoup plus sûr.

La libération de chaque bloc inutilisé individuellement comme dans une langue avec une gestion explicite de la mémoire peut être plus coûteuse que de laisser un collecteur de déchets le faire, car le GC a la possibilité d'utiliser des schémas de copie pour passer un temps linéaire au nombre de blocs laissés en vie (ou le nombre de blocs récents laissés vivants) au lieu d'avoir à gérer chaque bloc mort.

La même raison pour laquelle la plupart des grains ne vous permettreont pas de planifier vos propres fils. Parce que 99,99 +% du temps, vous n'avez pas vraiment besoin, et exposer cette fonctionnalité, le reste du temps ne fera que vous faire quelque chose de potentiellement stupide / dangereux.

Si vous avez vraiment besoin d'un contrôle de mémoire à grains fins, écrivez cette section de code dans autre chose.

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