Comments 87
Подскажите, а в чем заключается цель использования и усложнения кода на python, если он вообще не про производительность? Почему для backend не использовать обычные и более подходящие языки типа Go/C#/etc?
Начинаете вы когда производительность не важна, а со временем она может стать важной. И перед вами выбор - переписать все на более быстрый язык, или добавить костылики внутри языка и увеличить скорость не переписывая. Для многих переписать все не вариант
Но почему выбирают именно python для работы над задачей, которая заведомо не будет про "производительность"? На том же C# сделать API вроде не настолько сложнее, чем на python.
Вы на старте не знаете нужна ли вам производительность - может через пол года ваш маленький проект умрет или всегда останется маленьким. При этом есть поверье, что на языках вроде Python, Ruby легче писать код с нуля за счет гибкости языка и библиотечек вроде рельсы или Джанго. Когда вы упретесь в производительность скорее всего будут ресурсы, как-то решить эту проблему
Ответил подробнее ниже
Ну с таким же успехом можно взять и PHP, где есть какой-нибудь Symfony, который даст форы и RoR, и Django, а по скорости можно выжать производительность уровня gcc -o2.
Так что, имхо, язык выбирается не по критериям "удобство"/"скорость"/"экосистема" и проч., а исключительно по двум:
У нас есть команда, которая знает язык Х (в 99% случаях непрофильный специалист взяв язык из другой области превратит его код в лютейший неподдерживаемый трешак)
И "потому что можем"
А у вас есть 100 программистов на питоне и один на С# - то есть на ранних стадиях выбирается питон, а потом оказывается что всё сделано и работает и переделывать никто не хочет. И на С# писать вообще безумие, я бы ещё понял C++, но это детали.
Почему безумие?
Чисто моё убеждение, основанное на представлении что C# это однозначно Windows - что для меня неприемлемо, а политика нашей страны вполне однозначно требует перехода на линукс (сейчас это не так и C# и пол линуксом работает, но этому "сейчас" всего несколько лет). А сам Microsoft решил сделать движение в Rust для Office364, да ещё и заявил что C# не под угрозой. Ну и пресловутый вендор-лок.
Ну с появлением .net core это уже неактуально. Честно не совсем понимаю о каком вендор-локе идет речь, можете пояснить?
Сразу скажу - на C# я не программирую.
.NET выпускается Microsoft.Тесно связана с другими проектами Microsoft. Это и есть вендор-лок. (страничка на гитхабе с моей точки зрения, не то на чём держится огромная экосистема). Веры в то, что система начавшая жизнь в windows будет работать в linux у меня очень мало. Да, я запускаю многие windows программы в linux, некоторые даже лучше работают.
Ну и количество открытых проектов на c# о которых я слышал равно нулю, в отличии от С++, Java и Питон - о чём то это говорит (ну может, конечно, и об узости моего кругозора или моей предметной области).
Это немного устаревшая информация. Можете посмотреть тут https://dotnet.microsoft.com/en-us/platform/open-source
Ну опенсурс, кто подписывается под выпуском очередной версии?
Это разве имеет такое большое значение для open source? Мне кажется, что очень хорошо, что такая большая компания развивает open source.
Имеет. C#, go это жёсткий вендор лок. Ими корпорация крутит как хочет. Причём не просто может, а делает. Посмотрите на яблоко - там все тоже, но быстрее.
Не совсем понимаю, в чём заключается "кручение"? В обычном open source владелец проекта может управлять разработкой, тот же Линус крутит как хочет. Можете привести пример?
Преимущества C# проявляются когда задействована инфраструктура Microsoft. А пока её нет, helloworld проще написать на питоне.
Когда C# сервер net core работает под linux, то какая инфраструктура Microsoft подразумевается? Для питона мне тоже runtime нужно установить.
можно подумать, что чистые опен-сорс проекты зависят от вашего мнения больше. точно так же возможны повороты разработки, просто они определятся не менеджерами майкрософта, а мантейнерами проекта. вы от этих решений далеки одинаково, а влияют они не слабее.
Просто вы, походу, мелкомягких не любите, и люди в посте тоже, субъективщина полнейшая, под linux на .NET писать не сложнее, на .NET Framework даже можно писать на linux, если нужен WinApi под линукс, используйте тот же Wine. А, вообще, если сраниваете C#, то сравнивайте с Java, что там, что там крупная корпорация за плечами -Microsoft и Oracle, только почему то в первом случае это плохо, а во втором хорошо.
Я не особо в C# разбираюсь, но я просто не вижу опенсорсных проектов на нём под Linux.
Проекты на Java я правил, не зная вообще Java - поэтому он мне ближе и я на практике убедился что читаемость java достаточна для работы.
Относительно C# - было бы здорово если бы кто то сравнил свой практический опыт разработки на C# под windows, возможно с сервисами Microsoft, и отдельно под linux без использования инфраструктуры Microsoft.
Вообще-то C# и Java - это языки кровавого энтерпрайза. Первая ссылка в гугл по запросу: "c# open source projects" https://www.reddit.com/r/csharp/comments/atyn3p/im_looking_on_open_source_c_projects_in_which_i/. Вот еще https://dev.to/echoglobal/top-10-c-open-source-projects-on-github-1dcl?ysclid=mgmphserep895973844. Ну и вот еще https://github.com/Unity-Technologies?ysclid=mgmpo380e5943356278
Какая инфраструктура Microsoft вас интересует? Azure? Дак и там на linux можно работать
Вы активно пишете на C# под linux?
Есть такое. Что вас конкретно интересует? Web-сервисы, desktop или что-то еще? У вас нет понимания, что такое .NET и что такое .NET Framework, отсуда все проблемы. Вот краткий лекбез https://stackoverflow.com/questions/76748330/differences-between-net-vs-net-core-vs-net-standard-vs-net-framework-and-res

