Не, ну это имеет смысл. Автор пытается исключить возможный выигрыш С++ за счёт более оптимальной реализации задачи, которая собственно и будет запускаться на 10к тредах. И в конечном итоге получится так, что С++ быстрее/такой же, но на самом деле его полезная нагрузка просто жрёт в n-раз меньше цпу, что собственно и нивелирует больший оверхед самих потоков в сравнении с горутинами.
Для того, чтобы это избежать — надо сравнивать реализации не друг с другом, а с деградацией в сравнении с запуском 10к раз на одном(ncpu) тредах.
«Тактика», «адепт», «раскатывать»… в странном мире вы живёте.
Я живу в этом мире. Не я сливаюсь, не я веду себя так. Не моя тактика основа на вранье, обвинения, уличениях и прочем непотребстве.
Люблю эту адиторию. Много из себя строит, а после первых трудностей сбегает.
Меня все удивляли эти интерпретации и ЧСВ. Когда кто-то что-то спрашивает типчный адепт начинает строить из себя учителя, предполагая, что тот, кто спрашивает чего-то не знает. А раз не знает — ему можно впаривать любою херню, но суть в вере в себя. Адепт начинает думать, что он выше того, кто спрашивает.
Но иногда бывает так, что тот кто спрашивает — спрашивает это не для того, чтобы ему объяснили. А для того, чтобы адепт на кураже выложил все свои представления о теме. А далее эти представления очень просто разбиваются.
Ну и да, играть в игру «я не говорил, я не я» с более сильным не имеет смысла, ибо в любом случае разоблачат. Такие дела.
Ну это просто смешно. Неужели вы реально думаете, что такая попытка чего-то стоит?
Если вы на 4х ядрах
Во-первых враньё номер раз. Ни на каких ядрах и ничего я не запускал. Я в мейн-потоке запустил 100500горутин, а далее в мейнпотоке был цикл, который никак не мог заблокировать остальные потоки.
без вытесняющей многозадачности
Приплыли. Ведь отсутствие вытесняющей многозадачности это и есть дыра в дизайне любых гринтредов.
запустите 4 cpu-bound потока
Очередной враньё. Никакие потоки запущены не были. Никакие cpu-bound-задачи на них не запускались. Запускался слип.
Слип никак не может заблокировать поток, ибо он уже своей логикой вытесняет поток. Иная логика — дыра в дизайне.
а потом захотите запустить 5ый, но он не будет выполняться, — это тоже дыра в дизайне?
Опять враньё. В го потоки(реальные потоки) вытесняемые. Иначе быть не может. Если же это не так — никаких 4-х процессоров нет и вся попытка изначально подлог, а однопоточный дизайн — дыра в дизайне.
Больше похоже на неправильное использование.
Ещё раз. Никаких вменяемых оснований для называния моего кода неправильным нет. Блокировка мейн-потока никак не может влиять на другие потоки, либо запущенные горутины, либо из шедулер. По определению.
Тем более всё это изначальный подлог, ибо создание горутины находится выше и шедулер 100% запустился.
Единственная причина такого поведения — это нахождения шедулера и прочего управляющего кода в мейн-потоке, что является дырой в дизайне по определению.
P.S. Если так хочется посравнивать, можете сделать просто два распараллеленных cpu-bound теста рассчетов на хотя бы 10к горутин и 10к потоков.
Перед тем как предлагать что-то — надо выкатывать основание, либо вменяемые предположения следствием из которых будет являться осмысленность данных предложений. С чего вдруг горутины выиграют?
Какой быстрее посчитает и сколько ресурсов съест. Всякие -O2 и -O3 оптимизации для кода на плюсах использовать будет не спортивно, для схожести машинного кода.
Предложение является дырявым и не имеющим смысла. Когда я что-то измеряю я измеряю только то, что нужно. Поэтому я не буду писать так, чтобы слабость компилятора и рантайма го проявлялась.
По поводу вашего предложения — написать на го лучше вам, ибо я этот язык вижу в первый раз.
Делается же это не так. Берётся 100% масштабируемая задача время выполнения 10к запусков которой поделенное на n реальных ядер(либо лучше посчитать сразу в n-топоках по 10к/n запусков)учитывается как эталон. Далее всё это запускается на 10к тредах и высчитывается оверхед.
По поводу го. Если с сями/крестами я уверен в том, что эталонное время будет состоять на >99% из времени исполнения того куска кода, что написал я. То в го это может быть не так. Он может 50% времени долбить свой шедуллер/рантайм, либо ещё какую херню и результирующих цифрах мы полечим 50% мусора. Но это ладно.
Всякие -O2 и -O3 оптимизации
Кресты без оптимизаций не имеют смысла к существованию. При этом надо понимать, что -O0 — это не отсутствие оптимизаций, а наличии пессимизаций из-за волатайла.
Не «надо юзать», а «библиотека Go под капотом юзает». Это и есть мультиплексинг.
Это не ответ. Ещё раз, меня никаким тоном пугать не надо. Меня это мало волнует.
Хорошо, раскатывать — так раскатывать.
Утверждение раз:
Это не совсем аналог потоков в других языках, это скорее аналог futures, promises, async/await, libevent и подобных вещей.
Суть — противопоставление мультиплексинга(libevent) и горутин.
Утверждение два:
Там, где в го используются горутины, в C вы обычно используете libevent а не потоки.
Противопоставление горутин и мультиплексинга — два.
Далее, когда оратор был зажат в угол — последовало:
Но вы можете сделать иначе — вы можете использовать событийную модель. Горутина может вызвать собственную сетевую библиотеку, а та, обёртывая системные вызовы, добавляет сокет в список ожидания epoll(). При этом заблокируется только один поток на все сокеты.
Опустим событийную модель — она тут не при делах и я не буду это разоблать, что epoll не про событийную модель, но это такое.
Чтобы оратор опять не поплыл с моделью использования горутин — уточним:
Миллион одновременных клиентских соединений? Это чуть ли не канонический use case. Живут, что-то считают, засыпают на ввод-вывод, снова просыпаются, умирают.
Суть — поток данных клиент/сервер находится в своём потоке(выполнения). Это юзкейс для горутин, что собственно выше я и писал.
Далее, мультиплексинг — это про сбор множества потоков данных в один поток, который обрабатывает уже один поток(выполнения) и нет смысла использовать для этого множество потоков(выполнения).
Что мы имеем. Оратор, утверждая изначально о назначении горутин как об альтернативе мультиплексинга, т.е. не много потоков(данных) в один поток данных в один поток обработки, а в множество поток данных в множество потоков(исполнения) вдруг переобулся и начал утверждать обратное. Типичное натягивание совы на глобус и подбивание всего под себя.
Далее пошла типичная тактика обвинять меня в том, что я чего-то не понимаю и он видите ли мне что-то объясняет, а я не понимаю.
Такую же тактику использует адепт ниже, только он на вопрос «почему не работает?» — отвечает «вставьте кастыль — заработает», и каждый раз утверждает, что он отвечает.
Всё это сводится к тому, что адепты за меня придумывают то, что спрашивал я, игнорирую мои вопросы и подменяя их тем, что выгодно им, а далее уже обвиняют меня в том, что придумали они.
Жизнь — процесс познания нового. Только хамить не надо.
Просто смешно. Может мне спросить основание для обвинения меня в " Вы не понимаете, что такое мультиплексинг? Не знаете, что такое event loop?"? И будет очередное «поплыл»?
Ну и конечно же хамить. Это любимое занятие слабой аудитории — сливаться на «хамить» и прочее. А на вопрос «где я хамил» — обвинитель ничего показать не может, а если и может, то связать цитату и «хамил» логически не может.
Это я ещё не начал разоблачать " с самого начала знали." и сливы вида «итак было ясно, что системные потоки не медленнее». Это делается очень просто — я ищу на хабре все статьи про го, в которых упоминается «быстрее» написанные после вышей регистрации и если там не будет в ответах опровержения от вас, либо найду у вас цитатку подобную.
Какие-то горутины не могут получить управление, чтобы отработать, потому цикл ожидания никогда и не завершается.
Ещё раз. Меня не интересует как сделать так, чтобы это работало. Меня интересует то — по какой причине это не работает так, как написал я.
Добавьте runtime.Gosched(), как вам уже советовали.
Это не ответ. Вопрос был не в этом. Повторю в третий раз — почему оно не работает так, как написал я. Какие предпосылки к этому есть, кроме дыры в дизайне.
Как бы разница в пользу Go не стала выше из-за отсутствия переключений ядра и юзерспейса.
Опять же ни на чём не обоснованные утверждения. На основании чего там станет переключений больше? Потому что кто-то сказал?
Ну и для справки — переключение ничего не стоит. Особенно на фоне всплывших подробностей работы горутин с сисколами. Как будет время — я напишу бенчмарки с сисколами и добью эту тему. Другой оратор уже поплыл — до подробностей кричал «горутины аналог мультиплексинга», а после уже «надо юзать горутины с епулом, который собственно их аналогом и является. Бывает.
Мы говорим о вызове функций из нативных библиотек, или уже об асинхронном вводе/выводе?
Любая связь горутины с реальным миром — это код нативных библиотек. Единственная причина по которой это может быть не так — реализация на го обёрток вокруг сисколов, да и в целом переписывания всего либц на го.
Если горутина делает блокирующий системный вызов
Я говорю про это:
Вызов сишного кода выполняется с переключением на стек нативного потока, так что стек горутины не используется.
Хотя на блокирующих вызовах это крах всей логики горутин, ибо оно будет плодить потоки системные + смена стека, а на вызовах не блокирующих.
Весь никакая ассинхронность не нужны, если операции не wait. А такие операции только системные, либо внешние, но опять же — через всё это системное ipc, либо сеть, либо файлы.
Реализуется проверкой в прологах функций (оверхед там небольшой).
Ну хотя да, если там нету vla и прочих историй, то длину стека функции может почитать компилятор.
Вызов сишного кода выполняется с переключением на стек нативного потока, так что стек горутины не используется.
Но ведь суть всей ассинхронки именно во внешних операциях. Прочитать сеть, записать на диск, вызвать бдешку и прочее, а всё это си. Каким образом это работает?
Горутины, конечно, разбрасывает. Но вы не дали планировщику их разбросать. Дело не в том, чтобы запустить горутину, которая спит, дело в том, чтобы выбрать сигнал на её пробуждение в цикле событий, который там под капотом.
Не понят причём тут горутина, причём тут цикл событий? Ничего ему не мешает «их разбросать».
Горутины — не потоки.
Горутины тут не причём. Я вызвал цикл в основном потоке и всё втало раком. Потоки ли горутины, либо нет — никому не интересно и это ничего не меняет.
Нет, они не про это.
Именно про это. Если не про это — я слушаю ваши предположения.
Ну, как видите, 100500 потоков не может, а 100500 (и гораздо больше) горутин может.
Это не имеет смысла. Оно может во столько, сколько использовать имеет смысл. Работает не медленнее, при этом имеет преимущества системных потоков.
Может 100500 активных потоков, но 100500 активных потоков в го быть не может — может быть только(один? 4? 8?). 100500 потоков в слипе никому не нужно, ибо во-первых они будятся через адские кастыли, а во-вторых — стоимость их пробуждения будет нивелировать их смысл.
При этом, если считать честно — горутины создаются и управляются медленнее системных потоков, ибо потребляют больше процессорного времени в сравнении с системными.
Если не подменять понятия, то реальный юзкейс — это именно создание потоков, которые отрабатывают и уничтожаются сразу, а не живут миллионами одновременно(это не имеет смысла из-за оверхеда на пробуждение). В этом юзкейсе системные потоки не уступают горутинам, которые должны быть быстрее.
>>Го вставляет проверки доступного размера стека в прологи генерируемых функций, если стека не хватает на нужды функции, то он растёт. Поэтому guard page нет, и это вполне безопасно.
Это дороже. Опять же — как вызывать нативные(сишные) функции?
>>Ну вот видите, покажет. Тоже вполне себе разница.
Разница в чистых цифрах никакая тем более в сравнении с го в котором есть гц.
>>В реальности будет больше
Не будет. Будет именно так, как посчитал я. Не согласны — предъявите основание вашего утверждения.
я не поленился — шесть раз
Я померил — го 70мегабайт, а птреды 260. Запускалось это на 30к тредах, ибо линукс в больше не может. Как я сказал — тред 8кило * 30к, что ~235 мегабайт, что соответствует реальности. 30к * 2к — это ~59мегабайт, что соответствует наблюдаемым.
Почему важно то, что горутины весят меньше
Как мы уже выяснили — их «меньше» не преимущество, ибо в чистых цифрах оно ничтожно.
, и почему их, бывает, запускают в таких количествах?
Зачем?
>>Потому что горутины — это не потоки.
Это потоки. Им можно какие угодно вешать шильдики, но это потоки.
Они используются не для распараллеливания вычислений и тому подобного.
Поток не про распараллеливание — поток про «поток» — т.е. про параллельное исполнение множества потоков управления.
(Нет, используются, конечно, они всё-таки бегут поверх пула потоков, но это второстепенно.)
Как и обычные потоки.
Настоящая raison d'être горутин и каналов в го — это асинхронное выполнение.
Насколько я знаю — это именно треды.
Т.е. если я создам цепочку горутина->канал->горутина и т.д. — это будет не один поток, а 2.
Это не совсем аналог потоков в других языках, это скорее аналог futures, promises, async/await, libevent и подобных вещей.
Всё это логика над потоком управления, вернее разделение одного на множество и сборка обратно. Треды — это про запуск этих потоков, а каким образом происходит этот запуска — это отдельная история.
Запускать это в горутинах, либо в потоках — разницы нет. Вернее как го-пацаны говорят, что есть, ибо горутины быстрее потоки, но это не совсем так, вернее совсем не так.
Поэтому споры «горутины vs. системные треды» — довольно бесполезное времяпрепровождение. :)
Да нет, это просто отмазки для избежания неудобной ситуации перед простым фактом — горутины не быстрее.
То, что в го есть какая-то логика поверх потоков — из этого ничего не следует. Прикрутить её можно куда угодно.
Были бы это не потоки, если бы все эти цепочки горутина->канал->горутина объединялись бы в цепочку калбеков в рамках одного потока.
Первые два примера только ваш код (во втором случае разве что n увеличено в 10 раз). Никаких больше правок.
У меня не работает мой код — он просто зависает и всё. Хотя причина вроде понятна — оно не завершается пока все горутины не завершены, даже если я их не жду, что странно.
У вас C++ сидел в ядре (обрабатывая 100500 потоков)
Ну он не только в ядре сидел. Он сидел 100500 раз в ядре и 100500 раз в юзерпейсе.
При этом Go съел чуть больше проца, но и завершился чуть быстрее.
Ну если в этих горутинах будет не инкремент атомина, который на фоне всего стоит в районе нуля, а что-то посерьёзней, то быстрее они уже не завершатся.
Надо определиться. В данном случае код запускается на в мейн-потоке, а в отдельной горутине. У меня мой код не работает и никаких реальных причин из-за которых он может не работает — нет, кроме каких-то слабых мест в реализации го.
Именно ваш с миллионом горутин
Какие-то невероятные результаты. Скорее всего там 100к горутин.
С миллионом горутин и паузами (*)
Ну это уже цифры как у меня. Правда выжирает оно 2.5 ядра, что в 2.5 раза медленее птредов. Ниужели го более той болезнью, в которой обвиняли системные треды, при этом системные треды ею не болеют?
Как это реализуется? Это только подсчёт длинны стека, но опять же — это значит, что не вызовешь никакой сишный код. При этом это оверхд не слабый. Это можно реализовать как-то ещё?
В любой форме это сравнение не имеет смысла, ибо не является правдивым. Чистейшей воды подмена понятий «средства языка» с «готовые средства рантайма для реализации какого-то функционала». В данном случае в .net средства для веб есть по умолчанию, а у асм«а нет. И средства эти не уровня языка.
Сам же язык — это про удобство использования api и в редких случая для написания нового кода, но там кроме циклов и функций ничего нового особо не придумали.
А далее уже удобство использования самого языка и чьи-то синтаксические предпочтения. Кому-то нравится $i, а кому-то нет. Кому-то нравится экосистема одного языка, а кому-то другого. В целом при равной мощи рантайма разница между языками в „запилить быстро и удобно“ мало различима.
>>значит у него есть ниша, где он лучше других.
Скорее наличие ниши и делает язык лучше, ибо он более специализирован, а не наоборот. И то не сам язык(в очень маленькой степени), а его рантайм/реализацию самого языка.
Лучше в смысле как язык, то тут не всё так просто. Лучше в одном — хуже в другом.
то этот цикл просто не отдаст управление гопроцедурам.
Ну дак цикл там один, а вёдер у меня 8. И судя по тому, что я нагуглил — го не однопоточный, а может раскидывать всё это на несколько тредов, либо этого он не может?
Не забудьте, что ими управляет не планировщик ОС, а потому надо дать возможность этому планировщику запуститься — главный поток должен заблокироваться хоть ненадолго.
А что ему мешается запустить в параллельном треде? Тем более он запустился — он же вызвал горутину в которой есть слип. В чём проблема?
В вашем примере проще всего вставить очень маленький Sleep() в цикл проверки переменной.
Этот цикл — эмуляция нагруженного реального потока. Собственно это ещё одно причина из-за которой «горутины должны быть маленькие», хотя ничего не мешает расставлять какие-нибудь стоп-поинты(аля pthread_testcancel()).
Вообще, вы по сути проверили скорость создания потоков.
Ну да, ведь горутины именно про это.
Создание потоков в Linux это быстрая штука, спору нет.
Судя по бложикам го, судя по хайпу вокруг горутин — все меня(и не только меня) убеждают в том, что ОС не может даже в 100тредов.
Но вы же сами написали, что при равном количестве потоков/процедур у вас пример на C++ вылетает с нехваткой ресурсов.
Нет. Я писал не так — я писал, что активных потоков может быть 30к из-за каких-то ограничений линукса. А так же я написал, что я не знаю таких юзкейсов где надо иметь больше 30к АКТИВНЫХ потока.
Потоки куда тяжеловеснее по стеку (по умолчанию, если память не изменяет, там два мегабайта)
Сколько там мегабайт в стеке не имеет значение — занимать всегда будет столько, сколько используется кратно 4килобайтам.
Это тратит только адресспейс, которого:
address sizes: 39 bits physical, 48 bits virtual
И уж даже если взять под потоки 41бит — это в миллион раз больше, чем 2мегабайта.
Поменять же размер стека никаких проблем не состовляет:
Ну обычно у стека есть защита — последняя страница ставить с prot_none и при при заходе на неё падает с «сегфолтом».
Если у го её нет, то значит любая горутина может спокойно покараптить стек другой горутины, а если она есть — стек уже не 2кб, а 8кб минимум.
>>Вставьте задержку и посмотрите на maximum resident size, я думаю, что код на C++ покажет гораздо больший расход памяти.
Не покажет. Я уже объяснил причины. По поводу памяти — при любом стеке птреды будут занимать 8кб на один тред(страница активный + страница для защиты). Если в го — это 2кб, то будет занимать в 4раза меньше.
Опять же — ничего не мешает запилить аналог птреда и с 2кб стека, правда всех мало волнуют эти 100мегабайт на 100к тредов.
И опять же, как я говорил — гц в реальном приложении на го сожрёт куда больше.
>>Что будет для него эффективнее — писать сайт на ассемблере или на .NET?
Подмена понятий.
>>Я думаю, .NET будет лучшим выбором.
Не верно, ибо подмена понятий.
Никто не пишет сайты на .net. Никто не пишет сайты на языке — сайты пишут на готовом апи. И без разницы какой это язык, если ты вызываешь какой-нибудь интерфейс. Разница только в сахаре, но это не особо принципиально, да в современных ассемблерах сахара не меньше.
Подлог заключается в том, что вы сравниваете пацана с .net, который на 99% состоит из готового веб-рантайма и пацана с асм, у которого рантайма нет. Но ведь .net-пацан этот рантайм не писал — точно так же асм-пацан может его написать, либо взять готовое.
Если же взять нормальное сравнение, а не изначально ущербное, то никакой разницы не будет.
Реальный мир просто способствует продвижению этого мифа, ибо задачи на тех же сях решаются дольше. Но это следствие не того, что на сях «дольше», а просто задачи решаемые на сях сложнее. Живые сравнение Си вс жава не проводятся, ибо это не имеет смысла.
>>Потом появились треды (или нитки). Они были гораздо легче и работали в одном адресном пространстве. Если процессов обычно запускали единицы или десятки, то тредов можно было иметь уже сотни.
И какое отношение «было» имеет к сейчас и к го?
>>Однако, при неаккуратном использовании и они могли отнять все ресурсы системы.
Не могли. Никогда.
>> Каждый тред всё-таки занимал какие-то ресурсы, даже если был заблокирован.
Не занимал, а занимает. При этом точно так же он занимает в го, при этом это «занимает» ничего не занимает в сравнении с оверхедом ГЦ.
>>Чтобы ограничить число тредов, начали использовать тред пулы.
Не верно. Тредпул, если это именно тредпулл с постоянно живущими потами — существует не для это. Он существует для нивелирования оверхеда на запуск потока.
>>Горутины можно мыслить как задачи, выполняемые одним общим большим тред пулом. В Go горутины крайне дешевы.
Го тут непричём — го лишь одна из реализаций юзерпейс «тредов». И при этом «дешевы» — это не верно.
>>Вы можете запустить миллионы горутин без проблем для производительности.
Если под производительностью имеется ввиду как во всех бложиках «спящие треды не отъедают производительность» — это точно так же работает и в системных потоках.
>>Единственное требование — горутины должны быть «маленькие».
Не да, чтобы не надо было шедулить много активных горутин. Типичное проявление слабости шедуллера.
Я уже слышал столько легенд об «тормазящих системных потоках, которых нельзя запустить больше 20», «запустил 100системных потоков и даже спящие съедят 100% цпу» и прочее.
Но проблема как всегда в том, что когда адептам рассказывают что-то про «горутины вс системные треды» — почему адепты никогда не требуют доказательств? Сколько бы я не гуглил — я не увидел ни единого бенчмарка, либо сравнения с системными тредами.
Берём пишем простой бенч — создаём 100500(линукс больше не может, вернее он там и больше 30к активных не может) тредов с телом «инкремент атомика», а после смотрим за сколько все эти 100500 тредов отработали.
package main
import "fmt"
import "sync/atomic"
func main() {
var ops uint64 = 0
var n = 100500;
for i := 0; i < n; i++ {
go func() { atomic.AddUint64(&ops, 1) }()
}
for atomic.LoadUint64(&ops) < uint64(n) {}
fmt.Println(atomic.LoadUint64(&ops))
}
#include <thread>
#include <vector>
#include <atomic>
#include <cstdio>
int main() {
std::atomic<size_t> c{0};
size_t n = 100500;
for(size_t i = 0; i < n; ++i) std::thread{[&](){++c;}}.detach();
while(c < n) {}
fprintf(stderr, "%lu\n", (size_t)c);
}
pthreads
100500
real 0m0.288s
user 0m0.040s
sys 0m0.250s
Go
100500
real 0m0.226s
user 0m0.340s
sys 0m0.010s
В конечном итоге мы видим, что го еле-еле на 30% быстрее. При этом эту разницу можно выкрутить почти в ноль, если затюнить pthread/ведро.
Ну и так же мы видим, что создание даже 100500 тредов, которые ничего не делаю нихрена не «бесплатно», а даже очень платно.
Если же впилить в С++ слипы в каждый тред, то оно отработает так же(правда надо уменьшить количество до 30к, иначе падает с «кончились ресурсы»). Если же впилить в го — оно встанет раком. Может я просто не так писал слипы в го?
>>Java
>>альтернатива Си или Си++
>>Java
>>альтернатива
Спасибо — посмеялся.
>>Паскалю
>>такой как Оберон или Ада-95, спокойно могут держаться за него, не боясь оказаться в невыгодной «языковой ситуации».
Вся квалификация в одном предложении. Вернее её отсутствие. Мне жаль тех, кто ему поверил. Они оказались на задворках.
До появление жавы они воспевали «суперязыки» будущего, который дохли один за другим в небытие.
А по поводу «почему жава» — ну во-первых жава требует намного более низкой квалификации от данного «профессора» и шансы у оного осилить тот же С++ равны нулю, а уж про реальный си я даже заикаться не буду. Учить проще. Проверять проще. Но это всё не важно.
Основная причина — все эти вузы в сша сидят на грантах больших корпораций. Кто стоял за C/С++? К тому моменту дохлая Bell labs? А кто пропихивал жабку? Сан + корпоротивный сектор, который был опутан связями с сан и прочими вендорами, которые требовались новые адепты. Естественно С++ их не интересовал как излишне сложный и никакой в тот момент, хотя дава была ещё более никакая, но всяко лучше С++.
То же самое твориться и в вузах рашки(в центральной не так сильно), а вот на периферии и снг — во все поля — все под майкрасофтом как и этот ресурс. И точно так же «сишарпик наше всё, маздайка — наше всё и С/С++ не язык».
Всегда выгодней учить тому, что проще и тому, за чем стоят серьёзные дяди которые дадут пирожок и за кадры и за выбор. Особенно если эти дяди нас кормят — им не откажешь.
Замечание. Не «быстрые TCP-сокеты» и не «оптимизация TCP-сокетов», а быстрые биндинги/обёртки и оптимизация биндингов/обёрток. К сокетам это отношения не имеет.
Да, да, да. Смешно-смешно. 2016 и прочие мемчики школоты, но балабол пытается из себя что-то строить.
Ещё раз — мог бы ты что-то — ты бы не обделался, а не мог бы я больше тебя — я бы не победил. Всё просто.
>>Ваших комментариев не имеет никакой ценности в ситуации спора вне Вашей собственной головы — это очень печально.
Пока ты этого не доказал — твои потуги ничего не стоя, опять же — мой коммент — это ответ на твои потуги. А коли после моего ответа ответа от тебя по теме не последовало, а не по теме последовало — вывод один — ответить нечего, либо обделался/слился.
>>И, внезапно, если вы курлыкнули немного бреда, то оппонент вообще не обязан поддаваться приступу оверквотинга и разбирать каждую Вашу «ценную мысль».
Опять потуги убогие. Я могу тебя спросить за бред и ты обделаешься, как ты обделался по-теме, но зачем. Ты предпринял попытку спорить и ты пытался до определённого момента, если бы всё реально было так как ты сказал — ты бы написал это сразу, а не тогда, когда тебя загнали в угол. Либо хотя-бы ответил по теме, а потом начал кукарекать.
В конечном итоге всё просто — обделался, начал нести херню. Обосрался и здесь. Теперь уже пошли совсем детсадовские отмазки «я не обязан отвечать» — ты обязан — ты начал, тебя никто не заставлял. Начал спорить и съехал — проиграл.
>>Иногда случается даже так, что Ваш коммент представляет собой пустую трату байтов, вне зависимости от того, что там думают Ваш внутренний судья (он же прокурор).
Опять лсный балабол пытается себя приписать к байтам, да и вообще к теме. Смешно.
Споря с тобою — я не думаю — в этом нет смысла. Вернее как — я пытаюсь писать сдержано, дабы не ты не пошел доносить на меня. Хотя именно это ты и пытаешься сделать.
Как я уже сказал — очередная малоразвитая амёбка что-то строит из себя пытаясь взывать к публики таких же амёбок. При этом итак ясно кто победитель и почему. Каждый день по десять штук таких в спорах со мною обеделываются и их потуги ничего нового для меня не представляют, ибо все как под копирку один в один. Хотя все вылезли из одной парты и действуют по одной агитке.
Для того, чтобы это избежать — надо сравнивать реализации не друг с другом, а с деградацией в сравнении с запуском 10к раз на одном(ncpu) тредах.
Я живу в этом мире. Не я сливаюсь, не я веду себя так. Не моя тактика основа на вранье, обвинения, уличениях и прочем непотребстве.
Люблю эту адиторию. Много из себя строит, а после первых трудностей сбегает.
Меня все удивляли эти интерпретации и ЧСВ. Когда кто-то что-то спрашивает типчный адепт начинает строить из себя учителя, предполагая, что тот, кто спрашивает чего-то не знает. А раз не знает — ему можно впаривать любою херню, но суть в вере в себя. Адепт начинает думать, что он выше того, кто спрашивает.
Но иногда бывает так, что тот кто спрашивает — спрашивает это не для того, чтобы ему объяснили. А для того, чтобы адепт на кураже выложил все свои представления о теме. А далее эти представления очень просто разбиваются.
Ну и да, играть в игру «я не говорил, я не я» с более сильным не имеет смысла, ибо в любом случае разоблачат. Такие дела.
Во-первых враньё номер раз. Ни на каких ядрах и ничего я не запускал. Я в мейн-потоке запустил 100500горутин, а далее в мейнпотоке был цикл, который никак не мог заблокировать остальные потоки.
Приплыли. Ведь отсутствие вытесняющей многозадачности это и есть дыра в дизайне любых гринтредов.
Очередной враньё. Никакие потоки запущены не были. Никакие cpu-bound-задачи на них не запускались. Запускался слип.
Слип никак не может заблокировать поток, ибо он уже своей логикой вытесняет поток. Иная логика — дыра в дизайне.
Опять враньё. В го потоки(реальные потоки) вытесняемые. Иначе быть не может. Если же это не так — никаких 4-х процессоров нет и вся попытка изначально подлог, а однопоточный дизайн — дыра в дизайне.
Ещё раз. Никаких вменяемых оснований для называния моего кода неправильным нет. Блокировка мейн-потока никак не может влиять на другие потоки, либо запущенные горутины, либо из шедулер. По определению.
Тем более всё это изначальный подлог, ибо создание горутины находится выше и шедулер 100% запустился.
Единственная причина такого поведения — это нахождения шедулера и прочего управляющего кода в мейн-потоке, что является дырой в дизайне по определению.
Перед тем как предлагать что-то — надо выкатывать основание, либо вменяемые предположения следствием из которых будет являться осмысленность данных предложений. С чего вдруг горутины выиграют?
Предложение является дырявым и не имеющим смысла. Когда я что-то измеряю я измеряю только то, что нужно. Поэтому я не буду писать так, чтобы слабость компилятора и рантайма го проявлялась.
По поводу вашего предложения — написать на го лучше вам, ибо я этот язык вижу в первый раз.
Делается же это не так. Берётся 100% масштабируемая задача время выполнения 10к запусков которой поделенное на n реальных ядер(либо лучше посчитать сразу в n-топоках по 10к/n запусков)учитывается как эталон. Далее всё это запускается на 10к тредах и высчитывается оверхед.
По поводу го. Если с сями/крестами я уверен в том, что эталонное время будет состоять на >99% из времени исполнения того куска кода, что написал я. То в го это может быть не так. Он может 50% времени долбить свой шедуллер/рантайм, либо ещё какую херню и результирующих цифрах мы полечим 50% мусора. Но это ладно.
Кресты без оптимизаций не имеют смысла к существованию. При этом надо понимать, что -O0 — это не отсутствие оптимизаций, а наличии пессимизаций из-за волатайла.
Но это ладно — я сделаю честно.
Это не ответ. Ещё раз, меня никаким тоном пугать не надо. Меня это мало волнует.
Хорошо, раскатывать — так раскатывать.
Утверждение раз:
Суть — противопоставление мультиплексинга(libevent) и горутин.
Утверждение два:
Противопоставление горутин и мультиплексинга — два.
Далее, когда оратор был зажат в угол — последовало:
Опустим событийную модель — она тут не при делах и я не буду это разоблать, что epoll не про событийную модель, но это такое.
Чтобы оратор опять не поплыл с моделью использования горутин — уточним:
Суть — поток данных клиент/сервер находится в своём потоке(выполнения). Это юзкейс для горутин, что собственно выше я и писал.
Далее, мультиплексинг — это про сбор множества потоков данных в один поток, который обрабатывает уже один поток(выполнения) и нет смысла использовать для этого множество потоков(выполнения).
Что мы имеем. Оратор, утверждая изначально о назначении горутин как об альтернативе мультиплексинга, т.е. не много потоков(данных) в один поток данных в один поток обработки, а в множество поток данных в множество потоков(исполнения) вдруг переобулся и начал утверждать обратное. Типичное натягивание совы на глобус и подбивание всего под себя.
Далее пошла типичная тактика обвинять меня в том, что я чего-то не понимаю и он видите ли мне что-то объясняет, а я не понимаю.
Такую же тактику использует адепт ниже, только он на вопрос «почему не работает?» — отвечает «вставьте кастыль — заработает», и каждый раз утверждает, что он отвечает.
Всё это сводится к тому, что адепты за меня придумывают то, что спрашивал я, игнорирую мои вопросы и подменяя их тем, что выгодно им, а далее уже обвиняют меня в том, что придумали они.
Просто смешно. Может мне спросить основание для обвинения меня в " Вы не понимаете, что такое мультиплексинг? Не знаете, что такое event loop?"? И будет очередное «поплыл»?
Ну и конечно же хамить. Это любимое занятие слабой аудитории — сливаться на «хамить» и прочее. А на вопрос «где я хамил» — обвинитель ничего показать не может, а если и может, то связать цитату и «хамил» логически не может.
Это я ещё не начал разоблачать " с самого начала знали." и сливы вида «итак было ясно, что системные потоки не медленнее». Это делается очень просто — я ищу на хабре все статьи про го, в которых упоминается «быстрее» написанные после вышей регистрации и если там не будет в ответах опровержения от вас, либо найду у вас цитатку подобную.
Ещё раз. Меня не интересует как сделать так, чтобы это работало. Меня интересует то — по какой причине это не работает так, как написал я.
Это не ответ. Вопрос был не в этом. Повторю в третий раз — почему оно не работает так, как написал я. Какие предпосылки к этому есть, кроме дыры в дизайне.
Опять же ни на чём не обоснованные утверждения. На основании чего там станет переключений больше? Потому что кто-то сказал?
Ну и для справки — переключение ничего не стоит. Особенно на фоне всплывших подробностей работы горутин с сисколами. Как будет время — я напишу бенчмарки с сисколами и добью эту тему. Другой оратор уже поплыл — до подробностей кричал «горутины аналог мультиплексинга», а после уже «надо юзать горутины с епулом, который собственно их аналогом и является. Бывает.
Любая связь горутины с реальным миром — это код нативных библиотек. Единственная причина по которой это может быть не так — реализация на го обёрток вокруг сисколов, да и в целом переписывания всего либц на го.
Я говорю про это:
Хотя на блокирующих вызовах это крах всей логики горутин, ибо оно будет плодить потоки системные + смена стека, а на вызовах не блокирующих.
Весь никакая ассинхронность не нужны, если операции не wait. А такие операции только системные, либо внешние, но опять же — через всё это системное ipc, либо сеть, либо файлы.
Ну хотя да, если там нету vla и прочих историй, то длину стека функции может почитать компилятор.
Но ведь суть всей ассинхронки именно во внешних операциях. Прочитать сеть, записать на диск, вызвать бдешку и прочее, а всё это си. Каким образом это работает?
Это общий разговор.
Не понят причём тут горутина, причём тут цикл событий? Ничего ему не мешает «их разбросать».
Горутины тут не причём. Я вызвал цикл в основном потоке и всё втало раком. Потоки ли горутины, либо нет — никому не интересно и это ничего не меняет.
Именно про это. Если не про это — я слушаю ваши предположения.
Это не имеет смысла. Оно может во столько, сколько использовать имеет смысл. Работает не медленнее, при этом имеет преимущества системных потоков.
Может 100500 активных потоков, но 100500 активных потоков в го быть не может — может быть только(один? 4? 8?). 100500 потоков в слипе никому не нужно, ибо во-первых они будятся через адские кастыли, а во-вторых — стоимость их пробуждения будет нивелировать их смысл.
При этом, если считать честно — горутины создаются и управляются медленнее системных потоков, ибо потребляют больше процессорного времени в сравнении с системными.
Если не подменять понятия, то реальный юзкейс — это именно создание потоков, которые отрабатывают и уничтожаются сразу, а не живут миллионами одновременно(это не имеет смысла из-за оверхеда на пробуждение). В этом юзкейсе системные потоки не уступают горутинам, которые должны быть быстрее.
>>Го вставляет проверки доступного размера стека в прологи генерируемых функций, если стека не хватает на нужды функции, то он растёт. Поэтому guard page нет, и это вполне безопасно.
Это дороже. Опять же — как вызывать нативные(сишные) функции?
>>Ну вот видите, покажет. Тоже вполне себе разница.
Разница в чистых цифрах никакая тем более в сравнении с го в котором есть гц.
>>В реальности будет больше
Не будет. Будет именно так, как посчитал я. Не согласны — предъявите основание вашего утверждения.
я не поленился — шесть раз
Я померил — го 70мегабайт, а птреды 260. Запускалось это на 30к тредах, ибо линукс в больше не может. Как я сказал — тред 8кило * 30к, что ~235 мегабайт, что соответствует реальности. 30к * 2к — это ~59мегабайт, что соответствует наблюдаемым.
Как мы уже выяснили — их «меньше» не преимущество, ибо в чистых цифрах оно ничтожно.
Зачем?
>>Потому что горутины — это не потоки.
Это потоки. Им можно какие угодно вешать шильдики, но это потоки.
Поток не про распараллеливание — поток про «поток» — т.е. про параллельное исполнение множества потоков управления.
Как и обычные потоки.
Насколько я знаю — это именно треды.
Т.е. если я создам цепочку горутина->канал->горутина и т.д. — это будет не один поток, а 2.
Всё это логика над потоком управления, вернее разделение одного на множество и сборка обратно. Треды — это про запуск этих потоков, а каким образом происходит этот запуска — это отдельная история.
Запускать это в горутинах, либо в потоках — разницы нет. Вернее как го-пацаны говорят, что есть, ибо горутины быстрее потоки, но это не совсем так, вернее совсем не так.
Да нет, это просто отмазки для избежания неудобной ситуации перед простым фактом — горутины не быстрее.
То, что в го есть какая-то логика поверх потоков — из этого ничего не следует. Прикрутить её можно куда угодно.
Были бы это не потоки, если бы все эти цепочки горутина->канал->горутина объединялись бы в цепочку калбеков в рамках одного потока.
У меня не работает мой код — он просто зависает и всё. Хотя причина вроде понятна — оно не завершается пока все горутины не завершены, даже если я их не жду, что странно.
Ну он не только в ядре сидел. Он сидел 100500 раз в ядре и 100500 раз в юзерпейсе.
Ну если в этих горутинах будет не инкремент атомина, который на фоне всего стоит в районе нуля, а что-то посерьёзней, то быстрее они уже не завершатся.
Надо определиться. В данном случае код запускается на в мейн-потоке, а в отдельной горутине. У меня мой код не работает и никаких реальных причин из-за которых он может не работает — нет, кроме каких-то слабых мест в реализации го.
Какие-то невероятные результаты. Скорее всего там 100к горутин.
Ну это уже цифры как у меня. Правда выжирает оно 2.5 ядра, что в 2.5 раза медленее птредов. Ниужели го более той болезнью, в которой обвиняли системные треды, при этом системные треды ею не болеют?
По поводу вашего кода — вайл там не столько для ожидания завершения, сколько эмуляции нагрузки на основной поток.
Сам же язык — это про удобство использования api и в редких случая для написания нового кода, но там кроме циклов и функций ничего нового особо не придумали.
А далее уже удобство использования самого языка и чьи-то синтаксические предпочтения. Кому-то нравится $i, а кому-то нет. Кому-то нравится экосистема одного языка, а кому-то другого. В целом при равной мощи рантайма разница между языками в „запилить быстро и удобно“ мало различима.
>>значит у него есть ниша, где он лучше других.
Скорее наличие ниши и делает язык лучше, ибо он более специализирован, а не наоборот. И то не сам язык(в очень маленькой степени), а его рантайм/реализацию самого языка.
Лучше в смысле как язык, то тут не всё так просто. Лучше в одном — хуже в другом.
Ну дак цикл там один, а вёдер у меня 8. И судя по тому, что я нагуглил — го не однопоточный, а может раскидывать всё это на несколько тредов, либо этого он не может?
А что ему мешается запустить в параллельном треде? Тем более он запустился — он же вызвал горутину в которой есть слип. В чём проблема?
Этот цикл — эмуляция нагруженного реального потока. Собственно это ещё одно причина из-за которой «горутины должны быть маленькие», хотя ничего не мешает расставлять какие-нибудь стоп-поинты(аля pthread_testcancel()).
Ну да, ведь горутины именно про это.
Судя по бложикам го, судя по хайпу вокруг горутин — все меня(и не только меня) убеждают в том, что ОС не может даже в 100тредов.
Нет. Я писал не так — я писал, что активных потоков может быть 30к из-за каких-то ограничений линукса. А так же я написал, что я не знаю таких юзкейсов где надо иметь больше 30к АКТИВНЫХ потока.
Сколько там мегабайт в стеке не имеет значение — занимать всегда будет столько, сколько используется кратно 4килобайтам.
Это тратит только адресспейс, которого:
И уж даже если взять под потоки 41бит — это в миллион раз больше, чем 2мегабайта.
Поменять же размер стека никаких проблем не состовляет:
Ну обычно у стека есть защита — последняя страница ставить с prot_none и при при заходе на неё падает с «сегфолтом».
Если у го её нет, то значит любая горутина может спокойно покараптить стек другой горутины, а если она есть — стек уже не 2кб, а 8кб минимум.
>>Вставьте задержку и посмотрите на maximum resident size, я думаю, что код на C++ покажет гораздо больший расход памяти.
Не покажет. Я уже объяснил причины. По поводу памяти — при любом стеке птреды будут занимать 8кб на один тред(страница активный + страница для защиты). Если в го — это 2кб, то будет занимать в 4раза меньше.
Опять же — ничего не мешает запилить аналог птреда и с 2кб стека, правда всех мало волнуют эти 100мегабайт на 100к тредов.
И опять же, как я говорил — гц в реальном приложении на го сожрёт куда больше.
Подмена понятий.
>>Я думаю, .NET будет лучшим выбором.
Не верно, ибо подмена понятий.
Никто не пишет сайты на .net. Никто не пишет сайты на языке — сайты пишут на готовом апи. И без разницы какой это язык, если ты вызываешь какой-нибудь интерфейс. Разница только в сахаре, но это не особо принципиально, да в современных ассемблерах сахара не меньше.
Подлог заключается в том, что вы сравниваете пацана с .net, который на 99% состоит из готового веб-рантайма и пацана с асм, у которого рантайма нет. Но ведь .net-пацан этот рантайм не писал — точно так же асм-пацан может его написать, либо взять готовое.
Если же взять нормальное сравнение, а не изначально ущербное, то никакой разницы не будет.
Реальный мир просто способствует продвижению этого мифа, ибо задачи на тех же сях решаются дольше. Но это следствие не того, что на сях «дольше», а просто задачи решаемые на сях сложнее. Живые сравнение Си вс жава не проводятся, ибо это не имеет смысла.
И какое отношение «было» имеет к сейчас и к го?
>>Однако, при неаккуратном использовании и они могли отнять все ресурсы системы.
Не могли. Никогда.
>> Каждый тред всё-таки занимал какие-то ресурсы, даже если был заблокирован.
Не занимал, а занимает. При этом точно так же он занимает в го, при этом это «занимает» ничего не занимает в сравнении с оверхедом ГЦ.
>>Чтобы ограничить число тредов, начали использовать тред пулы.
Не верно. Тредпул, если это именно тредпулл с постоянно живущими потами — существует не для это. Он существует для нивелирования оверхеда на запуск потока.
>>Горутины можно мыслить как задачи, выполняемые одним общим большим тред пулом. В Go горутины крайне дешевы.
Го тут непричём — го лишь одна из реализаций юзерпейс «тредов». И при этом «дешевы» — это не верно.
>>Вы можете запустить миллионы горутин без проблем для производительности.
Если под производительностью имеется ввиду как во всех бложиках «спящие треды не отъедают производительность» — это точно так же работает и в системных потоках.
>>Единственное требование — горутины должны быть «маленькие».
Не да, чтобы не надо было шедулить много активных горутин. Типичное проявление слабости шедуллера.
Я уже слышал столько легенд об «тормазящих системных потоках, которых нельзя запустить больше 20», «запустил 100системных потоков и даже спящие съедят 100% цпу» и прочее.
Но проблема как всегда в том, что когда адептам рассказывают что-то про «горутины вс системные треды» — почему адепты никогда не требуют доказательств? Сколько бы я не гуглил — я не увидел ни единого бенчмарка, либо сравнения с системными тредами.
Берём пишем простой бенч — создаём 100500(линукс больше не может, вернее он там и больше 30к активных не может) тредов с телом «инкремент атомика», а после смотрим за сколько все эти 100500 тредов отработали.
pthreads
Go
В конечном итоге мы видим, что го еле-еле на 30% быстрее. При этом эту разницу можно выкрутить почти в ноль, если затюнить pthread/ведро.
Ну и так же мы видим, что создание даже 100500 тредов, которые ничего не делаю нихрена не «бесплатно», а даже очень платно.
Если же впилить в С++ слипы в каждый тред, то оно отработает так же(правда надо уменьшить количество до 30к, иначе падает с «кончились ресурсы»). Если же впилить в го — оно встанет раком. Может я просто не так писал слипы в го?
>>альтернатива Си или Си++
>>Java
>>альтернатива
Спасибо — посмеялся.
>>Паскалю
>>такой как Оберон или Ада-95, спокойно могут держаться за него, не боясь оказаться в невыгодной «языковой ситуации».
Вся квалификация в одном предложении. Вернее её отсутствие. Мне жаль тех, кто ему поверил. Они оказались на задворках.
До появление жавы они воспевали «суперязыки» будущего, который дохли один за другим в небытие.
А по поводу «почему жава» — ну во-первых жава требует намного более низкой квалификации от данного «профессора» и шансы у оного осилить тот же С++ равны нулю, а уж про реальный си я даже заикаться не буду. Учить проще. Проверять проще. Но это всё не важно.
Основная причина — все эти вузы в сша сидят на грантах больших корпораций. Кто стоял за C/С++? К тому моменту дохлая Bell labs? А кто пропихивал жабку? Сан + корпоротивный сектор, который был опутан связями с сан и прочими вендорами, которые требовались новые адепты. Естественно С++ их не интересовал как излишне сложный и никакой в тот момент, хотя дава была ещё более никакая, но всяко лучше С++.
То же самое твориться и в вузах рашки(в центральной не так сильно), а вот на периферии и снг — во все поля — все под майкрасофтом как и этот ресурс. И точно так же «сишарпик наше всё, маздайка — наше всё и С/С++ не язык».
Всегда выгодней учить тому, что проще и тому, за чем стоят серьёзные дяди которые дадут пирожок и за кадры и за выбор. Особенно если эти дяди нас кормят — им не откажешь.
Ещё раз — мог бы ты что-то — ты бы не обделался, а не мог бы я больше тебя — я бы не победил. Всё просто.
>>Ваших комментариев не имеет никакой ценности в ситуации спора вне Вашей собственной головы — это очень печально.
Пока ты этого не доказал — твои потуги ничего не стоя, опять же — мой коммент — это ответ на твои потуги. А коли после моего ответа ответа от тебя по теме не последовало, а не по теме последовало — вывод один — ответить нечего, либо обделался/слился.
>>И, внезапно, если вы курлыкнули немного бреда, то оппонент вообще не обязан поддаваться приступу оверквотинга и разбирать каждую Вашу «ценную мысль».
Опять потуги убогие. Я могу тебя спросить за бред и ты обделаешься, как ты обделался по-теме, но зачем. Ты предпринял попытку спорить и ты пытался до определённого момента, если бы всё реально было так как ты сказал — ты бы написал это сразу, а не тогда, когда тебя загнали в угол. Либо хотя-бы ответил по теме, а потом начал кукарекать.
В конечном итоге всё просто — обделался, начал нести херню. Обосрался и здесь. Теперь уже пошли совсем детсадовские отмазки «я не обязан отвечать» — ты обязан — ты начал, тебя никто не заставлял. Начал спорить и съехал — проиграл.
>>Иногда случается даже так, что Ваш коммент представляет собой пустую трату байтов, вне зависимости от того, что там думают Ваш внутренний судья (он же прокурор).
Опять лсный балабол пытается себя приписать к байтам, да и вообще к теме. Смешно.
Споря с тобою — я не думаю — в этом нет смысла. Вернее как — я пытаюсь писать сдержано, дабы не ты не пошел доносить на меня. Хотя именно это ты и пытаешься сделать.
Как я уже сказал — очередная малоразвитая амёбка что-то строит из себя пытаясь взывать к публики таких же амёбок. При этом итак ясно кто победитель и почему. Каждый день по десять штук таких в спорах со мною обеделываются и их потуги ничего нового для меня не представляют, ибо все как под копирку один в один. Хотя все вылезли из одной парты и действуют по одной агитке.
Попытайся хоть что-то высрать мне по-теме.