Un Mac mini peut compiler plus vite qu'un Mac Pro

Nicolas Furno |

Le Mac Pro a beau être un produit honteusement abandonné par Apple, il reste le Mac le plus puissant actuellement sur le marché dès lors qu’une tâche utilise plusieurs cœurs. Avec son option à 12 cœurs physiques, il aligne 24 cœurs logiques qui peuvent être exploités dans certaines tâches très précises. C’est le cas, notamment, lors de la compilation d’une app. Le code source doit alors être converti en code machine et rassemblé pour former un paquet prêt à être ouvert par un appareil, une tâche lourde qui bénéficie de la puissance d’un Mac Pro.

Du moins, ça c’est la théorie. En pratique, les résultats ne sont pas du tout aussi logiques et c’est même l’inverse qui se produit. C’est ce qu’a remarqué un responsable de LinkedIn quand les développeurs de l’app iOS ont commencé à abandonner leurs Mac Pro à 12 cœurs pour utiliser des MacBook Pro. Interrogés, ils ont répondu que les portables équipés de quatre cœurs seulement étaient plus rapides pour compiler l’app.

Avantage du Mac Pro : il peut facilement être recyclé en corbeille à papier. Corbeille pour un seul papier néanmoins : même alors, il n’est pas très efficace… Cliquer pour agrandir

Pour en avoir le cœur net, ce responsable a mené des tests sur tous les Mac qu’il a pu trouver, y compris sur un Mac mini affiché à 1339 € avec l’option Core i7. À titre de comparaison, le Mac Pro avec l’option 12 cœurs est vendu au minimum 8199 €. Sur chaque machine, il a compilé l’app iOS de LinkedIn en utilisant de plus en plus de cœurs et le résultat est étonnant.

Le Mac Pro est effectivement l’ordinateur le plus lent pour mener à bien cette tâche, alors que c’est l’iMac le plus rapide. Ce dernier est un modèle de 2015 équipé d’un processeur Core i7 à quatre cœurs physiques et huit cœurs logiques. Même le Mac mini fait systématiquement mieux que le Mac Pro, dernier du classement quel que soit le nombre de cœurs.

Par défaut, il faut plus de 10 minutes pour que le Mac Pro compile l’app, là où quatre minutes environ suffisent à l’iMac. Un écart énorme qui s’explique a priori par un bug. Xcode peut exploiter autant de cœurs que l’ordinateur peut en fournir, mais contre toute attente, le processus n’est pas accéléré en multipliant les cœurs, il est ralenti.

Ce graphique affiche le temps nécessaire pour compiler l’application de LinkedIn en fonction du nombre de cœurs utilisés. Le Mac Pro (en rouge) est le seul à pouvoir monter jusqu’à 24 cœurs. En jaune, l’iMac est bloqué à huit cœurs, mais c’est lui le plus rapide. Cliquer pour agrandir

Précisons que ce n’est pas systématiquement le cas et les apps développées uniquement en Objective-C ne souffrent pas du même problème. C’est Swift qui semble être le coupable dans l’histoire et a priori plutôt la troisième version. Notre développeur iOS se plaint également de lenteurs à la compilation depuis le passage à Swift 3 à la fin de l’année.

Suite à cette découverte, ce cadre de LinkedIn a essayé d’isoler le problème en utilisant différentes versions de macOS, en compilant une app beaucoup plus légère et même en testant une compilation avec un système installé sur APFS. Mais rien n’y a fait, il a obtenu systématiquement les mêmes résultats, ce qui l’amène à la conclusion qu’il y a un bug, soit dans macOS, soit dans Xcode.

En attendant un correctif (un rapport de bug a été créé), les développeurs trouveront à la fin de l’article deux solutions temporaires pour améliorer les temps de compilation. Il s’agit déjà de bloquer le nombre de cœurs utilisés par Xcode, sachant que le meilleur étant 5 pour un Mac Pro et 6 à 8 pour les MacBook Pro et iMac à quatre cœurs. Ensuite, désactiver l’indexation Spotlight de certains dossiers diminue également légèrement le temps nécessaire à la compilation.

