
N
22.02.2017
17:23:56

Mike
22.02.2017
17:24:05
Жги

Ivan
22.02.2017
17:24:09
Если вас не затруднит
Но в целомс я часто про эти аллокации встречаю, хотелось бы в деталях понять.

Google

Mike
22.02.2017
17:24:28
Сколько можно про js object notation слушать)


N
22.02.2017
17:30:07
вобщем возьмем обычный TCP сервер и к нему клиента. надо обменятся данными. Открываем сокет как TCP (он потоковый в отличии от UDP). Обычно как делают с JSON - сериализнули в массив байтов и отправили в сокет сначало размер данных которые будем слать и сам сериализованный JSON (или еще чет кроме JSON) в массиве байт: [type: byte] [byteArrayLength: long] [array: []byte] - такая вот последовательность. на другом конце принимаем 8 байт размера и потом аллоцируем буфер такого размера и в него вычитываем, после этого десериализуем. вот аллокация буфера она лишняя получается. msgpack можно читать прям из сокета не передавая никаких дополнительных длинн пакета - сериализуешь прямо в сокет и читаешь прям обьект попутно десериализуя из сокета. Там сам формат располагает к этому - посмотрите спецификацию понятно будет, если вкратце то считав из сокета один байт первый ты знаешь сколько байт будет дальше за ним, потихоньку читаешь и превращаешь в обьект сразу.
в формате json нет данных о том сколько байт идет дальше, в msgpack эта инфа есть прям в его формате представления, поэтому никаких буферов аллоцировать не надо чтобы принять большой msgpack. кидаешь json по TCP на мегабайт - аллоцируешь мегабайт буфер в него читаешь потом десериализуешь, а если кидать msgpack то кидаешь его просто так как есть а на другом конце вычитываешь прям в реальный обьект без буфера на мегабайт


Daniel
22.02.2017
17:36:25
про json - чушь
в нем есть открывающая и закрывающая скобки
поэтому размер слать не надо
и про msgpack слегка гонево
алоцировать не надо не из-за размера, а из-за того, что протокол бинарный
в пакете на своих местах ровно те байты ровно в том количестве, что требуются для соответствующего типа данных
поэтому он zero-copy

N
22.02.2017
17:40:12
он не zero-copy ни разу это раз - тут совет разобраться что такое zero-copy к ним относятся такие форматы как capnproto, советую глянуть реализацию или хотябы поверхностно разобраться что такое zero-copy

Ivan
22.02.2017
17:41:10
Ну вот видите, а вы говорили не пятница дескать, зря пройдет.

Eduard
22.02.2017
17:41:26
шо то в го чате напряженка какая то

Google

N
22.02.2017
17:42:50
остальное тоже у тебя смешалось и люди и кони. Я хотел избежать хотябы в этот раз лишних обьяснений. json не имеет в формате своем никаких данных сколько дальше идет байт, поэтому быстро считать из сокета тупо не возможно. теоретически можно читать побайтово из сокета JSON на стейт машине - будет невероятно медленно, поэтому потоковых десериализаторов под JSON я не видел, которые вешают прям на TCP stream.

Daniel
22.02.2017
17:43:11

N
22.02.2017
17:43:51
да хоть на C# - проще для восприятия. есть реализация zero-copy сериализатора capnproto
от одного крутого товарища, могу ссылочку сейчас нагуглить

Daniel
22.02.2017
17:44:08

Ivan
22.02.2017
17:44:13
Ну мене кажется даже я понял. ну втсретили скобку открывающуюся, и что делать то, понятно что придется читать в буфер. и возможно буфер ещё и увеличивать пока не встретим закрывающую

N
22.02.2017
17:44:46

Daniel
22.02.2017
17:44:54
не надо
я, вообще-то, хорошо понимаю, как работает tcp
видимо, даже лучше тебя
даже если ты будешь из сокета вычитывать по одному байту - реальное чтение будет из буфера, в который пришел пакет

