Re[27]: Mногопоточность: C++ vs Erlang vs другие
От: Evgeny.Panasyuk Россия  
Дата: 17.06.15 10:14
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Т.е. лямбда создаётся на стеке, но при сохранении её в std::function, происходит создание её копии в куче, потому что объект function устроен как-то так (схематично):


Естественно оно будет в общем случае в куче, так как происходит стирание типа, и соответственно размера.

EP>>И почему stackless корутина должна размещаться в каком-то другом месте?

V>Потому что, как и в случае std::string, для которого тоже есть некая оптимизация "маленьких" значений, реальный размер корутины заранее предугадать невозможно.

Это "потому что" никак не отвечает на поставленный вопрос. При стирании типа (как в std::function или .then), это справедливо и для передачи замыкания-лямбды, и для передачи корутины.
Как ответ на вопрос нужно показать чем объект-корутина отличается от лямбды в этом контексте, и почему её нужно размещать в другом месте. Ты же привёл общую для них характеристику, никак не обосновывающую необходимость отличий при размещении.

V>>>Я бы его разместил в объекте-наследнике того самого shared_state, который, в свою очередь, создаётся на куче.

EP>>А здесь можно вообще не менять ни сам future, ни лезть в его внутренности (типа наследования от shared_state). Потому что используем ли мы обычные продолжения, или объект-автомат (ручной или сгенерированный stackless coroutine) — это совершенно ортогонально тому где мы их размещаем.
V>Если используем future, то у нас в любом случае будет выделение памяти из кучи. Я лишь предлагаю свести кол-во выделений к минимуму, реализовав корутину как наследника future, либо как в случае с make_shared, просто расположив оба объекта в одном куске памяти (что фактически идентично с т.з. использования памяти). И я УВЕРЕН, что это именно так и будет. Даже могу поспорить на денюжку. )) Сорри, но это слишком очевидно, чтобы это "промухать". Не промухают, я уверен.

Подобная оптимизация возможна и для обычных замыканий, и для объектов-корутин которые я предлагаю — так как внутри .then мы знаем их размер, и можем аллоцировать их вместе с другими аллоцируемыми объектами за одну аллокацию (как в make_shared). Причём код оптимизации будет идентичным для обоих случаев, и авторам этой оптимизации вообще ничего не нужно знать о том что существуют ещё какие-то корутины.

В случае же proposal от microsoft, корутина аллоцируется своим отдельным аллокатором. И даже если оптимизация подобная make_shared и возможна — то автор future должен знать о том что у замыкания есть свой аллокатор, и писать отдельный код для этого случая.
Причём это относится не только к какой-то одной реализации future — а ко всем подобным. Специальный код должен быть в каждом случае.

EP>>Ты понимаешь что над корутинами из Boost.Asio можно сделать обёртку-итератор, в котором полностью будет хранится вся корутина? Или показать пример?

V>Не надо пример. Я, как раз, понимаю о чем речь, но ты не вникаешь в суть моих вопросов. Я всегда спрашиваю одно и то же — какой будет тип результирующего объекта?

Посмотри ещё раз сюда
Автор: Evgeny.Panasyuk
Дата: 12.06.15
— у корутины есть тип, имя этого типа задаётся объявлении корутины, то есть struct coroutine, или с синтаксическим сахаром — future<void> coroutine().
Это обычный тип, никакой магии.

V>Можно ли объявить переменную этого типа БЕЗ объявления корутины, а реальную корутину присвоить "потом" — как в твоём сценарии сериализации?


Конечно можно — это банальное type erasure, такое же как и в std::function.

V>>>Если твоя легковесная корутина будет содержать в себе другие корутины, то нужно эмулировать стек для их правильного обхода. И тут уже, извини, но без выделения памяти в куче — никак.

EP>>Зачем?
V>Для рекурсии. В т.ч. всевозможной неявной, через вызовы, скажем, захваченных в лямбду методов-переменных.

Только в случае корутинной рекурсии. То есть:
1) если в корутине вызывается обычная рекурсивная функция типа quicksort — то используется стандартный стэк.
2) если в корутине вызывается другая корутина, без рекурсии, то никакой динаимики — размер обеих известен во время компиляции.
3) если происходит простой рекурсивный вызов корутины, то получим ошибку incomplete type, который обходится динамикой, конкретнее — стэком корутин.

Не вижу в этом проблемы. В proposal от Microsoft динамика же будет во всех трёх случаях.

EP>>Вложенная корутина будет просто полем объекта внешней корутины

V>Ты забыл, что корутина у нас stack-less, поэтому стек ей придётся нарисовать ручками. И этот стек — штука динамическая, увы))
V>Поэтому — в куче.

Только в случае рекурсивных корутин

EP>>Вот пример, в нём нет никаких аллокаций в куче

V>(скипнул пример)
V>В этом примере нет, ес-но. Потому что нет недетерминированного стека вызовов.

А в proposal от Microsoft есть аллокации, хотя их вообще тут не должно быть.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.