Quelle est la meilleure façon d'initialiser NSMutableString objet?
Si je prends une question suivante. Quelle est la meilleure façon d'initialiser NSMutableString Classe?
(Tous les cas, le retour à des moments inattendus... donc je vais supposer que l'initialisation comme suit:)
- Si je sais à l'avance la quantité de travail. ( attendue )
NSMutableString *str1 = [NSMutableString stringWithString:@""]; NSMutableString *str2 = [NSMutableString stringWithCapacity:0]; NSMutableString *str3 = [NSMutableString stringWithCapacity:1000]; NSMutableString *str4 = [NSMutableString string]; for(int i = 0; i< 1000; i++) { //The following tasks.(Adding to the string to continue working.) [/*str1~str4*/ appendFormat:@"%d", i]; }
- Si je ne sais pas à l'avance la quantité de travail. ( inattendue )
NSMutableString *str1 = [NSMutableString stringWithString:@""]; NSMutableString *str2 = [NSMutableString stringWithCapacity:0]; NSMutableString *str3 = [NSMutableString stringWithCapacity:1000]; NSMutableString *str4 = [NSMutableString string]; for(int i = 0; i< /*a large of size(unpredictable)*/ ; i++) { //The following tasks.(Adding to the string to continue working.) [/*str1~str4*/ appendFormat:@"%d", i]; }
Divisent principalement en deux lors de l'exécution de ces tâches, Quelle est la meilleure façon d'initialiser?
Je parfois, lorsque vous travaillez avec ces tâches est également source de confusion.
OriginalL'auteur bitmapdata.com | 2011-12-26
Vous devez vous connecter pour publier un commentaire.
Cas 1
Des options de la liste, je ne l'utiliserais:
...si vous connaissez la destination de la taille, ou d'estimer avec un peu de marge en haut et sont en mesure de rapidement déterminer la taille exacte, ou la taille de scénario du pire des cas, cela pourrait sauver plusieurs réaffecter et les opérations de copie. Si vous ne connaissez pas la taille dans le pire des cas, ou si elle prend beaucoup de temps à calculer, alors vous pourriez aussi bien utiliser
[NSMutableString string]
ou[NSMutableString new]
. Aussi,*WithCapacity
est un indice, dont les cadres sont libres d'ignorer.Bien sûr, le corps de la boucle et de la taille que vous réserve implique aussi que toutes les valeurs sont [0...9] (en particulier, que toutes les valeurs de consommer un seul personnage), et vous pourriez dans ce cas probablement faire beaucoup mieux en utilisant des chaînes de format avec plus d'arguments. Cependant,
i
est évidemment plus grand que 9, pour la plupart des itérations, et consomment en moyenne 3 caractères, donc 3000 serait plus approprié de capacité de réserve pour exactement le code que vous avez posté.Cas 2
Des options de la liste, je ne l'utiliserais:
Mieux encore, si vous n'avez pas besoin de l'ajouter à un autorelease pool:
[NSMutableString new]
ou[[NSMutableString alloc] init]
.Autres Notes
Oui, gardant les objets de autorelease piscines (par exemple l'utilisation des alloc+init) peut améliorer les performances et de réduire le pic de l'utilisation de la mémoire de manière significative. Parfois, c'est au-delà de votre contrôle, et dans certains environnements (par exemple, à l'ARC), cela peut se produire même si vous utilisez un autoreleased commodité de constructeur par exemple
[NSMutableString string]
.La Solution Plus Rapide
Enfin, si c'est le cas que vous avez décrite est vraiment un souci de performances, le moyen le plus rapide serait de créer un
char
de tampon sur la pile, puis de créer unNSString
à partir du résultat de la copie de l'un des numéros sur lachar
tampon. En supposant que votreint
s sont tous les chiffres de 0 à 9, il serait très rapide et très facile, il suffit ensuite de créer unNSString
de l' (fin) cstring. Vous pouvez même le faire si la taille de saisie varie, ou est très grand (résultats dans une très longue chaîne).@autoreleasepool
bloquer manuellement et de libérer à la fin de la portée ne doit pas être tout ce que beaucoup. Donc, sauf si vous êtes émaillant communiqués au moyen de votre code (ce qui ne veut libérer de la mémoire plus rapidement, mais IMO il est plus difficile de voir si vous avez sorti), je suis sceptique à propos de la différence dans la plupart des cas. Par curiosité, avez-vous des chiffres à ce sujet?c'est, toutefois, ne sont pas typiques du monde réel de l'exécution des très très peu de développeurs de créer explicitement autorelease piscines régulièrement (au-delà de l'entrée d'un nouveau thread/programme). ainsi les piscines et les dépendances des objets deviennent des grandes souvent de. il y a également un certain nombre de facteurs qui réduisent les performances, ce n'est pas simplement le nombre d'allocations. la croyance que l'on peut/doit être insensible à ce que "le système gère de manière efficace, et automatiquement" conduit à des problèmes (suite)
(suite) pas contrairement à objc la collecte des ordures activité nécessitant un important montant d'un processus de temps CPU (un exemple réel à partir d'OS X). et oui, j'ai largement optimisé un certain nombre de programmes de cacao. la position courte est: explicitement contrôler et réduire objets de la durée de vie, en utilisant immuable types dans les endroits appropriés, etc. peut faire l'exécution d'un programme, quelques fois plus rapide. un lien existe dans Rickay du post (qui vous ont également commenté, donc... j'aurais cru que vous l'avez vu).
Je suis juste sceptique qu'il n'est pas exagéré, la plupart du temps. Le lien dans Rickay post affirme que c'est une optimisation et montre comment le faire. Il ne dit pas quand et à quel point c'est mieux que de l'utilisation judicieuse de autorelease piscines. Il recommande également
allocWithZone:
et un peu douteux de la mise en œuvre de l'objet de piscines. De toute façon, si vous avez construit un objet très complexe graphique avec des références à l'extérieur de la portée locale, le vraiment n'a pas d'importance qui libèrent la méthode que vous utilisez, parce que ces objets ne sont pas arriver dealloced immédiatement, peu importe comment vous les relâchez.il semble que vous êtes le choix de rester sceptique. et que le dernier bit de votre commentaire est faux, car un bon nombre d'objets transitoires sont créés dans la plupart des cas, leur destruction peut se produire plus tôt et leur mémoire peut être retourné plus tôt. Donc, disons que vous construisez quelque chose de complexe, comme une fenêtre ou d'un complexe de vue, est-il temporaire, autoreleased les objets qui sont créés qui n'ont pas besoin d'être ajouté à autorelease piscines et n'ont pas besoin de vivre au-delà de la portée dans laquelle ils sont attribués? sûrement.
OriginalL'auteur justin
Il n'a pas vraiment d'importance.
Si vous avez optimisé votre programme jusqu'à ce que cette décision aura un effet mesurable sur la performance globale, vous tape dans le dos ou, comme Sheldon de TBC dirais, "chocolat!"
PS:
Si vous savez la taille à l'avant ou à avoir une très bonne estimation sur elle, puis utiliser cette taille dans
stringWithCapacity:
ouinitWithCapacity:
si vous ne le faites pas, alors ne même pas la peine — laissez-le cadre de décider, c'est sacrément intelligent!__CFStrNewCapacity()
dans opensource.apple.com/source/CF/CF-635/CFString.c). Mais ce n'est généralement pas un endroit que vous devriez être en essayant d'optimiser. Si vous êtes à la création ainsi que de nombreuses chaînes que cette matière, vous obtiendrez de meilleures performances par la réutilisation de votre chaîne objets que sur l'optimisation de leur création.+1 pour la TEMPÉRATURE de référence!
OriginalL'auteur danyowdee
Ici est le chemin le plus court:
OriginalL'auteur Vahan
Mauvais, un NSString (@"") est inutilement créé, puis copiés dans un nouveau NSMutable Chaîne
Mauvais, un NSMutableString avec 0 de la capacité doivent être gonflés à la première plus de.
Bon, si 1000 a une certaine importance (c'est à dire qu'il attend de la taille du contenu que vous travaillez).
Bon, à l'aide d'une méthode de convenance, qui est comme faire de la
[NSMutableString alloc] init];
OriginalL'auteur Alexander
Si vous connaissez la taille à l'avance, utiliser
Si vous ne connaissez pas la taille à l'avant, utilisez
Puis la mutable chaîne de grandir comme il faut.
OriginalL'auteur Rayfleck
Il est toujours préférable d'allouer et initialiser un objet, de ne pas utiliser une méthode de classe pour le créer (ce qui la met dans le plus proche de l'autorelease pool).
Donc,
au lieu de
N'oubliez pas que vous devez libérer stringOne lorsque vous avez fini avec elle, mais pas stringTwo, parce que le stringWithCapacity: méthode de classe renvoie un autoreleased objet.
Lire plus sur le sujet ici: http://www.mulle-kybernetik.com/artikel/Optimization/opti-5.html
En quoi est
stringOne
mieux questringTwo
?Ce n'est pas "mieux", mais en terme de performance il est plus efficace d'allouer manuellement et libération de la mémoire vous-même. Il est un peu plus de code, mais il est préférable si vous allez consacrer beaucoup de chaînes.
OriginalL'auteur eric.mitchell