N
22.02.2017
17:46:02
ладно, буду обьяснять и по tcp тогда, чтоб остальные кто прочтет не ввелись в заблуждение. начнем с простого сейчас, но предварительно кину ссылку на zero-copy

Ivan
22.02.2017
17:47:37
#msgpack , я тут себе закладочку поставлю, если вы не против, а то усну в процессе, потом из за флуда не найти


N
22.02.2017
17:48:16
https://capnproto.org/news/2014-12-15-capnproto-0.5-generics-msvc-java-csharp.html
тут и на С# от Marc Gravell и на Java, что полагаю будет несколько ближе тебе
теперь про TCP: этот протокол осуществляет надежную передачу потока (!!!) байт с одной стороны в другую. то что под капотом это бьется на пакеты с сиквенсом и прочими делами по определенным правилам, дальше упаковывается в IP пакет и дальше в L2 пакет это и так всем понятно - любой нынче кто хочет все это может увидеть каким-нибудь Wireshark без проблем или еще чего. Но на выходе у TCP сокета поток байт бесконечный до закрытия соединения (Называется TCP streams) - есть логическое начало с открытием соединения и есть логический конец после закрытия и все что можно делать с ним это читать из этого потока и в него писать, а также спрашивать у API если ли чего сейчас там в буфере стрима в данный момент, если нет то ждать пока будет например. Передавая какой-то массив данных чтобы из этого массива сделать логическую единицу нам нужно либо передать размер и потом вычитывать этот размер, либо использовать такие же потоковые сериализаторы как msgpack, либо мудрить что-то свое. Как обычная работа с TCP сокетом устроена? Берем узнаем есть че прочитать и читаем сколько есть. Если не рвать соединение то где конец одной логической единицы? Как его узнать? Ответ: никак, если не передать эту информацию в этом же потоке - нужно описывать свою логику ОТ и ДО. Как отослать 10 файлов через TCP сокет? Ответ: шлем его длинну и потоком все его содержимое, на другом конце принимаем длинну и вычитываем ровно столько из сокета, потом ждем опять длинну следующего и вычитываем этот размер из сокета. Это блин очень просто для понимания. И да важный момент - если данных в стриме сейчас нет это не значит что это конец передачи - это вполне себе штатная ситуация для сетей как медленный канал или медленно отправитель отсылает или еще чего. Надеюсь после этого обьяснения вопросов не останется, а если останутся - гугл и книжки в помощь, а лучше немного практики и самому разок написать что-то поверх TCP голого


Roman
22.02.2017
18:03:08
теперь про TCP: этот протокол осуществляет надежную передачу потока (!!!) байт с одной стороны в другую. то что под капотом это бьется на пакеты с сиквенсом и прочими делами по определенным правилам, дальше упаковывается в IP пакет и дальше в L2 пакет это и так всем понятно - любой нынче кто хочет все это может увидеть каким-нибудь Wireshark без проблем или еще чего. Но на выходе у TCP сокета поток байт бесконечный до закрытия соединения (Называется TCP streams) - есть логическое начало с открытием соединения и есть логический конец после закрытия и все что можно делать с ним это читать из этого потока и в него писать, а также спрашивать у API если ли чего сейчас там в буфере стрима в данный момент, если нет то ждать пока будет например. Передавая какой-то массив данных чтобы из этого массива сделать логическую единицу нам нужно либо передать размер и потом вычитывать этот размер, либо использовать такие же потоковые сериализаторы как msgpack, либо мудрить что-то свое. Как обычная работа с TCP сокетом устроена? Берем узнаем есть че прочитать и читаем сколько есть. Если не рвать соединение то где конец одной логической единицы? Как его узнать? Ответ: никак, если не передать эту информацию в этом же потоке - нужно описывать свою логику ОТ и ДО. Как отослать 10 файлов через TCP сокет? Ответ: шлем его длинну и потоком все его содержимое, на другом конце принимаем длинну и вычитываем ровно столько из сокета, потом ждем опять длинну следующего и вычитываем этот размер из сокета. Это блин очень просто для понимания. И да важный момент - если данных в стриме сейчас нет это не значит что это конец передачи - это вполне себе штатная ситуация для сетей как медленный канал или медленно отправитель отсылает или еще чего. Надеюсь после этого обьяснения вопросов не останется, а если останутся - гугл и книжки в помощь, а лучше немного практики и самому разок написать что-то поверх TCP голого
+много
Вот честно
И нет в tcp способа узнать что данные отправлены или получены
Точнее, отправленные данные получены

