web-dev-qa-db-fra.com

Fichiers mappés en mémoire et scénarios avec peu de mémoire

Comment la plate-forme iOS gère-t-elle les fichiers mappés en mémoire lors de scénarios avec peu de mémoire? Par scénario à faible mémoire, j'entends quand le système d'exploitation envoie la notification UIApplicationDidReceiveMemoryWarningNotification à tous les observateurs de l'application.

Nos fichiers sont mappés en mémoire à l’aide de +[NSData dataWithContentsOfMappedFile:] , la documentation indiquant:

Un fichier mappé utilise des techniques de mémoire virtuelle pour éviter de copier les pages du fichier dans la mémoire tant qu'elles ne sont pas réellement nécessaires.

Cela signifie-t-il que le système d'exploitation débloquera également les pages lorsqu'elles ne seront plus utilisées? Est-il possible de marquer les pages comme n'étant plus utilisées? Ces données sont en lecture seule si cela modifie le scénario. Et si nous utilisions mmap() directement? Cela serait-il préférable?

38
Sedate Alien

Les fichiers mappés en mémoire copient les données du disque en mémoire, page par page. Les pages inutilisées peuvent être échangées librement, de la même manière que toute autre mémoire virtuelle, sauf si elles ont été câblées dans la mémoire physique à l'aide de mlock(2). Le mappage de la mémoire permet de déterminer le contenu à copier du disque dans la mémoire et à quel moment dans le système d'exploitation.

Passer du niveau Foundation au niveau BSD pour utiliser mmap ne fera probablement pas beaucoup de différence, au-delà de rendre le code qui doit s'interfacer un peu plus maladroit.

19

(Ce n'est pas une réponse, mais ce serait une information utile.)

De @ID_AA_Carmack Tweet ,

@ID_AA_Carmack Les fichiers mappés sur la mémoire iOS sont-ils automatiquement désaffectés dans des conditions de mémoire insuffisante? (using + [NSData dataWithContentsOfMappedFile]??)

ID_AA_Carmack a répondu à cela,

@KhrobEdmonds Oui, c’est l’un des grands avantages de l’utilisation de fichiers mappés sur iOS. J'utilise mmap (), cependant.

Je ne suis pas sûr que ce soit vrai ou pas ...

10
Kazuki Sakamoto

D'après mes expériences, NSData ne répond pas aux avertissements de mémoire. J'ai testé en créant un NSData mappé en mémoire et en accédant à des parties du fichier pour qu'il soit chargé en mémoire, puis en envoyant des avertissements de mémoire. L'utilisation de la mémoire n'a pas diminué après l'avertissement de mémoire. Rien dans la documentation n'indique qu'une mémoire amènera NSData à réduire l'utilisation réelle de la mémoire dans les situations de mémoire insuffisante, de sorte que cela m'amène à penser qu'elle ne répond pas aux avertissements de mémoire. Par exemple, la documentation de NSCache indique qu'elle essaiera de jouer à Nice en ce qui concerne l'utilisation de la mémoire. On m'a dit qu'elle répondait aux avertissements de faible mémoire émis par le système. 

Également lors de mes tests simples sur un iPod Touch (4e génération), j'ai été capable de mapper environ 600 Mo de données de fichiers dans la mémoire virtuelle, utilisez +[NSData dataWithContentsOfMappedFile:]. Ensuite, j'ai commencé à accéder aux pages via la propriété bytes sur l'instance NSData. Comme je l'ai fait, cette mémoire réelle a commencé à croître, mais elle a cessé de croître à environ 30 Mo d'utilisation réelle de la mémoire. La façon dont il est mis en œuvre semble donc limiter la quantité de mémoire utilisée. 

En bref, si vous souhaitez réduire l'utilisation de la mémoire des objets NSData, le mieux est de vous assurer qu'ils sont complètement libérés et que rien ne repose sur ce que le système fait automatiquement pour vous.

7
Evan

Si iOS est comme n'importe quel autre Unix - et je parierais que c'est de l'argent - les pages d'une région mmap () ne sont pas "remplacées"; ils sont simplement supprimés (s'ils sont propres) ou écrits dans le fichier sous-jacent, puis supprimés (s'ils sont sales). Ce processus s'appelle "expulser" la page.

Puisque votre carte mémoire est en lecture seule, les pages seront toujours propres.

Le noyau décidera quelles pages expulser lorsque la mémoire physique devient serrée.

Vous pouvez indiquer au noyau quelles pages vous préféreriez conserver/supprimer en utilisant posix_madvise () . En particulier, POSIX_MADV_DONTNEED indique au noyau de se sentir libre d'expulser les pages; ou comme vous le dites, "marquez les pages comme n'étant plus utilisées".

Il devrait être assez simple d'écrire des programmes de test pour voir si iOS respecte l'indicateur "pas besoin". Comme il est dérivé de BSD, je parie que ce sera le cas.

3
Nemo

Les techniques de mémoire virtuelle standard pour la mémoire sauvegardée sur fichier indiquent que le système d'exploitation est libre de jeter les pages à tout moment, car il peut toujours les récupérer plus tard. Je n'ai pas utilisé iOS, mais le comportement de la mémoire virtuelle sur de nombreux autres systèmes d'exploitation existe depuis longtemps.

Le moyen le plus simple de le tester consiste à mapper plusieurs fichiers volumineux dans la mémoire, à les lire pour garantir leur mise en mémoire, et à voir si vous pouvez forcer une situation de mémoire insuffisante. Si vous ne pouvez pas le faire, le système d’exploitation doit désamorcer les pages une fois qu’il a été décidé qu’elles ne seraient plus utilisées.

1
btilly

La méthode dataWithContentsOfMappedFile: est maintenant déconseillée à partir de iOS5.

Utilisez mmap pour éviter ces situations.

0
jarryd