Кстати, вы можете свою реализацию .NET написать, как в https://github.com/mono/mono?ysclid=mgmtb5jgxf454850511. Вот стандарт https://learn.microsoft.com/ru-ru/dotnet/fundamentals/standards
Я всегда воспринимал Microsoft как создателя экосистемы. Есть C#, есть Microsoft Office, SQL Server. Как подобная связка будет выглядеть под Linux?
Про nuget-пакеты почитайте https://learn.microsoft.com/ru-ru/nuget/what-is-nuget, https://www.nuget.org/packages
Я всегда воспринимал Microsoft как создателя экосистемы
когда то они в эту строну смотрели, лет 15 назад, сейчас уже совсем не так, Microsoft это не Apple, это Oracle или AT&T
Есть даже аналог VS для linux - VS Code, можете разрабатывать .NET приложения на самом линуксе, либо через терминал, кому как удобнее
Да, @WLMike прав. Зачастую, когда ты начинаешь свой небольшой проект - проще и быстрее взять язык, для которого много разных библиотек и на котором можно написать "быстро".
Затем ты выходишь на рынок и начинаешь это тестировать. И дальше, если мы говорим о каких-нибудь Pet проектах - проект так и останется маленьким. Или не найдёт свою аудиторию. Так будет в 80% случаев.
А если всё-таки проект вырастет - уже поздновато менять весь стек. Нужно расширять штат. А имеющийся штат только на Python пишет. Да и найти резработчиков - не просто. Поэтому выбирается путь думать об асинхронности и закидывать всё железом)
А если сразу писать всё на C# или чём-то производительном -проект может и не выйти. Или опоздать с моментом выхода. Тот же Golang, на который уходят с Python - сильно многословнее получается.
Но ведь даже в своем проекте "быстро" довольно относительно. Отладка в python довольно посредственная, работа с типами муторная и подвержена ошибкам, та же обработка ошибок потребует времени. Это всё как-то не похоже на "быстро", хотя, наверное в это вкладывается что-то другое. По наличию библиотек, скорее всего, — да, тут python будет лидировать. Тот же ChatGPT может сейчас довольно много всего написать рабочего. Но если речь про какой-нибудь backend, то и на других языках вроде нет проблем с различными библиотеками. В том же Visual Studio nuget пакеты ставятся в пару кликов.
Отладка в python просто замечательная
Почему не использовать Go? Чтобы проект с более-менее сложной бизнес-логикой на выходе не был x3 размером по кодовой базе от того, что могло бы быть, используя python :)
о да, размер кодовой базы это очень важный параметр для серверного приложения
особенно забавно это слышать для ситуаций на долгую дистанцию, где через 2-3 года вы охренеете поддерживать свой зоопарк на питоне (потому как вряд ли вы будете держать все актуально и обновлять)
Важный параметр - это поддерживаемость кода, верно.
Вопрос: почему я должен охренеть поддерживать приложение на пайтоне, но не охренеть поддерживать аналогичное приложение на go?
нормальные модули и версионность. Тебя вообще не колышет что там по модулям, если оно собирается то оно будет собираться и через 5 лет без танцев и тд.
строгая типизация при максимально простом языке. Это не только компактные шустрые бинарники, но и читаемость кода пополам с безопасностью
Мультиплатформенность. Питон вроде тоже мультиплатформенный но с кучей оговорок, если надо собрать под несколько разных платформ то зачастую цирк с конями когда одни питоновские пакеты используются для компиляции другого пиновского кода (и у этого зоопарка так же есть версионность и особености)
Для себя на практике вывел такие наблюдения для серверного:
php нестареющая классика, но сейчас он стал тем против чего боролся и на долгой дистанции выходит дорого, сложно и ограничено
JS это из мира фулстеков, с кучей приколов на уровне ноды (приколы чем то схожие с питоном). В отличии от php с раскаткой могут быть проблемы на долгой дистанции, особенно если обновы набегами раз в два года. Так же язык позволяет писать вообще нечитаемые ужасы, куда уж там php
python это старший брат JS. Проблемы практически те же, выгода побольше для бека. На долгой дистанции ВСЕГДА будет ебля со сборками. Даже в ноде можно привязаться к конкретным репозиториям и версиям, но в питоне все это сложно и обычной практикой является иметь отдельный докер под сборку и встраиваемую папку со всеми либами.
Goland это просто, максимально просто. Со сборкой - один раз настроил паплайн и забыл (у меня есть боевые проекты которые все еще дописываются по мере на 1.8). Написание так же просто - люди с базовыми знаниями вкатятся очень быстро, и даже без знания читать код может даже тот кто языка вообще не знает. Он шустрый потому прощает костыли, у того же питона вава с производительностью особенно если косячить, но в Го со сторогой типизацией творить хуйню можно, но не в таких широких пределах.
Раст то же что Си и С++. Можно многое, надо знать, нужно ебатся, код для не знающего похож на ельфийский - тот же php или js можно научится читать хотя бы примерно за день
строгая типизация при максимально простом языке. Это не только компактные шустрые бинарники, но и читаемость кода пополам с безопасностью
про "читаемость", в python есть type annotations, и кода без оных я не наблюдах в коммерческих проектах последних лет 5 уж точно.
Для типобезопасности есть линтеры (с оговорками конечно но все же) которые, как правило, тоже must have
Про проблемы с кроссплатформенностью пайтона - тру стори, только в 99% случаев все запускается на одной платформе
Даже в ноде можно привязаться к конкретным репозиториям и версиям
Что мешает привязаться к конкретным версиям в питоне?
И что, в Go-либах не бывает breaking changes?
С Го есть целая секта которая верит в наглядность кода, так что не нужны комментарии) Секстанты, но в чем то они и правы - в питоне можно создать ужасные вещи (тот же esptool) в которых без IDE и понимания языка далеко не уйдешь в понимании. В го сотворить нечитаемое можно только если пилить однофайлово, в единой функции и часто юзать GOTO. Хотя там есть свои подводные с тем же init() но это можно отслеживать (к слову отладка и тесты с бенчмарками на Го еще одна причина его юзать)
С либами есть файл go.mod в котором четко прописывается используемая версия Го и все используемые модули, которые так же указываются с версией (и в модулях то же самое). То есть если заюзать модуль который конфликтует с текущей версией то это сразу напишет. Если же все ок собирается, то и через 20 лет оно для сборки будет использовать модули конкретных версий даже если там набежало еще 100500 версий (указывать last нельзя, точнее загрузить или обновить можно, но в go.mod указывается конкретная версия).
Работа с Го это лучшее что я встречал за 15 лет практики. Как сборка, так и всякие мелочи по типу работы с модулями или тесты/бенчмарки. Встраивать код из других языков, профилировать или прописывать прямо в коде что именно подтягивать при конкретных сборках (как в си) - идеально. И как вишенка язык простой, голова отдыхает, ты думаешь о функционале, а не о синтаксисе, причем все достаточно низкоуровнево при желании.
синтаксис - дело наживное, вопрос опыта и привычки, а прописать конкретные версии в python’е тоже можно :) Если для вас язык, где дженерики завезли в N-ной версии - это «лучшее» то предлагаю дискуссию закрыть )
хз хз за дженерики
много про что могу сказать что появилось с 1.13 версии или 1.8 хотя по уму должно быть по умолчанию, но вот дженерики не входят в это число
Бысто что то накидать проверить концепцию ок, но вот если боевое и боги упаси высоконагруженное то генераторы ван лов
Отлаживать дженерики та еще лажа, особенно по ресурсам. Особенно учитывая что в реальности применяется вилка до 4 типов максимум, покрытие всех any это уже что-то кривое и небезопасное.
И опять таки 90% того что в других языках решают дженериками, решает правильное использование интерфейса. Прямо что бы напрямую разные типы юзается только с разными мапами чтоб сортировать разве что.
Раст то же что Си и С++. Можно многое, надо знать, нужно ебатся, код для не знающего похож на ельфийский - тот же php или js можно научится читать хотя бы примерно за день
для меня код на go похож на эльфийский, а код на расте - вполне читаемый и понимаемый. Так что тут субъективщина чистой воды.
Про "много нужно знать" - при работае с любым ЯП нужно знать, как этот ЯП работает, хотя бы базово.
И, в целом, все что вы написали, ни разу не отменяет моего основного тезиса, сказанного выше. Если язык подразумевает тонны бойлер-плейта по своей сути, то для большего, чем написания небольших приложений он не годится.
Если смотреть на читаемость, то самый читаемый (по моему опыту) это грамотно написанный проект на Java, С++ вполне читаем если немного вникнуть. А вот Питон, к примеру, набит абсурдными конструкциями и сахаром для компенсации архитектурных недоработок, JS вообще критиковался всеми за всё , PHP я уже не видел лет 20 и ничего о нём сказать не могу.
Я делал бэки и на Python и на Go. Мне трудно сказать за читаемость или что можно где-то "ужасные вещи" натворить, поскольку если с головой подойти к кодингу и просто знать соответствующий ЯП, то все будет максимально понятно и вовсе не ужасно. А ужасные вещи можно наколбасить с любым ЯП и на том же Go, я вас уверяю)) Да, Go выглядит как будто более приспособленным для веб серверов, но так он для них и создавался на секунду. Но что касается читаемости, попробуйте почитать код с десятками каналов и разобрать логику. Если не на опыте, с каналами и горутинами тоже можно натворить всякого.
Потому что производительность CPU лишь одна из метрик. Есть еще скорость разработки, доступность библиотек и стоимость найма разработчиков.
Python часто выигрывает по этим трем пунктам, что для многих бизнес-проектов на старте важнее чем голые RPS
Вся статья строиться на измерениях текущей реализации asyncio, учитывающей GIL и работающей в одном потоке, но no GIL так же позволит переписать планировщик корутин, что бы он использовал пулы потоков и тогда async станет эффективным и в CPU bound задачах (за счёт параллельного выполнения корутин в разных потоках из пула).
Вообще глобально многопоточность и асинхронность корутин это не много ортогональные вещи, но если говорить с точки зрения практики, но корутины всегда в пределе будут эффективнее потоков, так потоки управляются внешним планировщиком ОС, а корутины внутренним и имеют больше информации для оптимизации потока выполнения.
Текущую реализацию очень сложно перевести в многопоточную - крайне мало вероятно, что это случится. Там слишком много завязано на то, что переключение может произойти только в очень определенных местах кода
Вообще говоря нет, кроме того можно сделать эрзац вариант уже в текущем интерпретаторе: берем интерпретатор в no-gil сборке, а потом в отдельных потока запускаем свои EventLoop, у меня получился параллельные asyncio, внутри одно eventloopа естественно всё последовательно, но корутины из разных eventloopов могут работать параллельно в разных потоках
Ну, не так это. Если у вас есть некая переменная, к которой вы доступаетесь из разных корутин, то сейчас у вас есть гарантия, что ее никто не прочитает/поменяет между двумя async вызовами внутри одной корутины. И сейчас куча мест в коде, которые полагаются на это и не берут локи. В вашей реализации или в более полноценной эта гарантия ломается
И да, и нет.
Если говорить о переменных которые в контексте текущего диспатчера корутин, то так и останется в этом дистпатчере, а переменные которые имеют какой-то глобальный доступ, так я и сейчас могу запустить отдельный тред из которого могу поменять значение между двумя вызовами async.
Никаких новых требований не предполагается, да переменные который не потокобезопасны, они остаются не потокобезопасными, но они и так всегда по умолчанию не потокобезопасны.
Не надо делать не потокобезопасные вызовы, неважно из корутины они делаются или из мультитрединга.
Так сейчас asyncio исполняется в одном потоке, и все это понимают и пишут в основном потоко не безопасно, но без лишних локов, где это можно. В описанном вами варианте изменения из другого потока, наверняка или не нужна атомарность, или лок повесят. А вот если вдруг внезапно asyncio полетит во множестве потоков, то куча существующего кода разнесет
Практически везде в существующем коде есть такие куски
async def some_method(self):
res = await async_fn()
self.some_attr = sync_fn(self.some_attr, res)
И сейчас есть гарантия, что чтение атрибута и его обновление происходит атомарно, если специально не подпрыгивать с изменением его в другом потоке
Это тоже абсолютно решаемо, рас кажу как это сделано в Kotlin.
Там при запуске корутины можно указать диспетчер корутин (один из встроенных или даже свою реализацию), который определит какой пул потоков использовать, и там есть диспетчер который запускает корутину всегда в главном потоке, который запускает в параллельном пуле, в специально io пуле.
Так что просто оставляем что по дефолту asyncio.run запускает всё в одном потоке, но опцией даем возможность передать диспетчер
Справедливости ради, доклад я заканчивал словами о том, что в многопоточную модель потенциально можно было бы привезти green-threads. А точнее, сделать сами потоки "асинхронными внутри". То есть на один поток операционной системы порождалось бы несколько виртуальных потоков. Каждый такой виртуальный поток был бы фактически асинхронной корутиной. Как в Java, Golang и других "честных" языках, где давно уже green-threads или аналоги.
Хотя нечто похожее мы фактически получаем и сейчас, запускаю несколько инстансов асинхронного приложения на UWSGI. У нас фактически есть несколько потоков, каждый из которых внутри поддерживает асинхронность.
Единственный нюанс - эти потоки не видят друг друга и не столь эффективно работают, как в том же Golang
Питонистов, привыкших к тому что есть GIL, заставили верить в то, что многопоточный и асинхронный подходы при работе с IO - конкурирующие и взаимоисключающие. Но это справедливо лишь в контексте существования GIL )
Условная M:N модель, где M асинхронных задач (тысячи их) склейлятся на N тредов ОС (ограниченное количество, как правило равное кол-ву ядер CPU) - это нормальная практика во многих ЯП.
Замечательная async await модель в dotnet:
асинхронная задача освобождает текущий поток, когда она завершается, любой свободный поток ее подхватывает.
в эпоху no gil, полагаю, async await питона так же отойдет от парадигмы 1 асинхронный поток на 1 процесс
Модель dotnet практически невозможно затащить в Питон - сломается весь существующий асинхронный код
Сломается и сломается. Напишут в breaking changes об изменениях и дадут время на адаптацию. Не в первый раз уже ломающие изменения были в python 3
Проще не пытаться превратить Python в C#, а использовать сильные стороны каждого. В Python No GIL дает честную многопоточность для CPU-задач, для IO-оркестрации есть однопоточный asyncio. Комбинируя их, можно получить хороший результат, не ломая язык
Да, всё так. Спасибо за комментарий!
Хотя ветка обсуждения на введение green-threads активно сейчас ведётся, поэтому мб лет через 5 мы можем увидеть что-то такое. Вот ссылка, если интересно:
https://discuss.python.org/t/add-virtual-threads-to-python/91403
Это везде так. Пул воркеров, и отдельный диспетчер, распредделяющий задачи.
Есть важный нюанс: планировщик операционной системы сам решает, когда выделить потокам время на выполнение. При этом GIL в CPython заставляет поток освобождать его примерно раз в 5 миллисекунд.
* For the longest time, the eval breaker check would happen
* frequently, every 5 or so times through the loop, regardless
* of what instruction ran last or what would run next. Then, in
* early 2021 (gh-18334, commit 4958f5d), we switched to checking
* the eval breaker less frequently, by hard-coding the check to
* specific places in the eval loop (e.g. certain instructions).
* The intent then was to check after returning from calls
* and on the back edges of loops.
*
* In addition to being more efficient, that approach keeps
* the eval loop from running arbitrary code between instructions
* that don't handle that well. (See gh-74174.)
*
* Currently, the eval breaker check happens on back edges in
* the control flow graph, which pretty much applies to all loops,
* and most calls.
* (See bytecodes.c for exact information.)
А каковы на ваш взгляд перспективы async и free-threading в контексте появления в 3.14 субинтерпретаторов? Вот бы этот вариант ещё рассмотреть.
Спасибо за трезвый взгляд на вещи, хорошее доказательство того что выбор между async и threading это не религиозный вопрос, а инженерный компромисс, который зависит от конкретной задачи, нагрузки и... версии Python
Для многих проектов "просто подождать Python 3.13" реально может оказаться самой дешевой и эффективной стратегией
А вот в случае с IO-bound задачами, на мой взгляд, оба подхода — многопоточность и асинхронность — дают схожий результат.
Ох уж эта дихотомия... Допустим, пишем эхо-сервер, который должен пережевать 10Gbps пакетами по 64 байта. Это I/O-bound или CPU-bound? Или таки оно при использовании неэффективного языка из I/O-bound внезапно превращается в CPU-bound?
Допустим, пишем эхо-сервер, который должен пережевать 10Gbps пакетами по 64 байта
А здорово вы это придумали, я даже сначала и не понял)
Если же серьёзно, то под каждую задачу есть свой инструмент. Вы привели в пример пограничное значение, которое маловероятно, что будет написано на Python в целом.
При этом базовый echo-server я бы тоже писал на Python. Тут возникает вопрос: "А почему echo-server должен пережевывать 10Gbps?". Если это ошибка в постановке ТЗ - разработчик должен заметить и сказать об этом бизнесу. Если такое придумал сам разработчик - он скорее всего начинающий и не знает, какая реальная будет нагрузка, поэтому закладывается на супер хайлод.
Во всей статье я говорил о реальных примерах и реальном использовании. Поэтому будьте реалистом)
Для меня асинхронность — это, в первую очередь, не про скорость, а про экономию ресурсов. Если у нас до 1000 одновременных запросов, выбор между многопоточностью и асинхронностью не критичен. Многопоточность займёт, например, 4 ГБ оперативной памяти, и это допустимо. Если же речь идёт о более чем 10 000 одновременных соединений, асинхронность действительно эффективнее.
на лицо полное непонимание терминов, в принципе это простительно, потому в питоне это никогда не работало и люди, которые не знают ничего кроме него начинают излагать домыслы, коих полон интернет.
асинхронность это про то, что вы можете взять и выполнить какой-то код в фоновом процессе относительно текущего. точка. он может быть как честный без GIL так и с ним. все, больше это ничего не значит. очевидно что если у вас нет GIL то вы тут получите преимущество, потому что вы будете использовать все ресурсы процессора, а не одно ядро.
заводя разговор про 10к запросов вы уже влазите уже в другую область, называется "конкурентность" - тут немного другие правила и требования. В принципе можете с этим базисом обращаться в чат гпт, он вам все разъяснит, в чем отличие конкурентности от параллелизма. ну и что такое асинхронность еще раз.
Если очень сильно обобщить, то "конкурентность" - это способность нескольких различных участков кода выполняться независимо друг от друга. Ваше определение "асинхронности" попадает под это понятие, и не понятно, зачем вы их разделяете. Параллелизм - это подвид конкурентности.
P.S. говоря об асинхронности, автор явно имеет в виду конкретно модель асинхронного IO в python, что очевидно
просто это точные определения того что делается и как, чтобы все правильно понимали о чем речь и какой проблеме.
параллелизм это когда вы несколькими исполнительными блоками вместе работаете над общей задачей. соответственно ваш алгоритм распараллеливается или нет в зависимости от того как он работает. самый простой вариант суммирование двух больших массивов поэлементно.
асинхронность - возможность отправить вычисления (в общем понимании) считаться куда-то еще и не тормозить текущее выполнение. Вот есть асинхронное IO когда вы говорите “я не хочу ждать операцию, давай дуй в фоновое исполнение” - заметьте здесь нет речи о том как мы будем получить результат, речь не про колбеки и тому подобное, важен сам факт что мы можем как-то скинуть задачу с себя и пойти заниматься другими вещами.
конкурентность - в русском языке удачно дословно переводится от слова "конкурировать", особая ситуация когда в каком-то месте вам нужно иметь дело с одновременно поступающими задачами, например запросами или потоками которые считают матрицу и теперь им всем нужно например увеличить общий счетчик. Вот эти потоки, запросы становятся конкурирующими, когда они лезут одновременной и конкурируют за какой-то общий ресурс. Потому что есть ситуации когда они не кокурируют.
цель параллелизма - ускорение за счет использования доп ядер, задача конкурентности - как-то обработать задачи вместе а не одну за одной.
Поэтому и получается что это все термины из примерно одной области, но лучше их применять по определению.
важен сам факт что мы можем как-то скинуть задачу с себя и пойти заниматься другими вещами.
согласен с данным тезисом. Однако, если у нас эта самая вычислительная задача не является фоновой, а является полноценной и равнозначной задачей со всеми прочими, разве не будет справедливым говорить об "асинхронном выполнении"?
В прочем, не важно. Это спор за термины, суть которых ясна
Вы рассуждаете об асинхронности с точки зрения разработчика и технологии. Мой же вывод об асинхонности с точки зрения компании и продукта. Зачастую, владельцу бизнеса не очень важно, асинхронность или многопоточность вы будете использовать. Он будет видеть счёт за вычислительные ресурсы.
А относительно скорости в 80% случаев подходы похожи. Поэтому нет разницы, что использовать. Да и относительно ресурсов, если быть честным, в 80% случаев разницы не будет особой тоже. Типичный паретто)
потребление ресурсов будет значительно отличаться, если речь идет о тысячах задач / тысячах тредов. И не важно, параллельно эти треды будут выполняться (без GIL) или конкурентно (c GIL). Отсутствие GIL - не silver bullet, параллелизм всей сисиемы все равно будет ограничен кол-вом процессорных ядер, а работа тысячи тредов приведет к значительным затратам ресурсов CPU.
Вышел Python 3.14 . Одно из ожидаемых событий - та самая многопоточность. И она не работает в некоторых важных модулях, например для работы с базами данных. То есть пока вопрос что победит не стоит - побеждает асинхронность.

Конкретно с инсертами в базу есть простейшее архитектурное решение, собирать транзакции в батчи (и разнести отправку в очередь и отправку в базу на два разных воркера / процесса / executor-а). И имхо, тут ограничения будут скорее уже на стороне базы в любом серьёзном проекте.
with
ThreadPoolExecutor(max_workers=n_requests)
as
executor:
Я понимаю, что вы иллюстрируете краевые случаи тут. Но нужно конечно быть самим себе злым буратино, чтобы создавать 10,000 потоков.
Моё личное мнение - что less is more, и ко всем этим интерфейсам (multiprocessing, threading, asyncio) их комбинациям надо прибегать, если ОЧЕНЬ понятно зачем и почему вы делаете.
В примере с базой - если наивное решение в вашем случае даёт x10 пропускной способности, может x1000 и не нужна. You are not Google.
Ну то есть формулировать вывод, имхо надо так, что для каждой задачи свой инструмент, но есть существенный элемента хайпа, который надо разумно анализировать.
Асинхронность vs. многопоточность: что выживет в эпоху No GIL?