Я разобрался https://habr.com/ru/post/724682/. Дело действительно в Nagle. TL;DR: NODELAY надо выставлять с обеих сторон. Сочетание write+write+read - проблемное, ненадотак.
Не соглашусь, в некоторых случаях бывает оправдано размещение именно на одной машине. В частности, когда мы хотим существенно более быстрое взаимодействие между этими сервисами. Понятно, что кейс наверное в текущих реалиях не самый частый, но тем не менее.
Тестовый пример на то и тестовый, переписать на 8 версию не так сложно (тем более, что сборку расширения под 8.2 я уже починил).
Если не нужно очищать ресурсы, то по идее надо сохранять объект, который ими управляет, в области видимости (ну, вернуть его там или сохранить куда). А про finally согласен. В этом плане становится сложно, например, в C#, ибо даже вылетевший из области видимости объект, вообще говоря не удаляется. И что делать, кроме как явно очищать всякие файлы и сокеты (или возиться с IDisposable, но по сути, тоже, явно) - непонятно.
Справедливости ради, не golang единым - примерно в любом языке, где есть деструкторы или обработка исключений (в лице блока finally), goto в кейсе "не забыть очистить ресурсы", особо-то и не нужен. А вот break/continue с метками был бы полезен, много где.
Подозреваю, что "под капотом" что shmget/shmat, что shm_open/mmap обращаются к одним и тем же механизмам ядра, API просто разное. Потому думаю, что существенной разницы в производительности не будет. Но для POSIX разделяемой памяти, опять же, надо своё расширение к PHP писать (как и с семафорами).
Имеете в виду, положить php-объект сразу в расшаренную память? Звучит интересно. Чисто технически, можно написать расширение, которое будет создавать объекты (ну, хотя бы строки), которые сразу доступны из обоих процессов.
Про shm_get_var не в курсе, но вполне возможно она делает именно то, что вы описываете.
Да, когда я писал расширения к Perl, там у меня как раз была сборка Perl-объекта на стороне C++ и возврат его в Perl целиком. Единственное неудобство - так как в Perl сборщик мусора основан на ссылках (refcount), надо очень аккуратно за ними следить, я в какой-то момент долго разбирался, почему память утекает.
Да, но тогда строго говоря надо самостоятельно следить за потерями пакетов и что-то предпринимать по этому поводу (мы ж не можем просто "забить" на непришедший ответ). Понятно, что в рамках одной машины пакеты скорее всего теряться не будут, но строго говоря никто этого не гарантирует :-)
В тестовом сервере обработка заключается в банальном проходе по строке и подсчёту числа символов с разными кодами. Потому вряд ли в скорости обработки дело. Возможно сказывается время на первичную установку коннекта. Для интереса прогнал тест с 1000000 запросов, результаты вот:
Статический метод - дак по имени класса же FB.fb(x). А изнутри объекта (из не-статического метода) - просто по имени.
Дело не в том, что близко к сердцу или нет, а в том, что "что мы доказываем". Если доказываем "на языке X можно быстро написать что-то годное за счёт удобных языковых средств" - в таком случае непонятно, зачем мерять производительность (ну т.е. это прям совсем не основная характеристика при таком сравнении), а надо скорее сравнивать лёгкость написания / понимания / расширения.
А если доказываем "на языке X можно написать, чтобы быстро работало" - то тогда надо сравнивать более-менее идиоматичные способы написания "чтобы быстро работало". Ну либо бескомпромиссно оптимизировать, но эт уже нужны специалисты в каждом конкретном ЯП и лучше тогда в виде соревнования какого-то.
В общем, я не очень понял, что хотели сравнить, отсюда и вопросы.
Что же касается размера влинкованного рантайма (или размера интерпретатора) - дак он сильно зависит и от компилятора в том числе. Хотя конечно даёт некоторую информацию на тему "сколько надо потратить места, чтобы на сферическом компьютере в вакууме запустить эту программу". С другой стороны - когда он статически слинкован, нам на каждую программу своя копия рантайма нужна, а если мы про php там или джаву, то он более-менее один на всех. Впрочем, эт уже отдельная история.
Очень странное сравнение, как по мне. Если уж сравнивать производительность - то не решения "в лоб" или решения "максимально задействующего синтаксический сахар", а "решения, в котором сколько-нибудь заморочились с производительностью".
В плюсах - если уж хотим использовать iostream, то стоит выключить синхронизацию с stdio, чтобы буферизация работала std::ios::sync_with_stdio(false); . Там же, в плюсах, похоже компилятор решил весь C++-ный рантайм статически слинковать. Оно конечно удобно, но вообще говоря не то чтобы принято (ну т.е. под винды стоит компилировать MSVC и использовать его системные dll-ки, под пингвинов - системный же libc).
В джаве я не очень понял, зачем делать объект FB внутри main, а потом дёргать у него статический метод, в котором снова создаётся объект того же FB.
Вот к go, python и php придраться особо негде, по крайней мере на первый взгляд. А в остальных я не силён.
Про Retry-After давно не слышал. Хотя в университете про HTTP и его заголовки очень даже рассказывали (и даже просили написать HTTP-сервер).
А вот про Authorization не со всем соглашусь - бывает, что нужно всю информацию, требуемую для запроса, положить в URL. Например - токены доступа по ссылке (когда нужно что-то расшарить людям, которым известна ссылка, по типу документов в Google Drive). Потому в каждом случае надо отдельно разбираться.
А ещё, раз уж про авторизацию заговорили, можно вспомнить Basic HTTP Auth, для которого в частности имя пользователя и пароль можно задавать прямо в URL: <scheme>://<user>:<password>@<host>/<path>. И это даже вполне себе работает.
Увы, фоток датчика не осталось. Впрочем, там ничего сверхъестественного - два джека 3.5 и от них кабель, на конце обмотанный изолентой (внутри резисторы и термистор.
Я разобрался https://habr.com/ru/post/724682/. Дело действительно в Nagle.
TL;DR: NODELAY надо выставлять с обеих сторон. Сочетание write+write+read - проблемное, ненадотак.
APCu я бы тут отнёс к читерству, потому что добраться из не-php процесса до этого самого APCu будет проблемно.
Да, почитал, там внутрях SysV https://github.com/krakjoe/apcu/blob/master/apc_shm.c
И совершенно логичным образом всех заруливает "ручная" работа с памятью через FFI :-)
Не соглашусь, в некоторых случаях бывает оправдано размещение именно на одной машине. В частности, когда мы хотим существенно более быстрое взаимодействие между этими сервисами. Понятно, что кейс наверное в текущих реалиях не самый частый, но тем не менее.
Тестовый пример на то и тестовый, переписать на 8 версию не так сложно (тем более, что сборку расширения под 8.2 я уже починил).
Пофиксил, теперь должно собираться.
Если не нужно очищать ресурсы, то по идее надо сохранять объект, который ими управляет, в области видимости (ну, вернуть его там или сохранить куда).
А про finally согласен.
В этом плане становится сложно, например, в C#, ибо даже вылетевший из области видимости объект, вообще говоря не удаляется. И что делать, кроме как явно очищать всякие файлы и сокеты (или возиться с IDisposable, но по сути, тоже, явно) - непонятно.
Справедливости ради, не golang единым - примерно в любом языке, где есть деструкторы или обработка исключений (в лице блока finally),
goto
в кейсе "не забыть очистить ресурсы", особо-то и не нужен.А вот break/continue с метками был бы полезен, много где.
Подозреваю, что "под капотом" что
shmget/shmat
, чтоshm_open/mmap
обращаются к одним и тем же механизмам ядра, API просто разное.Потому думаю, что существенной разницы в производительности не будет. Но для POSIX разделяемой памяти, опять же, надо своё расширение к PHP писать (как и с семафорами).
Имеете в виду, положить php-объект сразу в расшаренную память? Звучит интересно. Чисто технически, можно написать расширение, которое будет создавать объекты (ну, хотя бы строки), которые сразу доступны из обоих процессов.
Про shm_get_var не в курсе, но вполне возможно она делает именно то, что вы описываете.
Да, когда я писал расширения к Perl, там у меня как раз была сборка Perl-объекта на стороне C++ и возврат его в Perl целиком. Единственное неудобство - так как в Perl сборщик мусора основан на ссылках (refcount), надо очень аккуратно за ними следить, я в какой-то момент долго разбирался, почему память утекает.
Пожалуй, это стоит отдельно поизучать. Займусь как-нибудь на досуге, самому интересно, странный очень эффект.
Тоже об этом думал. Добавил вариант с этой опцией, но результаты не поменялись.
Да, но тогда строго говоря надо самостоятельно следить за потерями пакетов и что-то предпринимать по этому поводу (мы ж не можем просто "забить" на непришедший ответ).
Понятно, что в рамках одной машины пакеты скорее всего теряться не будут, но строго говоря никто этого не гарантирует :-)
В тестовом сервере обработка заключается в банальном проходе по строке и подсчёту числа символов с разными кодами. Потому вряд ли в скорости обработки дело.
Возможно сказывается время на первичную установку коннекта. Для интереса прогнал тест с 1000000 запросов, результаты вот:
Ну потому что "большие данные" это не про размер данных, а про способы работы с ними.
Статический метод - дак по имени класса же
FB.fb(x)
. А изнутри объекта (из не-статического метода) - просто по имени.Дело не в том, что близко к сердцу или нет, а в том, что "что мы доказываем". Если доказываем "на языке X можно быстро написать что-то годное за счёт удобных языковых средств" - в таком случае непонятно, зачем мерять производительность (ну т.е. это прям совсем не основная характеристика при таком сравнении), а надо скорее сравнивать лёгкость написания / понимания / расширения.
А если доказываем "на языке X можно написать, чтобы быстро работало" - то тогда надо сравнивать более-менее идиоматичные способы написания "чтобы быстро работало". Ну либо бескомпромиссно оптимизировать, но эт уже нужны специалисты в каждом конкретном ЯП и лучше тогда в виде соревнования какого-то.
В общем, я не очень понял, что хотели сравнить, отсюда и вопросы.
Что же касается размера влинкованного рантайма (или размера интерпретатора) - дак он сильно зависит и от компилятора в том числе. Хотя конечно даёт некоторую информацию на тему "сколько надо потратить места, чтобы на сферическом компьютере в вакууме запустить эту программу". С другой стороны - когда он статически слинкован, нам на каждую программу своя копия рантайма нужна, а если мы про php там или джаву, то он более-менее один на всех. Впрочем, эт уже отдельная история.
Ну мы ж тут вроде скорость дефолтного рантайма замеряем :-) Так что шарп стоило включить.
Очень странное сравнение, как по мне. Если уж сравнивать производительность - то не решения "в лоб" или решения "максимально задействующего синтаксический сахар", а "решения, в котором сколько-нибудь заморочились с производительностью".
В плюсах - если уж хотим использовать iostream, то стоит выключить синхронизацию с stdio, чтобы буферизация работала
std::ios::sync_with_stdio(false);
. Там же, в плюсах, похоже компилятор решил весь C++-ный рантайм статически слинковать. Оно конечно удобно, но вообще говоря не то чтобы принято (ну т.е. под винды стоит компилировать MSVC и использовать его системные dll-ки, под пингвинов - системный же libc).В джаве я не очень понял, зачем делать объект FB внутри main, а потом дёргать у него статический метод, в котором снова создаётся объект того же FB.
Вот к go, python и php придраться особо негде, по крайней мере на первый взгляд. А в остальных я не силён.
Про Retry-After давно не слышал. Хотя в университете про HTTP и его заголовки очень даже рассказывали (и даже просили написать HTTP-сервер).
А вот про Authorization не со всем соглашусь - бывает, что нужно всю информацию, требуемую для запроса, положить в URL. Например - токены доступа по ссылке (когда нужно что-то расшарить людям, которым известна ссылка, по типу документов в Google Drive). Потому в каждом случае надо отдельно разбираться.
А ещё, раз уж про авторизацию заговорили, можно вспомнить Basic HTTP Auth, для которого в частности имя пользователя и пароль можно задавать прямо в URL: <scheme>://<user>:<password>@<host>/<path>. И это даже вполне себе работает.
Увы, фоток датчика не осталось. Впрочем, там ничего сверхъестественного - два джека 3.5 и от них кабель, на конце обмотанный изолентой (внутри резисторы и термистор.