All streams
Search
Write a publication
Pull to refresh
0
@phponeloveread⁠-⁠only

User

Send message
От ::data()/::c_str() ожидается нуль-терминированная строка аналогичная строке(std::string, у которой методы вызваны), а не её подстрока.

Ах да, забыл про арифметику. Опять же это сайзоф поверх типа «до» звёздочки. И sizeof(void) в итоге.

Сишники вполне себе обращаются с void, но почему-то все становится плохо, когда эту идею пытаются развить и строго объяснить с позиции системы типов и идеологии языка.

Поподробнее об этом, пожалуйста. Что именно становится плохо?

Вероятно потому, что с void сишник знакомится в младенчестве и просто принимает на веру

Некой мистической «строгостью» понимание не ограничено, логика не ограничена.

«надо писать void, когда функция не возвращает значения, а void* это… ну просто указатель, когда не знаем, на что указываем»

А ещё надо писать void, когда функция не принимает аргументов. Давайте поиграем в игру.

void определяет отсутствие результата, либо возврата. Как хотите это называйте. Что такое тип у указателя? Это тип возвращаемого операцией разыменования значения.

Что такое void * — это указатель для которого нет операции разыменования. *(void *) == void, то же самое что void f() {}; f(). Результата нет.

Мы не не знаем на что указываем — мы ни на что не указываем. «указатель указывает» — это детский садик. Это как функция у которой нельзя взять результат, так это — указатель, у которого так же нельзя взять результат.

int f(); и int * p; — они идентичны. Только у одной операция скобочки, а у второй звёздочка.

Тут скорее всего проблема в том, что как и сишник принимает на веру — так и представления о си — это вера. И то, что у кого-то есть вера — из этого не следует то, что без веры в си нет логики.
К слову, epoll(0), или BUSY_WAIT приводит к тому, что еполл сразу возвращается, независимо от кол-ва сработавших событий.

Я знаю о том, что произойдёт при epoll(0). Хотя формулировка не верна — кол-во событий на ожидание не влияет — любой событие будет епул.

Это приводит к тому, что текущий поток крутится в чём-то наподобие спинлока вместо того, чтобы сразу отдать остатки кванта.

Кому? Дяди Васи? Что конкурирует с епуллом по ЦПУ? Неужели обработчик евентов в том же треде(как это делается во всех реализация, что я видел)?

И таки да, в нормальном продакшене так не делают, т.к. вместо прироста будет просадка.

Какие ваши доказательства?
data/c_str не сломается

Сломается — это будет совсем не строка, что ожидается.
А memcat какой-нибудь тоже есть, или memlen?


Изначально было про то, что сишные функции для работы со строками в рамках std::string не применимы по причине отсутствия нуля после ресайза. Я доказал, что это не так.

Далее я помог автору комментария и привёл реальный пример( валидный для std::string), но невалидный для сишных строк. Вы зачем-то пришли и повторили мне то, что я итак сказал до вас. Зачем?

А теперь играете в игру «игнорирую всё» — зачем?

Если вы хотите нулевые символы в строке, то вам неизбежно придётся таскать рядом размер этой строки.

Зачем мне нулевые символы? Ну хорошо — придётся таскать, и?

Это отменяет что-то ранее сказанное мною, либо противоречит чему-то? Это ответ на моё утверждение намного выше?

Длинны в С++-строке это просто некая оптимизация получения длинные и не более того.

Это? Ну дак надо отвечать на тот комментарий, а не на другой.

Да и как я уже сказал — нулевые символы это больше надуманный кейс, чем реальный. От того я его и не рассматриваю. Если хотите — пусть будет length ещё и для хранения нулевых символов. Сломается ::data(), ::c_str(), но что поделать.
Это не я отвечал если что ).

Это неважно. Вы отвечаете в том контексте, которые определили до(после вас) вас. В нём же отвечал и я. Менять условия нельзя.

Мой тезис был такой — epoll(0) это хак. И конечно это хак! Смотрите — одно и то же решение: 43 место без epoll(0), 7 с epoll(0), изменена одна строка в коде!

