Petite étude: vitesse d'exécution de ibtool
tablier
Membre
exécution-> pendu tout les matins sous les bras jusqu'à ce que mort s'en suive!
Trêve de plaisanterie, J'ai des commandes du genre de celle ci-dessous à exécuter:
Donc, je dois faire une erreur monumentale et j'aimerais bien savoir laquelle!
Trêve de plaisanterie, J'ai des commandes du genre de celle ci-dessous à exécuter:
Developer/usr/bin/ibtool --export-strings-file /Users/msaro/AS/Main.strings /Users/msaro/AA/Main.nib
J'ai commencé par utiliser AppleScript:
- (NSString *)doExecScript:(NSString *)commande<br />{<br />NSDictionary *infoErreur ;<br /><br /> NSAppleScript *monScript = [[NSAppleScript alloc] initWithSource:commande] ; <br /> [monScript compileAndReturnError:&infoErreur] ;<br /> NSAppleEventDescriptor *descripteur = [monScript executeAndReturnError:&infoErreur] ;<br /> [monScript release];<br /> if (descripteur == nil)<br /> return [NSString stringWithString:[infoErreur objectForKey:@"NSAppleScriptErrorMessage"]] ;<br /> else<br /> return @"" ;<br />}
ça marche, mais c'est lent!! je suis donc passé à un appleEvent:
- (NSString *)doEventIbtool:(NSString *)commande<br />{<br />OSErr err = noErr ; <br />AppleEvent toolEvent, reponse ;<br />char commnd[512] ;<br /><br /> strcpy(commnd, [commande UTF8String]) ;<br /> err = AEBuildAppleEvent('syso','exec', typeProcessSerialNumber, &locProcess, sizeof(locProcess), <br /> kAutoGenerateReturnID, kAnyTransactionID, &toolEvent, NULL, "'----':TEXT(@)",commnd ) ;<br /> if (err == noErr)<br /> { err = AESendMessage (&toolEvent, &reponse, kAEWaitReply | kAECanInteract , kAEDefaultTimeout) ;<br /> (void) AEDisposeDesc(&toolEvent);<br /> // ici, traitement de la réponse -------------<br /> (void) AEDisposeDesc(&reponse);<br /> } ;<br /> return @"" ;<br />}
ça marche et c'est plus rapide. Pour comparer, j'ai voulu utiliser NSTask:
- (NSString *)doShellTask<br />{<br /> NSArray *table = [NSArray arrayWithObjects:@" --export-strings-file", @"/Users/msaro/AS/Main.strings", <br /> @"/Users/msaro/AA/Main.nib", nil ] ;<br /> NSTask *tache = [[NSTask alloc] init] ; <br /> [tache setLaunchPath:@"Developer/usr/bin/ibtool "] ;<br /> [tache setArguments:table] ; <br /> NSPipe *pype = [NSPipe pipe] ;<br /> [tache setStandardOutput: pype] ;<br /> NSFileHandle *fich = [pype fileHandleForReading] ;<br /><br /> [tache launch]; <br /> [tache waitUntilExit];<br /><br /> NSData *data = [fich readDataToEndOfFile] ;<br /> NSString *string = [[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding] ;<br /> [string release] ;<br /> [tache release] ;<br /> return @"" ;<br />}
Alors là , rien ne marche!! J'ai estimé qu'ibtool créait directement le fichier de sortie sans passer par la sortie standard. J'ai donc supprimé le pipe, le filehandle et le string final. Pas de différence, ça ne marche pas!Donc, je dois faire une erreur monumentale et j'aimerais bien savoir laquelle!
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
- Enlève l'espace à la fin du launchPath que tu mets à ta task
- Donne le bon chemin au launchPath de ta task (avec un "/" devant, sinon c'est pas un chemin absolu mais relatif au working directory qui doit être dans le contexte d'une NSTask un truc comme ton HomeFolder ou encore l'endroit du bundle de ton appli... bref normal qu'il ne trouve pas l'exécutable ibtool)
Si ça ne marche toujours pas, rajoute un pipe (éventuellement le même) à ta task pour setStandardError pour y récupérer la sorti de stderr (en plus de la sortie de stdout que tu récupères déjà par setStandardOutput) car s'il y a une erreur à l'exécution, c'est dans stderr que tu pourras la lire et comprendre ainsi pourquoi ça ne marche pas.
PS : Reste une question : après cette réponse, si ça marche (et donc que c'était bien juste ces points la source de l'erreur), je me demande qui on doit exécuter finalement... :P
Timed out fetching data. Variable display may be inaccurate. et bien sur le NSTask ne marche pas.
Alors que si j'écris tout marche parfaitement et le NSTask fonctionne correctement!
Quelque chose m'échappe!!
Par contre rien à voir avec ton problème mais c'est quoi cette manie d'utiliser stringWithString et arrayWithArray qui ne servent à rien du tout et son des no-op (à part si tu passes une NSMutableString pour la faire devenir NSString ou un NSMutableArray pour générer un NSArray mais là c'est pas le cas alors bon :P)
je parlais de la sentinelle du tableau (nil)
Ben, dans mon exemple il y a des méthodes qui ne servent à rien, oui, oui!!
Je ne suis pas un expert dans le maniement de la ram aussi je pense (peut être à tord) qu'en ajoutant cela les variables "auto_released" ont leur compte qui augmente de 1.
Dans le cas qui m'occupe, la version finale commence par: ce qui doit être correct je pense, même si on peut se passer de "table". Et j'ai garder l'habitude de déclarer les variables en tête des routines, pardon des méthodes. ça reste plus clair pour moi.
Objective C -> NSTask 51 secondes
AppleScript -> do shell script .. 42 secondes
Carbon -> AEBuildAppleEvent('syso','exec' ... AESendMessage 38 secondes
Il me semble que sous 10.6, AppleScript a été amélioré et fonctionne nettement plus vite qu'avant.
Les AppleEvents sont plus rapides qu'AppleScript: c'est connu depuis longtemps.
Les commandes sont construites par mon programme et sont directement utilisables par AppleScript et par Carbon. Pour NSTask, le programme extrait les arguments de la commande complète, ce qui fait une étape supplémentaire et ce qui explique peut-être les 51 secondes avec NSTask.
Bien sur, ce type de comparaison n'est qu'indicative.
Une possibilité que je n'ai pas regardé serait d'écrire les 200 commandes à exécuter dans un fichier "shell-script" et de l'envoyer au shell pour exécution. Je ne sais pas si c'est possible, et le traitement des erreurs ne me parait pas évident.