такі компілятори, як Javac, досить розумні, щоб виявити, коли метод є чистою функцією.
Це не питання "досить розумного". Це називається Аналіз чистоти і в загальному випадку неможливо: це рівнозначно вирішенню проблеми зупинки.
Тепер, звичайно, оптимізатори весь час роблять неможливо неможливі речі, "очевидно неможливо в загальному випадку" не означає, що він ніколи не працює, це означає лише, що він не може працювати у всіх випадках. Отже, є насправді алгоритми, щоб перевірити, чи функція чиста чи ні, просто частіше результат буде "я не знаю", це означає, що з міркувань безпеки та правильності потрібно припустити що ця конкретна функція може бути нечистою.
І навіть в тих випадках , коли він робить роботу, алгоритми є складними і дорогими.
Отже, це проблема №1: вона працює лише в особливих випадках .
Завдання №2: Бібліотеки . Для того, щоб функція була чистою, вона може коли-небудь викликати чисті функції (а ті функції можуть викликати лише чисті функції тощо) тощо. Javac, очевидно, знає лише Java, і він знає лише про код, який він може бачити. Отже, якщо ваша функція викликає функцію в іншому блоці компіляції, ви не можете знати, чи вона чиста чи ні. Якщо він викликає функцію, написану іншою мовою, ви не можете знати. Якщо він викликає функцію в бібліотеці, яка ще може бути навіть не встановлена, ви не можете знати. І так далі.
Це працює лише тоді, коли у вас є цілопрограмний аналіз, коли вся програма написана однією і тією ж мовою, і все складається відразу за один раз. Ви не можете використовувати жодну бібліотеку.
Завдання №3: Планування . Після того, як ви зрозуміли, які деталі є чистими, вам залишається запланувати їх, щоб вони розділили нитки. Чи ні. Запуск і зупинка потоків дуже дорога (особливо на Java). Навіть якщо ви зберігаєте пул потоків і не запускаєте і не зупиняєте їх, комутація контексту потоку також дорога. Ви повинні бути впевнені, що обчислення будуть працювати значно довше часу, необхідного для планування та переключення контексту, інакше ви втратите продуктивність, а не наберетеся.
Як ви, напевно, здогадувались, зрозуміти, як довго триватимуть обчислення, в загальному випадку неможливо (ми навіть не можемо розібратися, чи це займе обмежений час, не кажучи вже про те, скільки часу) і важко і дорого навіть у особливий випадок.
Убік: Javac та оптимізації . Зауважте, що більшість реалізацій javac насправді не виконують багато оптимізацій. Наприклад, реалізація javac Java Oracle покладається на базовий механізм виконання програм для оптимізації . Це призводить до ще одного набору проблем: скажімо, javac вирішив, що певна функція є чистою і досить дорогою, і тому вона компілює її для виконання в іншій нитці. Потім іде оптимізатор платформи (наприклад, компілятор HotSpot C2 JIT) і оптимізує всю функцію. Тепер у вас порожня нитка нічого не робить. Або, уявіть, знову ж таки, javac вирішує запланувати функцію на інший потік, і оптимізатор платформи міг би повністю оптимізувати його, за винятком того, що він не може виконувати вбудовані через межі потоку, тому функція, яку можна було б повністю оптимізувати, тепер непотрібно виконувати.
Отже, робити щось подібне дійсно має сенс, якщо у вас є один компілятор, який здійснює більшість оптимізацій за один раз, щоб компілятор знав про і міг використовувати всі різні оптимізації на різних рівнях та їх взаємодію між собою.
Слід зазначити , що, наприклад, компілятор HotSpot С2 JIT фактично робить виконувати деякі автоматичної векторизації, який також є однією з форм автоматичного розпаралелювання.