Compilation en cours dans Xcode. Cliquer pour agrandir

Apple présentera Swift 4 lors de sa conférence développeurs, au mois de juin. Espérons que ce problème de performances sera réglé avec cette mise à jour qui doit apporter la stabilité, au moins pour le code-source.

avatar pecos | 

Bigre !
oui, je connais ça aussi : le dev et la compilation pour Android sont (je trouve) considérablement plus laborieux qu'avec XCode pour iOS.
Surtout avec Eclipse sur des machines un peu vieilles.

Alors, effectivement, on code des fragments bien plus longs et on ne compile pas très souvent.

Ou alors pendant ce temps là on va nourrir le chat... se brosser les dents... arroser les fleurs... ouvrir un 5 ème coca ou un 3 ème paquet de tuc. :-(

Mais j'aime bien java aussi, quand même. ;-)

avatar bobdu87 | 

6250 lignes de code LOL
Moi je bosse sur un pauvre petit moteur 3D et le code se compte en dizaine de fois ce dont tu parles LOL...

avatar Rictusi | 

Lol pas trop vite s'il te plait, déjà il dit très bien que ce sont des petits projets.

Ensuite le nombre de ligne de code ne présage en rien de la qualité du code, au contraire, donc pour un "petit moteur 3D" tu me fais peur,( c'est facile de dénigrer sans rien voir hein ? )

Enfin j'ai aussi un projet avec 10 fois ce nombre de ligne, et tu sais quoi c'est incroyable ce qu'il raconte reste vrai, donc ce n'était vraiment pas la peine de venir ramener sa suffisance, juste souligner que ce qu'il raconte reste vrai sur des plus gros projets aurait déjà été pas mal.

Merci.

avatar BeePotato | 

@ pecos : « Si j'avais des apps pour iOS qui compilent en "plusieurs minutes", soit je jette l'ordi, soit je jette le code. »

Soit tu te félicites de travailler enfin sur une application un peu sérieuse. :-D

avatar pecos | 

C'est pourtant exactement le contraire, non ? à mon avis plus ça compile vite pour le même service rendu, plus le code est compact et bien conçu, mieux tu as fait ton boulot, et moins le complio est sollicité pour des conneries.

Et donc plus il va vite, CQFD.

Je me félicite donc plutôt d'avoir des apps qui compilent en 5 secondes.

Et je ne crois pas du tout que je serais content de travailler sur une app sérieuse si elle mettait juste beaucoup plus de temps à compiler que ce que j'écris. ;-)
Mais alors pas du tout.
Je crois plutôt que dans ce cas que je me livrerais à d'autres activités, ça vaudrait mieux.
Je suis pas maso, moi.

avatar patchoulol | 

@pecos

L'app LinkedIn est codée en Swift. Or la lenteur du compilateur Swift est un problème connu, sur lequel Apple travaille, en particulier lorsque Objective-C et Swift sont mêlés (ce qui est le cas ici).
Par ailleurs, tu peux être sûr que le nombre de lignes de code dans leur app est d'un ordre de grandeur supérieur à celui de ton app actuelle. Ce n'est pas qu'une question de qualité de code, c'est juste que son service rendu ne peut pas s'exprimer par 6000 lignes de code. Malgré cela, Swift garde énormément d'avantages, et tu devrais sincèrement envisager le switch depuis ObjC.

avatar BeePotato | 

@ pecos : « C'est pourtant exactement le contraire, non ? »

Ma remarque était à prendre comme une plaisanterie sur le fait de considérer qu’une application ne peut être dite « sérieuse » que si elle est grosse et complexe. Je n’ai peut-être pas mis assez de smileys pour que ce soit évident, désolé.

« à mon avis plus ça compile vite pour le même service rendu, plus le code est compact et bien conçu, mieux tu as fait ton boulot, et moins le complio est sollicité pour des conneries. »

Sauf que là, je ne faisais pas référence au même service rendu, mais au fait de travailler sur une application d’une toute autre taille (une application « sérieuse », quoi).
Il existe réellement de bonnes raison d’avoir des applications iOS dont le code source comprend des centaines de milliers, voire des millions, de lignes de code, hein.

Mais au delà de ça, non, même à service équivalent, un code plus compact ne signifie pas qu’il est mieux conçu. La qualité d’un code est généralement jugée selon deux critères :
• ses performances lorsqu’il est exécuté (qualité du point de vue de l’utilisateur) ;
• sa lisibilité et sa maintenabilité (qualité du point de vue du développeur).
Il y a bien sûr aussi le fait qu’il soit correct et non bourré de bugs, mais on peut lier ça aux deux critères ci-dessus.

Un code plus compact peut contribuer à améliorer la qualité selon l’un ou l’autre de ces critères, mais il peut tout aussi bien la dégrader.

La vitesse de compilation est quelque chose de bien moindre importance que les deux critères ci-dessus.

« Et je ne crois pas du tout que je serais content de travailler sur une app sérieuse si elle mettait juste beaucoup plus de temps à compiler que ce que j'écris. ;-) »

Chacun ses goûts.
Travailler sur une grosse application, c’est très différent mais ça peut être très sympa aussi.

avatar byte_order | 

> à mon avis plus ça compile vite pour le même service rendu,
> plus le code est compact et bien conçu, mieux tu as fait ton boulot,
> et moins le complio est sollicité pour des conneries.

Dans ce cas, autant développer uniquement en langage non compilé.
On a donc forcément la garantie que son code est bien conçu, puisque qu'il n'y a carrément pas de compilation.

Fort heureusement, le temps de compilation, la qualité du code et sa compacité n'ont pas grand chose à voir ensemble. Un compilateur qui tente toutes les implémentations possibles et fait des comparaisons statistiques pour choisir le meilleur, voir générer du code générant qu'au runtime l'implementation la plus adaptée ou, soyons fou, du code s'améliorant par boucle de feedback, les temps de compilation vont varier dans tous les sens, sans pouvoir affirmer que le plus rapide ou le plus lent seront le meilleur ou le pire, respectivement.

La qualité du code ne concerne pas que le compilateur. Elle concerne aussi les humains qui devront le lire et le faire évoluer.

On peut écrire du code C hyper compact, y'a même un concours chaque année (Fabrice Bellard, bien connu dans la profession, l'a gagné avec son Tiny C, un... compilateur C, justement, hyper compact mais pas pour autant ni le plus rapide ni le plus performant...) et avoir dedans un algo complètement inefficace.

> Et je ne crois pas du tout que je serais content de travailler sur une app sérieuse
> si elle mettait juste beaucoup plus de temps à compiler que ce que j'écris. ;-)

C'est dommage. Y'a des satisfactions au travail bien fait qui demande pourtant beaucoup de temps. L'optimisation d'un système d'exploitation, par exemple, où le moindre code refactoring internes pour booster ses performances générales un peu partout va engendrer un rebuild quasi complet de tout le code, sans pour autant changer quoi que ce soit à la surface.

C'est source de satisfaction, mais c'est impossible d'obtenir ce type de satisfaction en refusant des build cycles de 10 secondes max.

Et je pense qu'un système d'exploitation se classe parmi les "applications" sérieuses...

En ne considérant qu'une sorte de satisfaction immédiate, vous sous-estimez celle qui ne s’obtient uniquement qu'en y mettant du coeur, comme pour tout, mais également du temps.
Monter sa tente en 2 secondes c'est bien. Construire des cathédrales, cela peut être bien aussi. La satisfaction vient de la valeur qu'on donne au résultat.

Pondre rapidement une application mauvaise donnera aussi peu de satisfaction que mettre une plombe une application mauvaise, pour être clair.

avatar gavroche68 | 

Encore des pro qui n'ont rien compris ! C'est un iPad pro qu'il aurait fallu pour compiler, c'est l'avenir !

avatar wiwitop | 

Avec instruments on peut modifier le nombre de coeurs d'un Mac et par exemple ne garder que les coeurs physiques. je l'utilise quand je joue et que je veux réduire la chauffe de mon macbook pro (en plus d'une désactivation du turbo boost).

avatar byte_order | 

Par ailleurs :

> une tâche lourde qui bénéficie de la puissance d’un Mac Pro.

La compilation jusqu'à présent (C, C++, ObjectiveC pour ceux que je connais) n'est pas vraiment une tâche "lourde" en terme de "calcul". Cela fait longtemps que l'on sait que, statistiquement, une compilation est plus limitée par les I/O (les écritures en particulier) que le calcul du code à générer, les technos des compilateurs pour ces langages étant depuis longtemps arrivées à maturité.

On gagne alors du temps a trouver le strict nécessaire à régénérer et à linker, via de meilleurs outils de résolution de dépendance (ninja par exemple) et d'édition de lien incrémental (gold, par exemple).

On gagne évidement beaucoup de temps également à migrer sur des médias de stockage hyper performant, genre les derniers SSD sur PCIe.

Mais force est de constater que la compilation du dernier né des langages compilables, Swift, est visiblement nettement plus consommateur (ou non encore optimisé, selon les points de vu). Et cela se voit donc quand un core de CPU est moins capable de monter dans les tours que celui d'un autre CPU. Ici, un Xeon vs un i7 avec TurboBoost (boost qui convient parfaitement à ce type d'usage d'ailleurs, des pics assez court mais fréquent de besoin de perf de calcul).

avatar BeePotato | 

@ byte_order : « La compilation jusqu'à présent (C, C++, ObjectiveC pour ceux que je connais) n'est pas vraiment une tâche "lourde" en terme de "calcul". Cela fait longtemps que l'on sait que, statistiquement, une compilation est plus limitée par les I/O (les écritures en particulier) que le calcul du code à générer, les technos des compilateurs pour ces langages étant depuis longtemps arrivées à maturité. »

Ben quand même, ça représente pas mal de boulot pour le CPU, surtout qu’on n’arrête pas de compliquer la phase d’optimisation.

« On gagne évidement beaucoup de temps également à migrer sur des médias de stockage hyper performant, genre les derniers SSD sur PCIe. »

Tu as vraiment observé ça ?!?
Les fichiers manipulés étant ridiculement petits, ça me surprend.

avatar pecos | 

Je sais pas, mais effectivement, je n'ai pas constaté de changements profonds en terme de vitesse de compilation quand je suis passé du HD au SSD, voilà quelques années.

Il est vrai que pour des apps pour iOS, on ne voit peut-être pas la différence ?
Je n'ai jamais eu à compiler de très grosses applis pour mac par exemple.

avatar BeePotato | 

@ pecos : « Je sais pas, mais effectivement, je n'ai pas constaté de changements profonds en terme de vitesse de compilation quand je suis passé du HD au SSD, voilà quelques années. »

Pour du code de la taille que tu as évoquée précédemment (quelques milliers de lignes), rien ne fera une différence vraiment notable sur les machines actuelles.

avatar bobdu87 | 

LOL la compilation sur SSD est infiniment plus rapide que sur HDD (sauf quand on utilise la solution de MS LOL, le compilo le plus catastrophique de la terre)

avatar BeePotato | 

@ bobdu87 : « LOL la compilation sur SSD est infiniment plus rapide que sur HDD »

La compilation de quoi ?
Il y a des langages plus triviaux que d’autres à compiler, et dans ce cas évidemment le temps passé à faire des entrées/sorties peut vite compter autant, voire plus, que le temps de calcul dans le total. Mais ce n’est pas généralisable à tout, en parlant juste de « la compilation ».

(ah, j’ai oublié d’ajouter : « LOL » ;-) )

avatar byte_order | 

@BeePotato
> « On gagne évidement beaucoup de temps également à migrer sur des
> médias de stockage hyper performant, genre les derniers SSD sur PCIe. »
>
> Tu as vraiment observé ça ?!?
> Les fichiers manipulés étant ridiculement petits, ça me surprend.

Leur taille est faible en moyenne, oui, mais quand le nombre de fichiers manipulés augmente vraiment, oui, le cache ne pouvant plus jouer à plein, on retombe alors sur les performances des IO physiques, et elles sont clairement meilleurs avec un SSD.

Vécu avec des build de WebKit et des builds de OpenVTK et Boost.

avatar fte | 

Il peut s'agir d'un bug de scaling multicoeur, il peut s'agir d'optimisations ciblées sur les MacBook - dont le mini partage l'architecture -, ou d'autre chose.

Dans tous les cas on peut se demander si Apple a seulement testé correctement sur Mac Pro, si Apple en a encore quelque chose à faire du Mac Pro, ou si Apple a juste décidé que ça ne valait pas la peine d'investir du temps pour rectifier un soucis sur une machine que si peu de monde achète encore...

En tout cas en ce qui me concerne, je pense qu'Apple s'en fout complètement. Je prend ça comme un indice supplémentaire que le Mac Pro est abandonné.

Je sais. Spéculation gratuite de ma part. J'aimerais presque avoir tord.

avatar Piezi | 

So what?

avatar BeePotato | 

« mais contre toute attente, le processus n’est pas accéléré en multipliant les cœurs, il est ralenti. »

C’est le raccourci que le gars de LinkedIn s’est laissé aller à utiliser au milieu de son article, mais ce n’est que ça : un raccourci.
En réalité, comme on peut l’observer sur les courbes reproduites ici, la compilation est bien accélérée en augmentant le nombre de threads… jusqu’à un certain point.

Ça semble être juste la manifestation d’un principe classique de la programmation parallèle : si on se contente d’augmenter le nombre de tâches exécutées en parallèle sans réfléchir à la quantité de travail que chacune aura à faire, on arrive à un point où les divers threads passent plus de temps à communiquer les uns avec les autres qu’à faire du travail utile — et du coup, le travail global est exécuté moins vite qu’avec moins de threads.
Le seuil au delà duquel ça se produit est évidemment variable, puisqu’il dépend de plusieurs facteurs :
• le type de traitement à effectuer (nécessitant plus ou moins de communication entre threads — la compilation en nécessite bien plus que d’autres tâches (de nombreux traitements d’images, par exemple) où les threads peuvent être quasiment indépendants les uns des autres) ;
• la façon dont le logiciel est écrit (on fait facilement de petites erreurs entraînant plus de communication que nécessaire) ;
• la quantité de données à traiter.
Il n’est pas étonnant que ce seuil soit différent entre une compilation de Swift et d’Objective C avec deux compilateurs différents.

Ce qui n’est pas de bol pour le Mac Pro, c’est qu’à en juger par les courbes présentées ici, ce seuil pour la tâche de compilation testée est à peu près à 6 threads. On peut voir que le MacBook Pro, lui aussi, compile moins vite au delà. Mais comme il n’utilise jamais plus de 8 threads à la fois, ça se remarque à peine sur sa courbe.
Le Mac Pro, lui, permet de tester plus à fond cet effet. :-)