Ну дак перечитайте то — на что я отвечал и кому. Зачем менять условия?

Вам не нравится одна строчка? Ну что поделать.
Это по вашему филигранная работа и особенности? Мдмашка в чистом виде.

Это не работа — это знание особенной того окружения, в котором работаете.

Тут и комментировать нечего. Конечно применимы, в реальных хайлод все это сплошь и рядом.

Тогда это решение точно так же применимо в хайлоаде. Профит даёт.

Ну и не понятно так же. Всё это соответствует критериям, которые определили выше. И определил их не я. Вы точно так же оспорили это: habrahabr.ru/post/338268/#comment_10428330

В чём причина ваших ко мне претензий?

Во всех где вызываешь epoll(0) (а это все ядра, иначе зачем он вам вообще нужен в любом виде в реальном проде?).

Епул не обязательно долбить из всех потоков.

Из личного опыта знаю, что когда все ядра заняты на 100% (а именно это происходит) доступ по ssh становится невозможным.

Не знаю что там у вас за опыт, но такого не может быть по определению. Да и мой опыт говорит прямо об обратном.

Даже на десктопе я могу пустить этот вайлтру в скольки угодно тредах и это мне не помешает не то что по ssh зайти, а смотреть ютуб и писать на хабре. При этом это полностью стоковое ядро.

И вообще вы какой-то нервенный… Судя по нику — из-за расклада с PHP в highloadcup-е? Ну так там и нода утерлась, не переживайте вы так.

Не из-за этого. Я уже описал причины.
Я, неверное, непонятно и глупо ответил. Чтобы подобно не повторялось — дополню.

Дело в том, что отвечающий в ответе на мой комментарий описал ту ситуацию, которая уже была описана мною в том комментарии, на который он, собственно, и ответил.
С точки зрения сожжения CPU — безусловно и epoll(0) и пхп с jvm жгут его с КПД разной степени паршивости.

Это не ответ. Было определено два тезиса: «Потому что в реальных», «а напрасное пережигание электричества».

Что из этого следует? А то, что всё что не из множества «реальных задач» и всё, что «напрасно пережигает электричество» неприменимо и является хаком.

Мною были выдвинуты контрпримеры — на что последовало молчания. Если не можете в аргументацию своих тезисов, то зачем это вообще начинать?

я представляю решение на пхп в проде

Опять же. Вы нарушаете условие. Применимы-ли в проде парсинг жсона и хттп так, как это сделано в некоторых(почти всех) решениях? Нет. Ну дак зачем вы суёте сюда то, чем решения заведомо не соответствует.

Так же, не важно то, что вы представляете, а что нет. Пхп просто так жрёт электричество? Жрёт. Под критерий определённый автором первоначального утверждения подходит? Подходит. Всё остальное — отношения к делу не имеет.

Вы можете начать рассуждать о том, что рабсила дороже электричества, как какие-то иные критерии дороже, но. За это решение покупается производительность. Точно так же, как в пхп покупается что-то другое.

Никто не определил, что производительность — это «неважный» критерий, а что-то иное важный.

но с epoll(0) уже нет, даже банально по ssh туда влезть не удастся.

Не верно. Епул долбит не во всех потоках одновременно, а даже если во всех — есть планировщик. Никакой ссш у вас не сломается.

Ну и вообще, кто вас сказал о том, что epoll(0) заканчивается на захардкоренном нуле? Ничего вам не мешает считать время проведённое в обработчике и на основе данной статистике рулить этим аргументом.

Я не минусил (и не умею ;)

Я говорю не про вас, а про тех, кто минусует без аргументации.
Кто смелый — кто сможет аргументировать за минусы? А то получается странно. Минусы есть, а ответов нет. В такой ситуации ведь не скажешь, что «я просто несогласен, а ответ уже итак дан другим участником и я с ним согласен». Почему вы поступаете так несправедливо?
Памяти — да, CPU — нет.

