спрошу.
                  
                  
                  Задача: есть данные (структура такая же как и в БД: несколько столбцов и много строчек), они хранятся в файле, у которого свой формат, надо их обработать.
                  
                  
                  Формат файла такой: сначала идёт схема/описание "столбцов" (тип данных, количество байт, которое нужно на хранение, название "столбца"), а далее идут непосредственно данные, которые надо парсить исходя из описания (схемы). И написать парсер было легко (пришлось, конечно, дублировать тип данных и сами данные).
                  
                  
                  enum T {
                  
                  
                      Int32(i32),
                  
                  
                      Float(f32),
                  
                  
                      Double(f64),
                  
                  
                    ...
                  
                  
                  }
                  
                  
                  
                  
                  
                  enum TType {
                  
                  
                      Int32,
                  
                  
                      Float,
                  
                  
                      Double,
                  
                  
                    ...
                  
                  
                  }
                  
                  
                  Однако в парсере при каждом считывании ячейки нужно знать тип (берётся из схемы) и по нему определять, сколько байт надо считать и каким образом превращать байтики (например, для Int32 это будет i32::from_le_bytes, для Float это будет f32::from_le_bytes). И из-за этого приходится делать что-то такое:
                  
                  
                  match ttype {
                  
                  
                    TType::Int32 => ...,
                  
                  
                    TType::Float => ...,
                  
                  
                    TType::Double => ...,
                  
                  
                    ...
                  
                  
                  }
                  
                  
                  И это создаёт слишком много branch instructions (надеюсь, я правильно использую термин). Можно ли от них избавиться?
                  
                  
                  
                  
                  
                  Вообще исходная идея была такова: каким-то чудом парсить данные (после того как мы знаем схему), не делая pattern matching (в общем, избавиться от branch instructions). Это вообще можно реализовать?
                  
                  
                  
                  
                  
                  Пока я писал этот текст, я понял, что можно было бы использовать HashMap (по типу сразу достать функцию, которую потом вызвать)
                  
                  
                
матч и так может скомпилится в хэшфуннкцию или дерево, как оптимизация
Если тебе такое подойдёт можешь посмотреть на поколоночное хранение, т е чтобы у тебя сначала лежали все значение одной колонки, потом все значения другой и тд, тогда тип можно будет проверять один раз на столбец. Больше можно посмотреть в контексте колоночных СУБД, там как всегда, свои плюсы свои минусы
Конечно, я не смогу изменить формат данных, но читать по колонкам данные я смогу
Надо смотреть, если файл большой то может так получиться что ты его несколько раз читаешь, и если он в page cache операционки не поместится то ещё и прям с диска будет несколько раз данные запрашивать, и это будет сильно дольше чем ещё один if
Ещё одна мысль, у тебя же схема на протяжении файла не меняется? Т е ты можешь сразу при чтении схемы сопоставить номер поля и соответствующую функцию Парсинга, т е на каждую строчку ветвления не будет
Да, схема одна и та же. А сопоставить можно с помощью того же HashMap?
Должно и вектора хватить, номер поля в схеме -> индекс в векторе
можно даже при парсинге прям по этому вектору итерироваться
А потом лукапаться по хешмапе дороже будет)
Нафига и зачем хэшмапа, если матч сделан практически в стиле switch-case, где у него и так будет наиболее оптимальная табличка? Без всякого хэширования, лазания в кучу и проверок наличия индекса с двойными лукапами.
и это тоже да, хешировать инты по идее должно быть дешево, но все равно дороже чем просто индекс
Может, я что-то не так делаю или не понимаю, но тут есть переходы: https://godbolt.org/z/hE3xzo3Md (14 строчка)
Наверное, можно было бы сделать как-то так: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=ee3a429ec2cb50764eae681f998c771c
Да, действительно... Это всё из-за переполнений (упростил функции, чтобы точно не было переполнений и всё ок. Паттерн матчинг быстрый стал)
Обсуждают сегодня