Cela dit, la solution est simple : après avoir fait quelques test pour déterminer le seuil à ne pas dépasser pour les trucs qu’on compile d’habitude, on règle le nombre maximal de threads de compilation à cette valeur et voilà.
Vu que Xcode est un logiciel destiné aux développeurs, dont on peut s’attendre à ce qu’ils connaissent ce phénomène, le comprennent et s’y adaptent sans problème, il n’y a pas de souci.

avatar bobdu87 | 

make -j 16 chez moi :)
Mais bon linux et vrai machine pro ;)

avatar BeePotato | 

@ bobdu87 : « make -j 16 chez moi :) »

Ce à quoi je pourrais répondre « petit joueur » ou « perte de temps » selon ce que tu compiles.
Comme je l’ai déjà dit, il n’y a pas de valeur magique pour ça, puisque ça dépend de ce qu’on compile, sur quelle machine et avec quel compilateur.

« Mais bon linux et vrai machine pro ;) »

Manque plus qu’un utilisateur pro. :-P

avatar pocketalex | 

"Manque plus qu’un utilisateur pro"

Excellent ? ? ?

avatar Rictusi | 

Du beau matos que t'as là dis donc !?

avatar mk3d | 

MacGe joue à internet explorer. Heu c'est seulement maintenant que tu t'en rends compte?

avatar ovea | 

∀?☠️?

Pages

CONNEXION UTILISATEUR