L>Регресс, это когда у тебя есть задача — посчитать хэши для набора строк, известных во время компиляции, а ты, вместо того, чтобы написать простой, понятный и поддерживаемый код, пишешь compile time crc32, который а) нужно тестировать б) нужно поддерживать в) отличается от crc32 ф-ии, используемой в рантайме г) увеличивает время компиляции д) тянет за собой дополнительное метапрограммирование (список строк нужно хранить в чем-нибудь вроде boost::fusion::vector или хз где и обходить через какой-нибудь fusion.for_each, в общем, не то, что обычно используют в рантайме) е) нельзя дебажить. Вывод: данный подход не дает никаких преимуществ перед тупым вычислением хэшей при старте программы, одни недостатки, он контрпродуктивен и сеет в коде иррациональное зло
(а) протестировать достаточно единожды. Все-таки компиляторы тестируют неплохо.
(б) (в) поддерживать нужно любой код, но compile-time проверки поддерживать проще, чем crc32 в рантайме. Впрочем, в рантайме CRC32 вообще не нужно в данном проекте
(д) э нет, вот как раз CRC32 и был задействован для того, чтобы исключить дополнительное метапрограммирование.
Попробую объяснить подробно, что и зачем было сделано.
Для database connectivity на C++. Нужна простая и быстрая библиотечка, поддерживающая следующие особенности: postgres, async queries, threading (thread pool), db connection pool и prepared statements. Существующие библиотеки — "выберите чего-нибудь два", а с асинхронностью вообще плохо. Это не считая кошмарного синтаксиса и неудобного использования.
На C++ 11 как раз можно сделать удобно — спасибо variadic templates, можно писать примерно так:
vector<tuple<int, string>> results;
db_pool.query("SELECT id, name FROM accounts WHERE date>?", results, last_login_date);
for (auto account : results)
cout << get<1>(account) << endl;
Для чего нужно CRC32? Для поддержки prepared statements, которые привязаны к соединениям. Поскольку соединений в пуле много, неизвестно, поступал ли уже этот запрос в это соединение или нет. Если поступал, то по CRC32 запроса можно его найти. Вероятность коллизии крайне мала, запросов же не сотни тысяч.
Можно делать иначе — в рантайме регистрировать каждый запрос, на стартапе получать уникальный ID, и пользовать его. Решение с CRC32 банально быстрее было написать, и меньше тестировать.
Здравствуйте, wander, Вы писали:
W>Ничего подобного. Такая точка зрения обычно является результатом длительной работы в команде в конторе на фуллтайм.
а все мы тут кодим, из-за хобби? =)
W>а) Не все программисты обладают одинаковой квалификацией, чтобы потом читать такой код.
насколько я знаю, в команду не кидают тех кодеров, которые не обладают необходимыми навыками, для решения тех задач, которые решает команда.
а если же такое и случается — то такие кодеры не приживаются, и их переводят в другие команды.
никогда не наблюдал такого, чтоб команда себя ограничивала из-за одного новичка %)
W>б) Если человек только начал работать, ему будет гораздо сложнее входить в колею.
в команды, которые длительное время занимаются решением одной задачи — никогда не закинут нового человека, ибо он как пятая нога. обычно новых людей объединяют в новые команды, которые с нуля начинают решение задач.
W>в) Довольно часто требуется просто решить задачу, а не решить задачу самым крутым способом доступным на текущем языке.
т.е. в рантайме считать CRC — это быстрее в реализации, даже со всем вытекающим? как по мне — так наоборот.
W>То, что они занимают больше времени — факт
это ты субъективно.
W>даже судя по твоим постам на форуме
ну опять же — субъективно.
ну...я и мои посты — исключительный случай. я работаю исключительно удаленно, и исключительно в тех проектах, в которых я хочу участвовать. ну и занимаюсь я несколько необычными задачами, для некоторой предметной области, в которой сроки на реализацию — последнее, о чем "бос" может подумать.
W>г) Отчитываться за такой код труднее, если начальство само не балуется таким же.
начальству вообще наплевать на код. ему — чтоб продукт работал.
W>Это соответствует рабочей обстановке у многих работодателей. Это не троллинг и не абсурд — реальность как она есть.
страшная реальность. но, как говорится — сам себе враг.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, wander, Вы писали:
W>Ничего подобного. Такая точка зрения обычно является результатом длительной работы в команде в конторе на фуллтайм. Где всякие программерские изыски неприемлемы и даже вредны, потому что: W>а) Не все программисты обладают одинаковой квалификацией, чтобы потом читать такой код. W>б) Если человек только начал работать, ему будет гораздо сложнее входить в колею. W>в) Довольно часто требуется просто решить задачу, а не решить задачу самым крутым способом доступным на текущем языке. То есть времени нет писать изыски. То, что они занимают больше времени — факт, даже судя по твоим постам на форуме (да и мой собственный опыт говорит о том же). W>г) Отчитываться за такой код труднее, если начальство само не балуется таким же.
W>Это соответствует рабочей обстановке у многих работодателей. Это не троллинг и не абсурд — реальность как она есть.
На самом деле не совсем так. Просто однаждый я начал программировать не только на С++, но и на С#, а теперь еще и питоне. Эти языки намного проще, мне сначала не нравилось то, что язык, рантайм и библиотеки делают слишком многое за меня, а потом я понял как это удобно. Дело в том, что это снижает когнитивную нагрузку. Если программируя на С++, (допустим) 50% когнитивных усилий уходит на то, чтобы анализировать С++ код, а оставшиеся 50% (опять же, допустим) идут на все остальное — алгоритмы, струткуры данных и архитектуру, то когда я пишу на питоне, я могу сосредоточиться на том что делаю. Моешь чашку — думай о чашке.
Дело тут не в языках, а в сложности кода. На С++ можно тоже писать простой код. Такой код не обязательно должен делать простые вещи, скорее наоборот, только научившись писать простой код можно делать действительно солжные и интересные вещи. Когда умеешь это делать, особенно забавно наблюдать за всеми этими попытками написания "умного" кода, который использует кучу очень сложных концепций для организации чего-нибудь очень прстого, буфера там какого-нибудь в памяти, ну или interop-а с БД, как в данном случае
Причем все эти сложности, как правило, оправдываются какой-нибудь ерундой. Код выглядит красиво и просто, либо мы что-нибудь экономим, вычисляя это что-то во время компиляции. Чаще всего все эти оправдания сложности не выдерживают критики при более или менее пристальном рассмотрении. При таком рассмотрении очень часто оказывается, что ради сомнительных преимуществ просраны действительно важные инженерные аспекты, как то простота отладки и тестирования, либо эффективность процесса компиляции и скорость build-run цикла разработки.
SD>(а) протестировать достаточно единожды. Все-таки компиляторы тестируют неплохо.
То, что оно собирается, еще не значит, что оно правильно работает.
SD>Попробую объяснить подробно, что и зачем было сделано. SD>Для database connectivity на C++. Нужна простая и быстрая библиотечка, поддерживающая следующие особенности: postgres, async queries, threading (thread pool), db connection pool и prepared statements. Существующие библиотеки — "выберите чего-нибудь два", а с асинхронностью вообще плохо. Это не считая кошмарного синтаксиса и неудобного использования. SD>На C++ 11 как раз можно сделать удобно — спасибо variadic templates, можно писать примерно так:
SD>
SD>vector<tuple<int, string>> results;
SD>db_pool.query("SELECT id, name FROM accounts WHERE date>?", results, last_login_date);
SD>for (auto account : results)
SD> cout << get<1>(account) << endl;
SD>
Я правильно понимаю, что предполагается всегда читать результаты запроса в память полностью?
SD>Для чего нужно CRC32? Для поддержки prepared statements, которые привязаны к соединениям. Поскольку соединений в пуле много, неизвестно, поступал ли уже этот запрос в это соединение или нет. Если поступал, то по CRC32 запроса можно его найти. Вероятность коллизии крайне мала, запросов же не сотни тысяч.
SD>Можно делать иначе — в рантайме регистрировать каждый запрос, на стартапе получать уникальный ID, и пользовать его. Решение с CRC32 банально быстрее было написать, и меньше тестировать.
Я правильно понимаю, что при выполнении запроса сначала по его crc32 ключу ищется prepared statement?
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, wander, Вы писали:
W>>Ничего подобного. Такая точка зрения обычно является результатом длительной работы в команде в конторе на фуллтайм. X>а все мы тут кодим, из-за хобби? =)
Причем тут это? Просто в определенных условиях сложно поступать как хочется. Условия у всех разные.
W>>а) Не все программисты обладают одинаковой квалификацией, чтобы потом читать такой код. X>насколько я знаю, в команду не кидают тех кодеров, которые не обладают необходимыми навыками, для решения тех задач, которые решает команда. X>а если же такое и случается — то такие кодеры не приживаются, и их переводят в другие команды. X>никогда не наблюдал такого, чтоб команда себя ограничивала из-за одного новичка %)
Команда не ограничивает, команда вырабатывает оптимальные условия.
W>>б) Если человек только начал работать, ему будет гораздо сложнее входить в колею. X>в команды, которые длительное время занимаются решением одной задачи — никогда не закинут нового человека, ибо он как пятая нога. обычно новых людей объединяют в новые команды, которые с нуля начинают решение задач.
Ты не видел, а я видел.
W>>в) Довольно часто требуется просто решить задачу, а не решить задачу самым крутым способом доступным на текущем языке. X>т.е. в рантайме считать CRC — это быстрее в реализации, даже со всем вытекающим? как по мне — так наоборот.
Про CRC ты спорь с теми, кто по этому поводу возражал. Я про другое говорил.
W>>То, что они занимают больше времени — факт X>это ты субъективно. W>>даже судя по твоим постам на форуме X>ну опять же — субъективно. X>ну...я и мои посты — исключительный случай. я работаю исключительно удаленно, и исключительно в тех проектах, в которых я хочу участвовать. ну и занимаюсь я несколько необычными задачами, для некоторой предметной области, в которой сроки на реализацию — последнее, о чем "бос" может подумать.
Это как раз очень нетипичный случай И ты свой нетипичный случай распространяешь на всех. Я же объяснить пытался чем обоснован тот "абсурд", который писался выше
W>>г) Отчитываться за такой код труднее, если начальство само не балуется таким же. X>начальству вообще наплевать на код. ему — чтоб продукт работал.
Начальство бывает разных уровней. Непосредственному начальству (это может быть тимлид, или начальник отдела) на код не должно быть наплевать.
W>>Это соответствует рабочей обстановке у многих работодателей. Это не троллинг и не абсурд — реальность как она есть. X>страшная реальность. но, как говорится — сам себе враг.
Это не тот случай, чтобы устраивать священные войны. Я понимаю что тебе такой подход симпатичен (мне тоже), но нужно иметь силы понять, что он не единственно правильный. И в других условиях другие подходы имеют резон.
Здравствуйте, Lazin, Вы писали:
L>На самом деле не совсем так.
Ну, случаи разные. Но то, что я перечислил довольно часто является причиной отказа от определенных фич языка. Взять тот же google code style (как один из самых известных).
L>Просто однаждый я начал программировать не только на С++, но и на С#, а теперь еще и питоне. Эти языки намного проще, мне сначала не нравилось то, что язык, рантайм и библиотеки делают слишком многое за меня, а потом я понял как это удобно. Дело в том, что это снижает когнитивную нагрузку. Если программируя на С++, (допустим) 50% когнитивных усилий уходит на то, чтобы анализировать С++ код, а оставшиеся 50% (опять же, допустим) идут на все остальное — алгоритмы, струткуры данных и архитектуру, то когда я пишу на питоне, я могу сосредоточиться на том что делаю. Моешь чашку — думай о чашке. L>Дело тут не в языках, а в сложности кода. На С++ можно тоже писать простой код. Такой код не обязательно должен делать простые вещи, скорее наоборот, только научившись писать простой код можно делать действительно солжные и интересные вещи. Когда умеешь это делать, особенно забавно наблюдать за всеми этими попытками написания "умного" кода, который использует кучу очень сложных концепций для организации чего-нибудь очень прстого, буфера там какого-нибудь в памяти, ну или interop-а с БД, как в данном случае
А мне кажется именно в языках. Просто все эти изыски родились из-за определенных ограничений того или иного языка. В попытке эти ограничения компенсировать появились и изыски. Если язык сразу позволяет думать о чашке, то и изыски не нужны.
L>Причем все эти сложности, как правило, оправдываются какой-нибудь ерундой. Код выглядит красиво и просто, либо мы что-нибудь экономим, вычисляя это что-то во время компиляции. Чаще всего все эти оправдания сложности не выдерживают критики при более или менее пристальном рассмотрении. При таком рассмотрении очень часто оказывается, что ради сомнительных преимуществ просраны действительно важные инженерные аспекты, как то простота отладки и тестирования, либо эффективность процесса компиляции и скорость build-run цикла разработки.
Согласен в целом. Профессионализм — в чувстве баланса. Не соглашусь, что это всегда плохо, но тем не менее. Опять же, метапрограммирование — не всегда заумная зубодробительная синтаксическая каша — иногда и оно дает простой и понятной код, который не стыдно отдать на ревью и легко сопровождать. Повторюсь, профессионализм в чувстве баланса.
Здравствуйте, niXman, Вы писали:
X>к тому же, даже не могу представить, что можно написать не используя шаблонов %)
Ну ядро линукса, например
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, SkyDance, Вы писали:
SD>Можно делать иначе — в рантайме регистрировать каждый запрос, на стартапе получать уникальный ID, и пользовать его. Решение с CRC32 банально быстрее было написать, и меньше тестировать.
а хапросов много?
Я так понял, что речь идёт о кэше запросов же, да?
Путь номер 1)
Ну тупо std::map<std::sting, то_что_ты_хочешь_кэшировать> и программировать ничего не надо, всё уже есть, и кэш будет и риска коллизий совсем нет.
Путь номер 2)
Реализуешь бор (префиксное дерево), для хранения отображения из текста в кэшируемое значение и используешь его. Тут вообще оверхед близкий к нулевому будет
Путь номер 3)
Как-то коллекционируешь строчки, которым ты в CT хочешь читать хэши, и подбираешь натравливаешь на эту коллекуию утилиту, которая порождает функцию, которая отображает строку в уникальное число. Дальше эзаешь число и эту функцию.
Зачем наворачивать CT-вычисления тут я
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>а хапросов много?
E>Я так понял, что речь идёт о кэше запросов же, да? E>Путь номер 1) E>Ну тупо std::map<std::sting, то_что_ты_хочешь_кэшировать> и программировать ничего не надо, всё уже есть, и кэш будет и риска коллизий совсем нет.
E>Путь номер 2) E>Реализуешь бор (префиксное дерево), для хранения отображения из текста в кэшируемое значение и используешь его. Тут вообще оверхед близкий к нулевому будет
E>Путь номер 3) E>Как-то коллекционируешь строчки, которым ты в CT хочешь читать хэши, и подбираешь натравливаешь на эту коллекуию утилиту, которая порождает функцию, которая отображает строку в уникальное число. Дальше эзаешь число и эту функцию.
E>Зачем наворачивать CT-вычисления тут я
Можно просто считать хэши в рантайме, при вызове query, можно даже только от части строки (murmurhash2 это всего навсего чуть больше 50-ти инструкций)
А вообще, самый простой и, на мой взгляд, самый правильный вариант — переложить это все на приложение. Приложение само должно вызвать prepare, сохранить statement id и использовать его потом. Библиотеке знание о том, есть ли statement id для того или иного запроса или нет — ни к чему.
Здравствуйте, Erop, Вы писали:
E>Путь номер 2) E>Реализуешь бор (префиксное дерево), для хранения отображения из текста в кэшируемое значение и используешь его. Тут вообще оверхед близкий к нулевому будет
По сравнению с чем? В префиксном дереве при lookup'е нужно по узлампамяти попрыгать.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>По сравнению с чем? В префиксном дереве при lookup'е нужно по узлампамяти попрыгать.
А при получении данных по хэшу не нужно, что ли? Вопрос в затратах же..
Что-то мне подсказывает, что если так уж критична именно в этом месте скорострельность, то лучше всего последовательные id выдавать при регистрации запросов, или вообще не id, а хэндлы.
А если таки не важна настолько, то можно и по самой строчке вхождение в кэше искать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Ну ядро линукса, например
речь шла о С++, и о сомнительной резонности сомнительной Си-шной библиотеки в плюсовом коде.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, Erop, Вы писали:
EP>>По сравнению с чем? В префиксном дереве при lookup'е нужно по узлампамяти попрыгать. E>А при получении данных по хэшу не нужно, что ли? Вопрос в затратах же..
Для hashtable нужно сделать 1~2 запроса в память (если без коллизий), а для trie таких запросов в среднем будет больше. Я бы использовал trie для такого поиска только если бы была важна приемлемая worst case complexity (например o(n)) или упорядоченность, и std::map (которая есть из коробки) не подходила бы.
E>Что-то мне подсказывает, что если так уж критична именно в этом месте скорострельность, то лучше всего последовательные id выдавать при регистрации запросов, или вообще не id, а хэндлы.
Если важна скорострельность, то можно и что-то типа:
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, Erop, Вы писали:
E>>Ну ядро линукса, например X>речь шла о С++, и о сомнительной резонности сомнительной Си-шной библиотеки в плюсовом коде.
Ох, лол :-D
APR — сомнительная библиотека, с сомнительной резонностью
APR умеет vectorised I/O, boost нет, apr может в базы данных(и даже умеет prepare), boost нет. По поводу сишечки — я вот например иногда использую т.н. structure hack, для производительности, в c++ коде. Может ты сумеешь предложить типобезопасный аналог на шаблона, раз уж ты такой их фанат?
Здравствуйте, Lazin, Вы писали:
L>Ох, лол :-D
дешево вбрасываешь...
да и зачем столько смайликов?
L>APR умеет vectorised I/O
т.е. умеет прикидываться UIO? да, это гениально!
L>boost нет
а должен?
L>apr может в базы данных(и даже умеет prepare), boost нет.
а должен?
глядя на твои примеры, складывается ощущение, что только Си-шные библиотеки(или только ARP?) умеют описанное.
L>По поводу сишечки — я вот например иногда использую т.н. structure hack, для производительности, в c++ коде. Может ты сумеешь предложить типобезопасный аналог на шаблона, раз уж ты такой их фанат?
знать бы еще о чем речь..
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, Lazin, Вы писали:
L>>Ох, лол :-D X>дешево вбрасываешь... X>да и зачем столько смайликов?
Я отталкиваясь от уровня аргументации оппонента
L>>APR умеет vectorised I/O X>т.е. умеет прикидываться UIO? да, это гениально!
Мне надо было кроссплатформенно читать и писать в файлы подобным образом. Буст не может
L>>boost нет X>а должен?
Поддерживать довольно базоаую возможность, нет конечно
L>>apr может в базы данных(и даже умеет prepare), boost нет. X>а должен?
Кто этими базами данных пользуется…?
X>глядя на твои примеры, складывается ощущение, что только Си-шные библиотеки(или только ARP?) умеют описанное.
Чего это вдруг? Я такого не утверждал, просто привел apr в качестве примера. Мне она правда больше подходит чем буст.
L>>По поводу сишечки — я вот например иногда использую т.н. structure hack, для производительности, в c++ коде. Может ты сумеешь предложить типобезопасный аналог на шаблона, раз уж ты такой их фанат? X>знать бы еще о чем речь..
Здравствуйте, Lazin, Вы писали:
L>Я отталкиваясь от уровня аргументации оппонента
правильно будет так: "Я субъективного+предвзято+заинтересованно отталкиваясь от уровня аргументации оппонента "
(даже смайлик твой вклеил, для подтверждения серьезности твоей аргументации)
L>Мне надо было кроссплатформенно читать и писать в файлы подобным образом. Буст не может
а еще он не умеет окошечки.
L>Поддерживать довольно базоаую возможность, нет конечно
если мыслить твоими критериями — окошечки это тоже весьма базово, даже базовей базового.
L>Кто этими базами данных пользуется…?
... L>Чего это вдруг? Я такого не утверждал, просто привел apr в качестве примера. Мне она правда больше подходит чем буст.
... L>Google — struct hack
— выдаешь желаемое за действительно. жги ишо!
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
L>>Поддерживать довольно базоаую возможность, нет конечно X>если мыслить твоими критериями — окошечки это тоже весьма базово, даже базовей базового.
Да хрен с ними, с окошечками. Логирование в буст добавили уже?
Есть такое понятие, как cross-platform support middleware. Boost, это как раз оно и есть. Но кроме буста есть APR, GLib, commonc++, POCO.
Просто когда я написал, что не использую буст, ты сначала обвинил меня в велосипедостроительстве, а apr назвал сомнительной библиотекой. (Лол)
L>>Кто этими базами данных пользуется…? X>... L>>Чего это вдруг? Я такого не утверждал, просто привел apr в качестве примера. Мне она правда больше подходит чем буст. X>... L>>Google — struct hack
X> — выдаешь желаемое за действительно. жги ишо!
Что из процитированого я выдаю за действительное по твоему?
Здравствуйте, Lazin, Вы писали:
L>Да хрен с ними, с окошечками. Логирование в буст добавили уже?
google -> 'boost logging'
L>Есть такое понятие, как cross-platform support middleware. Boost, это как раз оно и есть. Но кроме буста есть APR, GLib, commonc++, POCO.
хорошо, что есть.
ты считаешь, что все это нужно объединить в одну кучу?
(а POCO уже умеет IOCP/epoll/qkueue, или все еще select и poll ?)
(и да, POCO я однажды рассматривал для применения, но качество кода мне не понравилось.)
L>Просто когда я написал, что не использую буст, ты сначала обвинил меня в велосипедостроительстве, а apr назвал сомнительной библиотекой. (Лол)
обвинений не было.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, Lazin, Вы писали:
L> По поводу сишечки — я вот например иногда использую т.н. structure hack, для производительности, в c++ коде. Может ты сумеешь предложить типобезопасный аналог на шаблона, раз уж ты такой их фанат?