Google

Daniel
22.02.2017
18:06:17
что приложение данные вычитало - это, конечно, никак не выяснить
но при чем ту json и отправка длины?
у json есть маркер конца (как и у smtp, например)

N
22.02.2017
18:07:47

Daniel
22.02.2017
18:11:24
не надо, я в курсе

N
22.02.2017
18:11:31
если вкратце это невероятно медленно, даже если лепить промежуточный стрим с буфером, который немного прироста даст производительности
чтение будет побайтовым на стейт машине - никак иначе

Daniel
22.02.2017
18:12:07
а оно все равно таким будет, извини
такой уж формат

N
22.02.2017
18:12:26
да, именно формат

Daniel
22.02.2017
18:12:33
конечно, по сисколу на байт - это будет жестко
но в go это, слава создателям, не так

N
22.02.2017
18:14:09
да там можно через доп буфер читать, что несколько ускорит, но один хрен медленно. и то и то ручками делал сам - и парсер json и msgpack, который вешал прям на стрим через буферизированный поток для ускорения сетевого взаимодействия

Daniel
22.02.2017
18:14:49
что медленно-то?

N
22.02.2017
18:14:51
поэтому выше я написал че делаем если шлем json и чего делаем если берем msgpack
передача + десериализация без лишней аллокации - вот что медленно

Daniel
22.02.2017
18:15:26
json сам по себе никто не шлет, это правда. или http, или websocket
и тот, и другой снабжают сообщение размером.

Google

N
22.02.2017
18:15:49
а я про потоковую передачу
выше тему эту начал

Daniel
22.02.2017
18:16:40
но, вообще-то, никто не мешает с одной стороны json в сокет засунуть, а с другой - вычитать

N
22.02.2017
18:17:38
я хотел избежать обьяснений почему так никто не делает
поэтому написал как делают и чем хорош при этом msgpack

Daniel
22.02.2017
18:18:28

N
22.02.2017
18:19:44
и?

Daniel
22.02.2017
18:20:36
"никто не делает" и "в стандартной либе есть соответствующий метод" - противоречат друг другу, правда?

N
22.02.2017
18:27:08
ща все обьясню)

Daniel
22.02.2017
18:27:52
кому?!
если мне - не надо, я в курсе

Ivan
22.02.2017
18:28:16
Я б послушал

Daniil
22.02.2017
18:29:02
Я бы тоже. А то у меня целый TCP сервер общается по JSON

Sergey
22.02.2017
18:49:45

Oleh
22.02.2017
18:52:29
кто то работал с go-sciter ? норм вещь или дрянь редкостная?

Daniel
22.02.2017
18:58:19

Sergey
22.02.2017
18:59:10
Ну по крайней мере сишный интерфейс там оооочень странный


N
22.02.2017
19:00:16
если мне - не надо, я в курсе
ну нет так нет. Для остальных: то что по ссылочке выше это тоже самое, что я описывал несколько выше - чтение с буфером из потока JSON. Буфер несколько ускоряет вычитывание из потока за счет более быстрого освобождения буфера источника, а если источник это TCP сокет то чем быстрее буфер сокета освободим тем быстрее он сможет наполнится новыми данными. Процесс десериализации JSON медленнее чем передача допустим по гигабитному каналу в хороших условиях и чтобы не деградировать коннект до скорости десериализатора втыкают буфер, что несколько ускоряет процесс. А дальше - под капотом там все таже машина состояний с посимвольным чтением из промежуточного буфера - это невероятно медленно. В сравнении: msgpack передает информацию о размере строки - чтобы понять где ее конец в массиве байт не надо бежать посимвольно попутно ловя закрывающую кавычку у строки со всеми вытекающими - тупо мы заранее знаем какая длина у строки вычитываем это кол-во байт и преобразуем в строку. Поэтому целять JSON на поток TCP это я хз что может быть хуже, разве только XML. Для ускорения JSON обычно жертвуют памятью - быстро из сокета целиком вычитывают полный JSON и потом его потрошат в обьект, но доп аллокации если говорим про Go