Память в современном, да и в любом другом мире, не отделима от CPU. ЦПУ читает память и время затраченное на её чтение/запись/ожидание прямо пропорционально кол-ву этой самой памяти, при прочих равных. А они равные.

Главная проблема GC не в том, что оно вносит задержки

Задержки стоят ЦПУ, внезапно. Сколько их — одна большая, либо много маленьких — неважно. Хотя много — естественно дороже.
Если вы хотели привести контр-пример, то надо было приводить нуль-символы в строке. Но опять же есть memchr(), memcpy().

Это что такое?
Ведь вы же измеряли цпу-время разных решений

Ведь вы же НЕ измеряли цпу-время разных решений. Естественно.
А jvm — это не напрасное прожигание электричества? А пхп — это не напрасное прожигание электричества? А жсон, хттп и прочее — это что? Это такое же напрасное прожигание электричества.

Ведь вы же измеряли цпу-время разных решений, да и в реальном мире производительность любых решений покупается в основном за счёт электричества и железа.

А подобные кастыльные парсеры жсона так же используются в реальных задачах? А подобные роутеры так же используются в реальных задачах? Что же вы так избирательны.

Я не знаю причины по которым вы говорите то, что говорите. Но я предполагаю то, что причина тут явно не в реальных задачах, не в электричестве, а в неком недовольстве/обиде на тех, кто этот «хак» знал.

Что бы легче найти косяки с работой памяти.

Это ложная уверенность, а любая ложная уверенность способствует большему кол-во ошибок, нежели что-то иное.

А если попробует записать что-то в nullptr, то это сразу будет видно.

В этом вся суть — мы взяли какой-то кейс и выдали его за все косяки, либо за какую-то весомую их часть. Это не так.

Разименование адреса «на прямую» достаточно редкий кейс, особенно в современном С++. new через new — уже не модно — это не жава.

Нулевой this вызывать функции позволяет, любые поля, кроме нулевого — будут не nullptr(скорее всего оно попадёт в нулевую страницу, но это просто особенность модели памяти и вас тут просто повезло, ведь вы говорили о nullptr). Все филды после 4к — уже мимо. Массивы — мимо.

Плюс, есть много кейсов, где это только навредит. Получили в оффсет ноль — не получили сегфолт, а получили мусор — получили сегфолт.
struct{arr[10];}.arr[offset] = 123;


На самом деле в любой программе используется малая часть адресспейса. Сколько там там памяти на топовой ноде? Одна миллиардная доля? Даже если это мы заммапим сотни петабайт — это копейки. Это даже не один процент.

Исходя из всего этого шанс разименовывая мусор попасть не на сегфолт достаточно туманны.

Все упиралось в сеть и хаки с epoll.

Почему же хаки? Знание и использование особенностей работы.
Вы начали с того, что топовое решение на Rust попало только на 31-е место, а вот на Go — аж на 15-е (потом поправили что на 11-е).

Это был не я.

Просто уточню, что решение на Rust (раз уж за него зацепились) отставало от 1-го места по очкам менее чем вдвое. И именно в этом контексте я и написал, что в таких условиях решает не язык, а конкретные оптимизации.

Именно про это я и говорю, но. Конкретные оптимизации зависят от языка и я, так же, сказал почему.

Я спорю именно с тем, что оптимизации — это какая-то вещь в себе. Нет. Для оптимизаций нужны возможности, в том числе, со стороны языка.

Точно так же, как выбор языка не делается просто так. Он обусловлен той областью, в которой работает человек. Т.е. язык косвенно влияет и на опыт человека и на его компетенцию в данной теме.

Плюс — хайлоад кап был чисто русский, так что могло быть просто мало народу в русскоязычном комьюнити.

Очень много. По крайней мере агитаторов.

Я например узнал о соревновании сильно постфактум.

Аналогично. Странно, что организаторы для такой холиварной темы не оставили рабочей свою систему проверки решений и рейтинг(вне зачёта) активным на месяц. Многие(в частности, тут мелька ссылка на редит, где раст-участник жаловался на недостаток времени) просто не успели.

