Comments 8
Привет. А почему бы не засунуть дату_время и задачу в std::map и выдергивать задачи по ключу дата_время?
Замечательная статья, хороший разбор, хорошее решение, и отличный слог — очень легко и приятно читать.
Гит не врет что на задачу было потрачено порядка 10 часов? Просто это как раз причина, почему я взял наитупейший формат bool[] validPoints
— что-то сложное вертеть это вспоминать про кучи/деревья, правильно их заполнять, и в итоге все равно остается элемент "пробинга" когда мы генерируем лишь кандидатов, а не гарантированно правильны последовательности.
Сравнить перформанс напрямую можно портировав мой вариант на плюсы и использовав в бенчах ваши же структуры (ну, возможно дописать конвертацию из вашего формат в этот на этапе setup, который в бенчах не участвует). Похожее решение на шарпе (см. в конце комментов) выигрывало в 1..10 раз (хотя там немного читерят с кэшированием), тут я бы ожидал похожего результата
Вроде чуть больше 12 часов, точнее не скажу.
К моменту создания репозитория у меня уже была выполнена часть 1 без тестов. Долго попытался прикрутить нативные тесты - потратил кучу времени: обычно пользуюсь CMake и гуглтестами, и перебрал 4 варианта работы с датами в С++, прежде чем остановился на boost (в промежуточных коммитах можно увидеть следы chrono и winapi).
А сравнивать перфоманс (перформанс?) не вижу смысла: тут нужны правильные бенчмарки, а их не особо прикольно делать без реального приложения, использующего структуру: оторвано от предметной области.
Например, я могу представить себе использование, в котором каждое расписание генерирует бот, и там нормальным будет расписание "*.*.* *:*:*.1,2,4,5,6,7 (и еще 800 чиселок)". Тогда, чтобы мое решение заработало хотябы за вменяемое время, нужно сверху прикручивать "оптимизатор расписаний", а ваше работает как ни в чем не бывало (чуть дольше будет работать конструктор, и все).
Я могу представить себе использование по типу cron-а, где у нас всего 10 расписаний (и все 10 попадут в кеш), а могу промышленное, где расписаний десятки тысяч.
Могу представить, ситуацию, в которой 99.9% расписаний не содержат фильтра миллисекунд, и наоборот, где миллисекунды - самая частая и важная часть.
В конце концов, мои итераторы не thread-safe, а ваше решение, думаю, из коробки заработает из нескольких потоков (если правильно помню код. Но допилить его до thread-safe явно проще).
Что именно мы собираемся сравнивать сейчас? Разница производительности в каждом из случаев будет различаться, и, возможно, что в ряде случаев моя версия даже проиграет, несмотря на разницу С++/С# и парсинг строк.
Поэтому делать прямое сравнение без предметной области смысла не имеет, а вот держать в уме два подхода - полезно, чтобы в реальной рабочей ситуации выбрать наиболее подходящее для данной ситуации решение.
Да, тоже обратил внимание, что у вас не тредсейф (у меня нет изменяемого состояния, поэтому тредсейф бесплатный, да).
Ну, соглашусь с аргументацией, пожалуй) Просто было бы интересно все же сравнить, даже в контексте "вот в таком сценарии х3 выигрыш, а вот в таком х4 проигрыш". Было бы понятно, что решения формируют Паретто-оптимальное множество и являются оба хорошими, каждый в своем роде)
До меня только сейчас дошло.
Если просто из любопытства - то можно создать реализацию ISequence, которая выделяет массив булов, и забить итератор ими (мы получаем крохотный оверхед за счет использования кучи, но поскольку в куче всегда всего одно значение, этим оверхедом можно пренебречь).
Получится очень близкое к вашей реализации решение, которое можно будет протестировать. Даже интерфейс использования не поменяется. Программирования там на 20 минут.
Ближайшее время я буду занят, но может в конце выходных руки дойдут - сделаю.
Похожее решение на шарпе (см. в конце комментов) выигрывало в 1..10 раз
Я видел только дерево сегментов, а это немного другое. Сейчас полистаю еще.
Изначально назывался
ICondition
, но не пережил рефакторинга.
Комментарии зато его пережили, похоже.
Почему не все тестовые задания одинаково полезны: С++ edition