Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > обертка над asio сокетом |
Автор: boostcoder 10.4.2011, 20:11 | ||||
всем доброго вечера. хочу написать обертку над asio сокетом, дабы улучшить юзабильность. хочу избавиться от ручного написания байнда и хранения записываемого буфера до окончания асинхронной операции. это и хочу обсудить. сейчас вижу интерфейс таким:
чтоб использовать так:
первый вопрос - есть ли смысл вообще в обертке? второй вопрос - в случае записи указателя на char, есть ли смысл копировать данные в какой-то внутренний буфер обертки? или просто запоминать указатель, по при вызове хэндлера - освобождать память на которую он указывает? третий вопрос - что вообще нужно такой обертке, и что не нужно? спасибо. |
Автор: bsa 10.4.2011, 23:51 | ||
ни в коем случае. Память освобождаться должна там, где была выделена. |
Автор: boostcoder 11.4.2011, 11:14 |
допустим... тогда встает вопрос о размере внутреннего буфера обертки. 1. должен указываться в конструкторе? 2. или увеличивается столько, сколько свободной памяти на машине? 3. расходы на выделение памяти/копирование не пугают? у меня есть такое предложение: обязать пользователя передавать в сокет смарт_поинтер инициализированный/заполненный юзером. в этом есть есть два плюса: 1. не нужно ничего копировать. т.к. внутренний буфер становится очередью из смарт_поинтеров 2. не нужно руками освобождать память. |
Автор: mes 11.4.2011, 12:00 | ||
нельзя ли пример строчки которая Вас не устраивает, с указанием неугодных моментов ?.. |
Автор: borisbn 11.4.2011, 12:44 | ||||||||
IMHO некрасиво
внутренний буфер будет увеличиваться только в том случае, если юзер будет подавать данные быстрее, чем они будут уходить получателю... Если юзер так рассчитал систему - то он сам виноват. Библиотека (обёртка) тут не при чём. Думаю, что сама отправка (скорость передачи по каналу) будет на порядки дольше, чем обращение к менеджеру памяти и копирование из одной области памяти в другую. Даже если передача данных будет происходить по 127.0.0.1
В этом случае юзерская ф-ция отправки, например, строки будет выглядеть некрасиво
вместо
|
Автор: boostcoder 11.4.2011, 16:32 | ||||||||||||
тут Вы ошибаетесь. в http://forum.vingrad.ru/forum/topic-325353/view-all.html теме, возьмите последние исходники и посмотрите. там очень простой код. выделение 13 байт, sprintf(), передача в async_write(), в хэндлере delete[]. ничего сложного ведь ;) но на 100мбитной сети, происходит 220000-250000 таких последовательностей, что полносьтю загружает одно ядро. вроде бы казалось, ничего сложного в этих операциях нет. но профайлер говорит что 48 процентов времени уходит только на new! в общем, выделение памяти и инициализацию смарт_поинтера оставил на юзера. помоему, очень даже юзабельно получилось ![]() пожелания/рекомендации/критика приветствуются. класс сокета:
пример 1:
пример 2:
пример 3:
всем спасибо ![]() Добавлено через 6 минут и 9 секунд
не нравится постоянно писать байнд. в добавок, если сигнатура не соответствует, или не соответствует кол-во плейсхолдеров, или их вовсе нет - то глядеть в 120 строк вывода об ошибке сомнительное удовольствие. |
Автор: boostcoder 11.4.2011, 16:53 |
эм... такой вопрос: а есть ли смысл добавлять методы для синхронных операций? IMHO - лишнее. |
Автор: borisbn 11.4.2011, 17:15 | ||||
профайлер не знает, сколько времени уходит непосредственно на отправку/приём, т.к. они асинхронные В Вашем примере ровно столько же new делается на стороне клиента юзера
думаю, что эти new как-то можно соптимизировать. и лучше это сделать в одном месте - в обёртке, а не каждый раз у юзера. А не замахнуться ли нам на Вильяма нашего Собственного Менеджера Памяти ![]() думаю, Вы правы. Лишнее. А вот добавить [необязательные] handler'ы connected и disconnected можно ![]() |
Автор: boostcoder 11.4.2011, 17:21 | ||||
это да. но я хотел сказать то, что ко всем new не нужно еще и добавлять расходы на копирование.
как, например? пул памяти? ага. а потом кто-то скажет еще добавить аксессоры для ip:port, и что-то еще ![]() у обертки есть метод socket() который возвращает ссылку на внутренний сокет. а у него есть все необходимые методы. эта обертка - всего лишь сокет. над ней можно написать другую обертку, к примеру обертку сериализатора/десериализатора для абстрагирования от типа. т.к. сейчас обертка работает только с массивом чаров. |
Автор: boostcoder 11.4.2011, 17:39 | ||
предлагаешь написать менеджер памяти? и кто такой "Вильяма" ? |
Автор: mes 11.4.2011, 18:40 |
http://www.bibliotekar.ru/encSlov/a/25.htm |
Автор: boostcoder 11.4.2011, 18:43 |
mes, спасибо. я никогда не понимал классику. потому не смотрел. потому не знаю таких высказываний. хотя... http://ru.wikipedia.org/wiki/%D0%9A%D0%B8%D0%BD-%D0%B4%D0%B7%D0%B0-%D0%B4%D0%B7%D0%B0! мне нравится. помоему это единственное из классики что я могу посмотреть без принуждения.. |
Автор: boostcoder 11.4.2011, 19:02 |
mes, кстати. как Вам такой сокет? ;) |
Автор: phprus 11.4.2011, 20:37 | ||
Аллокации, влияют не так сильно, а вот копирование памяти, ее предварительное зануление(если используется std::vector) начинает тормозить уже на скорости обмена с сетью порядка 200Мбит/с (выведено из опыта излишней буферизации в своем приложении), то есть скорость работы приложения ограничивается скоростью копирования памяти. shared_ptr не может принимать массивы, и не во всех случаях безопасен при многопоточности. В первом случае есть shared_array, а второй так просто не решается :( |
Автор: mes 11.4.2011, 21:00 |
внимательно не рассматривал, но интуитивно не очень.. |
Автор: boostcoder 11.4.2011, 21:48 |
запустите код из http://forum.vingrad.ru/forum/topic-325353/view-all.html темы под профайлером. и сами посмотрите на результат. не думаю что профайлер врет. это интересный момент.. |
Автор: borisbn 12.4.2011, 09:40 |
принимать может ( http://liveworkspace.org/code/93c25ddc57b2e363cc6880d858a56139 ) удаляет неправильно (без []) |
Автор: mabrarov 12.4.2011, 23:36 | ||||
Вы просто забыли, что такое шаблон Proactor и как важен для него механизм, предоставляемый Boost.Asio: custom memory allocation (http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio/overview/core/allocation.html) С этим механизмом (с его применением) Вы сильно удивитесь резвости asio, так как в этом случае все аллокаци во всех используемых очередях (io_service, io_service::strand, deadline_timer) могут свестись к банальному:
|
Автор: boostcoder 13.4.2011, 01:39 |
mabrarov, Марат, здравствуйте ;) по приведенной вами ссылке, читал, и не раз. не могли бы Вы популярно объяснить, и, желательно с примером. буду сильно благодарен. спасибо. |
Автор: mabrarov 13.4.2011, 02:14 | ||
А я думал, что уже достал Вас ![]() Объяснить проще, чем в примерах Boost.Asio, я не смогу. К сожалению, проще уже некуда. Могу только пояснить следующее: как любая система построенная по шаблону Proactor (да и вообще - как все многопоточные системы, базирующиеся на очередях - т.е. почти все более-менее "продвинутые" многопоточные системы, например, Intel TBB), asio активно использует очереди (в случае asio - это очереди из функциональных объектов). В связи с этим остро встает вопрос выделения памяти в таких очередях (особенно остро в свете многопоточности и кешей процессора). Intel TBB решает это своим "прокаченным-специализированным" аллокатором (и обещаниями повторно использовать выделяемые блоки). asio использует очень легкое и гибкое решение (и это не единственный случай!): позволяет использовать allocator per async operation (начиная с dev release 1.53 - во всех асинхронных операциях). И вот какая штука: в любом вменяемом (т.е. не "hello world") приложении количество одновременных однотипных асинхронных операций над одним и тем же объектом (например, socket или deadline_timer) всегда ограничено сверху. И зачастую это ограничение равно единице (Вы уже на него нарвались недавно). Исходя из всего вышесказанного, зачастую, Вы можете просто заранее выделить непрерывный блок памяти, который будет удерживаться Вашим handler-ом (например, при помощи shared_ptr). Затем, каждый раз когда asio будет нужна память для чего-то временного (обычно, это память для расположения в очереди - IOCP или boost::asio::io_service::strand или даже deadline_timer), что связанно с асинхронной операцией, для которой Ваш handler является completion handler-ом - asio просто попросит об этом через Ваш же handler. При этом те гарантии что дает asio относительно custom memory allocation, гарантируют, что (при достаточном размере Вашего пред-аллоцированного блока памяти) Вы всегда сможете выделить эту память из того самого, ранее выделенного, блока памяти. Кроме того, гарантии asio позволяют удерживать этот "пред-аллоцированный блок памяти" самим же handler-ом (с небольшим ограничением на handler - см. доки по Boost.Asio 1.53, почти всегда это ограничение выполняется и уж точно всегда его можно легко обойти). Главное, хранить в handler-е не сам блок, а указатель на него (лучше -smart) - чтобы в блок помещался сам handler + что-то временное. В моем проекте (http://sourceforge.net/projects/asio-samples) echo_server (и qt_echo_server, и, вообще, все "asio samples") вообще не выделяет память в куче при своей непосредственной работе (кроме приема новых входящих TCP-соединений, да и тут есть reuse). Custom memory allocation сводит все выделения памяти к тому коду, что я указал - т.е. никаких блокировок и даже никаких атомарных (interlocked) операций. Плюс, в теории (не могу до сих пор проверить) - это должно очень положительно сказаться на использовании CPU-кеша (+ учтите очень правильную реализацию strand-ов в asio). |
Автор: boostcoder 29.5.2011, 06:52 | ||
возможно я не туда смотрю.. вот дока asio-1.4.9 входящая в состав boost-1.46.1: http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio/overview/core/allocation.html а вот дока asio-1.5.3 с офф. сайта: http://think-async.com/Asio/asio-1.5.3/doc/asio/overview/core/allocation.html не вижу разницы. или я не туда смотрю? |
Автор: mabrarov 30.5.2011, 10:07 | ||||
Вот и я не увидел. Но в release notes к asio-1.5.3 все четко сказано. А уж в коде я сразу "порылся" 8) - ждал этого с самого рождения asio. Не увидел и написал Christopher M. Kohlhoff об этом. Он вежливо поблагодарил за замеченную неточность и... ничего не исправил. |
Автор: boostcoder 30.5.2011, 10:21 |
![]() "великий OpenSource" (с) остается ждать. |
Автор: mabrarov 30.5.2011, 10:47 |
К слову, документация у Christopher M. Kohlhoff ну просто очень и очень хорошая (только надо не забывать, что примеры в ней тоже являются обязательным чтивом). Думаю: 1) когда asio-1.5.3 войдет в Boost C++ Libraries, все будет исправлено; 2) сразу после выхода asio-1.5.3 Chris уже должен был готовиться к http://boostcon.boost.org/2011-resources; 3) судя по тому, что я читал в рассылке asio-users, он действительно занят коммерческими проектами, остается только поражаться тому, как он находит время и силы и вносит столь серьезные (и долгожданные) изменения, как move semantic support и custom memory allocation support for SSL async operations. |
Автор: boostcoder 30.5.2011, 10:54 | ||
не могу согласиться. увы :( полагаю, сейчас отпишется не один программист, разделяющий мою точку зрения ;) ибо я такое слышу каждый день(ну почти) от знакомых и коллег. |
Автор: mabrarov 30.5.2011, 11:25 | ||
Радует, значит про Asio на просторах СНГ слышали и даже используют. А если чего-то в документации Asio не хватает, то... для этого и существуют asio samples. Дай бог времени и желания - напишу пару статей на русском про наиболее частые ошибки разработчиков, пытающихся использовать Asio вопреки определенным в документации ограничениям/гарантиям. Ну и да, это Open Source (и даже не GPL) - поэтому прежде чем переводить production code на Boost.Asio я внимательно изучал его исходники. Это многое открывает, особенно в плане понимания производительности Asio в сравнении с "raw WinSock". Сравните документацию по Boost.Asio с документацией по ACE или даже с книгами по ACE. |
Автор: boostcoder 30.5.2011, 11:42 | ||
вставьте-ка лучше ссылку в подпись. найти будет легче. и, возможно, гугл проиндексирует.
когда я только начал постигать _network_programming_in_c++_, я пересмотрел несколько библиотек, и ACE одна из них. но от нее я отказался, в виду монструозности. поэтому не юзал. и о качестве документации вряд-ли смогу сказать уверенно. |