Дело было в placement new, который в C++ вызывает конструирование объекта. А конструирование объекта, это инициализация.

Дело было не в этом. Зачем обманывать?

Был определён кейс «выделить память и инициализировать», допустим — инициализировать очередь для обработки. На самом деле даже это неважно — просто инициализировать память.

В языка с ГЦ память будет проинициализирована ДВА раза. В С++ один раз. Плюс, ещё остаётся открытый вопрос о том, можно ли вообще аллоцировать массив за одну аллокацию.

Только в C++ строки это контейнер

Строк в С++ нет, как и в си. Есть std::string, но строки на нём не заканчиваются. Даже если поверить в то, что строки есть, так же в С++ есть сроки из си. С какой стороны не взгляни — утверждение неверное.
у которого есть lenght и capacity. И если хочу «очистить строку», то сбрасываю длину.

И что же из этого следует? Какое отношение это имеет к моей цитате? Это её опровергает, либо что?

*str = 0; Имеет ту же семантику. Дальше что? std::string, кстати, делает то же самое — сишное *str = 0, только к этому изменяет ещё size.

И алгоритмы оперирующие на длину, а не на нуль символ, как работали так и работают.

Начнём с того, что ничего не запрещает std::string изменять «нуль-символ». Т.к. в крестах нет реаллока, а у c_str() сложность константная, то срока обязана иметь капасити +1 для нуля. Уже давно даже data() нуль-терминированная.

Таким образом через что не возьми данные из std::string — сишные функции работать будут. Тут вы соврали.

Если вы хотели привести контр-пример, то надо было приводить нуль-символы в строке. Но опять же есть memchr(), memcpy().

Поэтому да же в программах на Си, можно увидеть свою реализацию строк.

Поэтому — это почему? Из-за lenght у std::string в С++? Сомневаюсь. Поэтому явно от С++ не зависит.

А оптимизацию для lenght можно прикрутить к чему угодно. И из этого мало что следует.

Велосипеды-обёртки поверх сишных строк строками не являются.

И кроме как embedded это особо никому не нужно, т.к. можно исользовать пул объектов.

Не можно. Это раз, а два — к чему ваши оценки? Вы говорили о чём? О том, что можно делать то же самое, а теперь вы пытаетесь избавиться от неудобных примеров оптимизаций.

Ну и голословные утверждения про «не нужно» вы так же чем-то сможете подтвердить?

Какой-нибудь memset с 0.

Это не очищение памяти. И с по каким таким причинам она вдруг должна «очищаться»?

Пул объектов?

Дело в том, что память и объекты — это разные вещи. Объекты могут и обычно несут в себе какую-то логику инициализации. Память же — это просто память.

Сишниые строки в самом C/C++ редко использую, т.к. strlen пробегает по всей строке и это медленно.

Сишные строки как раз-таки и используются. Длинны в С++-строке это просто некая оптимизация получения длинные и не более того.

Есть всякие поиски подстрок, поиски символов и прочее. А медленно — это только в кейсе получения длинны. Остальные операции со строками требует прохода по ней и проверка символа на ноль — операция с нулей(в большинстве случаев) стоимостью. Какая разница что делать — сравнивать два указателя, либо сравнивать текущий символ с нулём?

А в C++ не так?

Да, в С++ это не так. Можно выделить кусок памяти не создавая объектов, а потом создать их в уже выделенной памяти во время её обхода.

В критичных местах в C++ да же предварительно не очищается память, просто помечаем как «свободную».

Что понимается под «очищением памяти»? Возврат страниц в систему? Подобное поведение свойственно любым менеджерам памяти. В реализации почти всех языков берут какой-нибудь jmalloc/tcmalloc/gnumallo, либо свой велосипед. Поэтому менеджер памяти в других языках не обладает какими-то резко другими свойствами.

Information

Rating
Does not participate
Registered
Activity