sont des compilateurs tels que Javac assez intelligents pour détecter quand une méthode est une fonction pure.
Il ne s'agit pas de "suffisamment intelligent". C'est ce qu'on appelle l' analyse de pureté et cela est impossible dans le cas général: cela équivaut à résoudre le problème de l'arrêt.
Maintenant, bien sûr, les optimiseurs font des choses prouvablement impossibles tout le temps, "prouvablement impossible dans le cas général" ne signifie pas qu'il ne fonctionne jamais, cela signifie seulement qu'il ne peut pas fonctionner dans tous les cas. Donc, il existe en fait des algorithmes pour vérifier si une fonction est pure ou non, c'est juste que le plus souvent le résultat sera "je ne sais pas", ce qui signifie que pour des raisons de sécurité et d'exactitude, vous devez supposer que cette fonction particulière pourrait être impure.
Et même dans les cas où elle exerce ses travaux, les algorithmes sont complexes et coûteux.
C'est donc le problème n ° 1: cela ne fonctionne que pour des cas spéciaux .
Problème n ° 2: bibliothèques . Pour qu'une fonction soit pure, elle ne peut appeler que des fonctions pures (et ces fonctions ne peuvent appeler que des fonctions pures, et ainsi de suite). Javac ne connaît évidemment que Java et ne connaît que le code qu'il peut voir. Donc, si votre fonction appelle une fonction dans une autre unité de compilation, vous ne pouvez pas savoir si elle est pure ou non. S'il appelle une fonction écrite dans une autre langue, vous ne pouvez pas le savoir. S'il appelle une fonction dans une bibliothèque qui n'est peut-être même pas encore installée, vous ne pouvez pas le savoir. Etc.
Cela ne fonctionne que lorsque vous avez une analyse complète du programme, lorsque le programme entier est écrit dans la même langue et que tout est compilé en une seule fois. Vous ne pouvez utiliser aucune bibliothèque.
Problème n ° 3: planification . Une fois que vous avez déterminé quelles parties sont pures, vous devez toujours les planifier sur des threads séparés. Ou pas. Le démarrage et l'arrêt des threads sont très coûteux (en particulier en Java). Même si vous conservez un pool de threads et ne les démarrez pas ou ne les arrêtez pas, le changement de contexte de thread est également coûteux. Vous devez être sûr que le calcul s'exécutera beaucoup plus longtemps que le temps nécessaire pour planifier et changer de contexte, sinon vous perdrez les performances, pas les gagnerez.
Comme vous l'avez probablement deviné maintenant, déterminer combien de temps un calcul prendra est impossible dans le cas général (nous ne pouvons même pas déterminer si cela prendra un temps fini, sans parler du temps) et difficile et coûteux même dans le cas particulier.
A côté: Javac et optimisations . Notez que la plupart des implémentations de javac n'effectuent pas réellement beaucoup d'optimisations. La mise en œuvre d'Oracle de javac, par exemple, repose sur le moteur d'exécution sous-jacent pour effectuer des optimisations . Cela conduit à un autre ensemble de problèmes: disons, javac a décidé qu'une fonction particulière est pure et elle est assez chère, et donc elle la compile pour être exécutée sur un thread différent. Ensuite, l'optimiseur de la plate-forme (par exemple, le compilateur HotSpot C2 JIT) arrive et optimise l'ensemble de la fonction. Maintenant, vous avez un fil vide qui ne fait rien. Ou, imaginez, encore une fois, javac décide de planifier une fonction sur un autre thread, et l'optimiseur de plateforme pourrait optimisez-le complètement, sauf qu'il ne peut pas effectuer d'inlining au-delà des limites de thread, et donc une fonction qui pourrait être complètement optimisée est maintenant exécutée inutilement.
Donc, faire quelque chose comme ça n'a de sens que si vous avez un seul compilateur effectuant la plupart des optimisations en une seule fois, afin que le compilateur connaisse et puisse exploiter toutes les différentes optimisations à différents niveaux et leurs interactions les unes avec les autres.
Notez que, par exemple, le compilateur JIT HotSpot C2 effectivement fait effectuer une auto-vectorisation, qui est aussi une forme d'auto-parallélisation.