Невозможность модификации встроенных классов[править | править код]
По сравнению с Ruby и некоторыми другими языками, в Python отсутствует возможность модифицировать встроенные классы, такие, как int, str, float, list и другие, что, однако, позволяет Python потреблять меньше оперативной памяти и быстрее работать. Ещё одной причиной введения такого ограничения является необходимость согласования с модулями расширения. Многие модули (в целях оптимизации быстродействия) преобразуют Python-объекты элементарных типов к соответствующим Си-типам вместо манипуляций с ними посредством Си-API. Также это избавляет от многих потенциальных ошибок при неконтролируемом динамическом переопределении встроенных типов.
Глобальная блокировка интерпретатора (GIL)[править | править код]
Основная статья: Global Interpreter Lock
Интерпретатор Python в CPython, Stackless и PyPy использует потоко-небезопасные данные, во избежание разрушения которых при совместной модификации из разных потоков применяется глобальная блокировка интерпретатора — GIL (Global Interpreter Lock): в ходе исполнения кода поток интерпретатора блокирует GIL, выполняет некоторое количество инструкций (по умолчанию 100), после чего освобождает блокировку и приостанавливается, давая возможность работать другим потокам. GIL также освобождается во время ввода-вывода, изменения и проверки состояния синхронизирующих примитивов, при исполнении кода расширений, не обращающихся к данным интерпретатора, например, NumPy/SciPy. Таким образом, в каждый момент времени в одном процессе интерпретатора Python может исполняться только один поток кода на Python, независимо от числа доступных процессорных ядер.
Потери производительности от GIL зависят от характера программ и архитектуры системы. Большинство программ являются однопоточными либо запускают всего несколько потоков, из которых часть в каждый конкретный момент простаивает в ожидании; персональные компьютеры обычно имеют не более четырёх процессорных ядер, которые загружены параллельно исполняющимися в системе процессами, так что реальные потери производительности из-за GIL невелики. Но в серверных приложениях может быть удобно использовать десятки и сотни (а то и больше) параллельных потоков (например, в системах массового обслуживания, где каждый поток обрабатывает данные для отдельного пользовательского запроса), а сервера на конец 2010-х годов нередко имеют десятки и даже сотни процессорных ядер, то есть технически могут обеспечить этим потокам физически одновременное исполнение; в таких условиях GIL может приводить к действительно значительному снижению общей производительности, так как лишает программу возможности полноценно использовать ресурсы многоядерных систем.
Ведётся работа по оптимизации GIL[67][68]. Отказ от GIL в ближайшем будущем не планируется, так альтернативные механизмы на однопоточных приложениях, которых большинство, работают медленнее или потребляют больше ресурсов:
Вариант интерпретатора с синхронизацией доступа к отдельным объектам вместо глобальной блокировки[69] из-за частых захватов/освобождений блокировок оказался слишком медленным.
python-safethread — CPython без GIL,[70] по утверждениям авторов, обеспечивает на однопоточных приложениях скорость порядка 60-65 % от скорости CPython.
Реализация потоков через процессы ОС, например, модуль processing[71] (с версии 2.6 переименован в multiprocessing). В UNIX-подобных системах накладные расходы при порождении процесса невелики, но в Windows использование процессов вместо потоков ведёт к существенному увеличению расхода оперативной памяти.
Отказ от совместного использования изменяемых данных и вызовов внешнего кода. При этом данные дублируются в потоках и их синхронизация (если таковая нужна) лежит на программисте[72]. Этот подход также увеличивает потребление оперативной памяти, хотя и не настолько сильно, как при использовании процессов в Windows.
Библиотеки обеспечивающие собственную организацию поддержки потоков, такие как parallelpython[73], pympi[74] и другие.
Радикальным вариантом решения проблемы может быть переход на Jython и IronPython, работающие на виртуальных машинах Java и .NET/Мono: эти реализации вообще не используют GIL.
Do'stlaringiz bilan baham: |