Sergey
22.02.2017
19:00:48
Распаковываю msgpack array, надо какие-то энумы проверять в цикле с распаковкой, я так и не разобрался чем отличаются MSGPACK_SUCCESS и MSGPACK_CONTINUE

N
22.02.2017
19:04:08
дополню - доп аллокации в контексте Go говорят о мусоре и жоре памяти. На один процесс лично я ловил потребление процессом памяти более 10 гигов при этом скорость была более-менее, пробовал лепить на стрим JSON - долго и убого, никуда не годится. sync.pool не канают, пакеты разного размера, считать перцентели и динамически подгонять тоже особого понту нет. берем msgpack получаем сразу прирост по скорости и снижаем атоматом потребления памяти - Profit. Как я полагаю нить суждения уже потеряна, но началось с того что был вброс о том что mgpack «плохо», решил рассказать где он - это хорошо

Google

Ivan
22.02.2017
19:06:21
А как он сам в структуры ложится, что то такое выше было. У него схема есть ? Валидация ?

Daniel
22.02.2017
19:06:59
я бы хотел обратить внимание публики на то, что json медленный не потому, что посимвольное чтение, а потому, что текстовый

N
22.02.2017
19:07:23

Daniel
22.02.2017
19:07:57

Ivan
22.02.2017
19:07:59
Получится невалидное сообщение передать

N
22.02.2017
19:08:03
Получится невалидное сообщение передать
если некорректно сериализовать то да, целостность данных проверятся на TCP поэтому транспорт гарантирует доставку и берет это на себя, а если сериализатор с ошибками то можно передать и не валидный вариант. Если говорим что сериализатор без ошибок то приедет все корректно - ровно то, что передано и превратится ровно в то, что передано после десериализации

Ivan
22.02.2017
19:09:57
Второй вопрос, на клиенте js -ры, будут иметь проблемы его читать ?

Daniel
22.02.2017
19:10:06
либы есть
но он бинарный же

Sergey
22.02.2017
19:10:12

Ivan
22.02.2017
19:10:51
А тулинг , ну типа там курлом послать ?

N
22.02.2017
19:10:56

Ivan
22.02.2017
19:12:12
А проверить сообщение на соответствие схемы ? Пусть после чтения в буфер.


N
22.02.2017
19:18:19
А проверить сообщение на соответствие схемы ? Пусть после чтения в буфер.
давай по простому - mspack это альтернатива json. более компактная за счет бинарного представления и годится для потоковых передач по сети за счет своего формата и самое главное он более быстрый опять же из-за формата и более компактного представления. все остальное как с json, только он не человеко читаемый и забросить его по http курлом задача не такая простая как с json. API работы обычно совпадает с привычной работой с JSON во многих реализациях. В msgpack есть зарезервированные байты для реализации собственных типов - я брал описывал в одной задачке все свои типы прям в сериализаторе и гонял по сети очень быстро, соотвественно в процессе десериализации сразу валидировался формат, который приехал - все типы были жестко описаны и это покрывало все возможные потребности по этой задачке на 10 лет вперед

Ivan
22.02.2017
19:19:14
Я понял, спасибо.

N
22.02.2017
19:19:29
стандартные типы а-ля словарь или массив идут из коробки
чуть сложнее описывал ручками там прям

Ivan
22.02.2017
19:19:57
Получается что простым смертным у которых прблемы быстродействия нет, геморроится незачем.

Daniel
22.02.2017
19:20:38