Как стать автором
Обновить

Комментарии 22

НЛО прилетело и опубликовало эту надпись здесь

Спасибо за замечания по коду, извиняюсь если причинил боль, я не слишком опытен в плюсах чтобы учесть всё при разработке, думаю с дальнейшим изучением плюсов буду писать более читабельный и современный код, да и время поджимало, что сумел, то сделал, возможно когда нибудь зарефакторю)
По поводу бинарного файла, он нужен для быстрого поиска нужного тайла и соответственно отрисовки карты, совокупность констант, структур и самих картинок в файле при применении пары формул находит нужный тайл в файле за считанные мгновения, в отличии от простого поиска по папке, где может и 10 секунд искать один тайл на ssd, впринципе это всё я и описал в статье, если у вас есть более интересное решение, опишите его пожалуйста, я был бы рад узнать.

НЛО прилетело и опубликовало эту надпись здесь

"тайл с x=45917, y=53960 на зуме в 100 по пути root/100/45/917/53/960"

Там квадранты которые можно и нужно держать в hex, зума 100 не будет, максимум 14-16, может быть под 18 но это редкость.

"а для доступа к картинке обращаетесь к root/<n / N>/<n % N>.png, где первое — целочисленное деление, второе — взятие остатка"

Своя алгебра у квадрантов, делений никаких тут не нужно, всё на сдвигах.

Автору рекомендую сильно пережать картинки в jpeg и запаковать в архивы без сжатия. В моём варианте я в рар упаковал блоками по 256 (64 и т.д. по зуму) штук, без сжатия но с информацией для восстановления. Если коннектор до картинок колупает картинку с ошибкой, то запускается восстановление архива и иногда оно действительно помогало. Заодно напишите чекер этих баз, что бы проверять корректность всех картинок враз. Отказоустойчивость - хорошая и удобная штука.

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

Реализовывал такую же хрень лет 10 назад тестил на древних атомах первых - работало отлично, тормозов не было. Писалось на шарпе с почти готовой обёрткой вокруг unrar.dll и прикручено оно было естественно на обёртках OpenGL для отрисовки.

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

п.с.: Автор, усиленно на квадранты перейти рекомендую) Никаких xy тут нет, тут одно число, четверичное. Ваш x,y = {00, 01,10,11} = {0,1,2,3} в четверичной. Далее нужна алгебра от этого четверичного числа влево/вправо/вверх/вниз - это 4 операции условно два сложения два вычитания. Всё это не даёт коллизий. Картинки тоже так же переподпишите. Тайл x,y = 3FA0A7.jpeg, папки так же шестнадцатеричные. Это математика. Да да, без неё никак. Придётся кое что придумать и реализовать самостоятельно. Работать будет и работать будет хорошо.

Автору рекомендую сильно пережать картинки в jpeg и запаковать в архивы без сжатия. В моём варианте я в рар упаковал блоками по 256 (64 и т.д. по зуму) штук, без сжатия но с информацией для восстановления

Лучше положить в базу sqlite. И использовать можно будет без распаковки, напрямую, и места занимает меньше чем архив

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

Если вопрос "чтение файлов по одному с диска" и "чтение из sqlite" то второе точно выигрывает - проверялось много-много лет назад на андроид приложении (RMaps), которое умело и то и другое. Для кучи одиночных файлов файловая система работает как база данных, причем неоптимизированная с большим overhead

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

Так вот, всё что вы делаете - должно работать, это очевидно. Но как работать? Вы пишете - максимально быстро. "Максимально быстро" и "быстро" - сильно отличаются. Максимально быстро - это значит быстрее и быть не может. Причём это самое "максимально быстро" придётся доказывать. Т.е. что бы утверждать что оно "максимально быстро" - нужно доказать то, что все прочие реализации будут медленнее. А как вы это докажете?) Проблема.

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

Вы сами же пишете - изобрели велосипед, но стоило ли оно того, если сравнивать не с чем? Проблема))

Это я всего лишь про то, на что как обычно влетают начинающие прогеры. Прогают не на том, прогают не туда, прогают не то. Всё как обычно, и конечно же в этом ничего страшного нет.

Первое что вы должны получить - это валидный продукт, это значит напишите быстро и получите 100% работающее. С какой скоростью оно работает - это вообще не важно.

Про скорости. Вам пол-жизни не хватит, что бы написать рендер на 30 картиночек, такой что максимально быстрый. Вовсе не шучу. Оно так и есть. Пишите лишь бы работало, а уже после причём не кому то а себе - напишете куски быстрых реализаций, но на это у вас пол-жизни уйдёт, ещё раз говорю) Не верите? А это не вопрос веры. Давайте по существу, почему нет?

Как оно работает? Есть бд - пусть это файловая система [это тоже бд], или узкоспециализированная штука которые и называются бд - это не суть. Есть и есть. Как они работают? По каким то там запросам они отдают объекты. Объекты иногда кешируются, иногда нет, оно иногда настраивается, иногда нет. Бд может следить за собой ну например как файловая система и быть отказоустойчивой, а иногда бд за собой не следят как тот же скюель и в общем то это почти бесполезные бд [ну потому что бесполезные]. Все они работают как обычно на "вставку"/"удаление"/"изменение" и т.д. всё стандартно, иногда сами самовосстанавливаются и прочее прочее. Суть - они все динамические, а динамический - это изменяющийся по времени [по определению]. Далее вы тут сами напишите портянку про бд себе, и допишите сюда всё то что сейчас существует.

А ТЕПЕРЬ ДАВАЙТЕ ПОСМОТРИМ НА ВСЁ ЭТО И НА ТО ЧТО ВАМ НУЖНО)))))

Вам не нужна динамическая бд, вам не нужны объекты, вам не нужны запросы, вам не нужны поиски, вам не нужно от этого всего вообще ничего. А то что вам нужно - в этом всём НЕТУ)

Что вам нужно? Максимально быстро, отказоустойчиво, просто и желательно иметь поверх такое апи, что бы оно было по вашей задаче максимально простым и даже тривиальным. Иначе говоря вы суёте число и получаете картинку. Вот что нужно.

Теперь конкретно. Статических бд нет, статических бд отдающщих не объекты а указатели на них нет, статических отказоустойчивых бд нет, ничерта нет) Гонг вопрос: сколько это всё вы будете писать? И дело не в писанине тут. До писанины вы даже не дойдёте. Потому что перед тем как что то писать - нужно вообще то понимать что будет в итоге. А в итоге получается вообще принципиально иная архитектура, нежели имеющиеся. Ну вы же хотели максимально быстро? Хотели? Ну получите. У вас джиельобёртки напрямую и должны получать по hex-числу указатель на кусог бд И ВСЁ)))))) В случае чего бд должна самовосстановиться. Более ничего тут и не нужно.

А теперь сколько по времени вы это всё собираетесь писать? Понятно или нет?) Никогда вы сие не напишете, потому что это очень сложно, почти невозможно это. Для вас во всяком случае сейчас и ещё лет десять сверху - это в принципе не реализуемая задачька. Так вот я всего лишь про то, что пишите как есть, как вы задумали - так и пишите. И разбирайтесь в алгоритмах, это очень важно. Под алгоритмами я вовсе не понимаю тут какие то мат.алгоритмы, это не то, про них можно почитать и потестить и всё такое. Разбирайтесь в алгоритмах как что работает на самом деле. Алгоритм в данном случае - это как раз таки пример того что написано выше про бд в целом. Ещё это всё называют архитектурой. Вот для вас это важно. Как и что работает на самом деле.

И не слушайте брюзжащих старпёров, ибо да они сильно знают как и что работает на самом деле. Но писать то вам, а не мне) Так что пишите как задумали, и никого не слушайте. А вот когда напишете - тогда может быть [и то не факт] и поглядите что можно исправить и подправить. Даже могу объяснить почему это выгодно. Вы являетесь по сути программой, конечным автоматом с ножками и ручками. Вы как программа запущены в треде. Если кто-то лезет в тред - он тормозит тред) Нельзя лочить тред, от этого будет только хуже, причём сильно хуже. Вы как программа запущены и исполняетесь, ну и исполняйтесь. Вот когда ваше исполнение закончится, вот тогда можно анализировать результаты вашего исполнения, смотреть время, корректность результата и т.д. А до тех пор влезать в ваш тред никак нельзя, так что удачи вам а точнее вашему треду, как напишете - так и приходите с результатами) Оно будет конечно не интересно, глупо, ужасно, убого, дебильно, монструозно, велосипедно, ужасающе медленно - ну и что? Оно будет ваше и оно будет работать. Это главное.

Спасибо большое, я бы и не додумался до такого в силу слабости в вышмате, когда рисование маршрутов на прямиком на тайлах делал это было ещё то испытание, пока кто то не подсказал что линейная интерполяция существует)

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

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

растровые, у меня была бд откуда рендерились тайлы, тоесть я особо не мог выбрать какие мне нужны, а про векторные не слышал, погляжу, спасибо!
Я думал вообще делать векторную карту, но она имеет слишком много минусов по сравнению с картой из тайлов.

Спасибо большое!

Я, честно говоря не совсем понимаю что значит "поиск файлов" и в чем суть оптимизации. Вот допустим у нас в локальной директории лежат готовые тайлы. Именование файлов соответствует их позиции на проекции веб-Меркатора, например {X}_{Y}_{Z}.png. Мы рендерим сцену, смотрим какие тайлы перекрывают текущую область видимости при текущем масштабе, и просто берем их с диска по имени. В одной сцене как правило всего 20-30 тайлов. По сути так и работает тайл-сервер, мы у него запрашиваем имя тайла, он нам его выдает. Только тут они все на диске.

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

Я на 100% не уверен, но разве время доступа к файлу зависит от общего количества файлов данной директории? Не слышал о таком. Вот допустим у нас есть функция QImage* getTile(const QString& filename). Внутри она пытается открыть файл по имени, и естественно обрабатывает случаи, в который указанного файла нет на диске. Опять же, на одной сцене всего около 30 тайлов. Если одного из тайлов не окажется на диске, то он как бы и не будет отрисован. Т.е. 30 обращений к файловой системе за кадр(и то, если мы полностью изменили текущую область видимости не экране). Я в свое время делал приложение для растрирования векторных морских навигационных карт и разбиения их на тайлы. Все тайлы лежали в одной папке. В картографическом приложении я просто их от туда брал. Каждый раз при изменении уровня зума или или центра, я рассчитывал т.н. Tile Coverage - квадратная область [minX,maxX,minY,maxY]. И тайлы из этой области брал с диска.

Я точно не знаю, просто замечал что очень долго грузится при большом количестве тайлов в папке, не знаю точно изза чего такое происходило, но ждать одного экрана приходилось по 5-10 секунд

Ого, спасибо, посмотрю как они реализовали это)

Да просто реализовали, ибо чем проще - тем быстрее [почти всегда].

Там условный хеадер должен быть и его длина, в хеадере офсеты на другие хеадеры. В свою очередь эти хеадеры содержат офсеты на начала картиночек. В итоге этот бинарник это немножко офсетов на начала данных и собственно данные.

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

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

Пример: реализуйте собственные перечисления. Пихните это всё в библиотеку. Наследуйтесь от этой библиотеки и вы погубите производительность перечислений примерно до полутора раз.

Смысл: если вы тащщите много данных из библиотеки - это не выход. ТащИте мало данных, библиотека должна "обсчитывать" всё что можно в пределах библиотеки и не выходить за эти пределы, и в итоге вы должны получать маленькие данные, которыми уже и пользуйтесь на выходе из библиотеки.

Иначе говоря у вас есть библиотека "калупающая" эти самые бинарники, где лежат картиночки. Внимательно потестируйте выходное апи этого всего. И проведите тест безбиблиотечный. Код который вы запихаете в библиотеку иногда есть смысл не пихать в библиотеку, а прям "заинлайнить" "копипастой" туда где оно вызывается непосредственно. Межбиблиотечные вызовы иногда могут оказаться критичными, учитывайте это.

Бинарники должны быть короткими. Выше написано что лучше всё читать с диска куском враз. Например кусок может содержать в себе 256 картиночек. Целиком читайте этот кусог в оперативку, из него берите то что нужно, а нужно из него будет многое, потому то и проще читануть приличный кусог, но не шибко большой конечно же. Тут нужны тесты.

Далее. Вы же это всё обновлять как то будете. Ну не вы а юзер конечно же. Что юзеру надо - он то и обновит. Обновлять как обновляют нынче всё что есть гигантскими кусками - это вообще путь дегенерата. Но это почему то повсеместно практикуется. Почему? Ахз почему. Стильно модно маладёжно. Наверное. Правда это дичайшая дичандра, но кого это волнует?

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

И т.д. и т.п.

сейчас поясню немного

  1. На экране помещается 20 тайлов, 20 тайлов достать из бинарника это моментальная задача, это не просто быстро, это максимально быстро, если есть система быстрее я буду в шоке.

  2. При открытии файла он не загружается в оперативную память, поэтому файл может быть хоть 10гб размером, скорость считывания и нагрузка на систему не изменится

  3. Линукс это лучшая операционная система, хочется удобства, велком ту MAC OS, по производительности виндовс никогда не сравнится с линуксом.

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

  1. На экране не известно сколько тайлов помещяется, всё зависит от разрешения экрана. Даже при условии что если ваши картиночки константны (256x256) то не факт что выводить вы их будете в родном разрешении. Практика показывает что картиночки лучче вывести в чуть ужатом виде, изначально они у вас 256x256, рендерьте их 192x192 и поглядите что получится. Проблемы и с рендерами имеются, иногда рендеры рендерят по дифолту с прозрачностью, но когда они рендерят - края полупрозрачные получатся, а это значит что вы увидите сеточку. В общем смысле я щяс говорю про то, что не факт что у вас будут константные сетки, совпадающие с родным разрешением тайлов. А отсюда следует что даже при константном разрешении экрана вы не можете утверждать что у вас константное кол-во тайлов будет. Учитывайте это. И т.д. и т.п. Рендеры тут не совсем интересны даже, это та ещё отдельная песня. В любом случае рендер должен иметь возможность получить указатель на картинку, если этого в рендере нет - это совсем пагримушка какая то а не рендер.

    Что значит достать тайл из бинарника?)))) Его не нужно доставать. Вообще никак не нужно. Нужно бинарник положить целиком в память, и найти офсет на начало нужно картинки в бинарнике. Вам указатель на картиночку нужен а не картиночка. Вы как обычно плодите буферы на буферы которые буферами погоняют. А зачем вам это?

  2. Это как? Большинство систем настроены на виртуализацию памяти. И все файлики дифолтно читаются в память, а затем с ними можно что либо делать. Если вы используете иные механизмы - это такое себе... Потестируйте апи, я вот не знаю про линуксовые апи в случае с IO, но железки везде одинаковые. Обратите внимание на железо прежде всего. Никакое проганье не должно быть оторвано от железа, иначе это не проганье а порнография. У винта есть кеш. Кеш большой. Кеш больше вашей картинки. Причём нынче уже сильно больше, десятки мегабайт, уже иногда и сотни и более. Как вы читаете картинку с диска? Вы читаете её как то через кеш диска. Но если вы читаете по одной картинке, то вы не используете кеш по максимуму. Иначе говоря картинка у вас мегабайт (условно), вы читаете в кеш диска, из кеша в куда то там [в оперативку конечно же, но у вас не так, ну да ладно], однако же проще и эффективнее зачитывать куски примерно равные размеру кеша диска [или кратные ему]. Т.е. файлики и должны быть прилично большими, но не слишком большими.

    Возьмите и потестируйте IO-операции. Наплодите 256 файликов пофиг с чем каждый размером мегабайт, и один файлик размером 256 мегабайт. И читайте в оперативку и то и то. Или куда оно вам надо. Один большой кусок прочитается быстрее.

  3. Линукс это не лучшая ос. Для прогера - совершенно нет. Для прогера это ацкий ужас и кошмар. И вообще то линукс это не ос, это вроде бы как ядро. А вот то что поверх ядра накарячено в виде конечной ос - это уже ос и есть. Все ос разные, ядро вроде как одно. Как настроены ос - так они и работают. И все эти опирационки разные. Линкус вроде как один, а толку особо от этого нету. Ещё раз подчеркну - для прогера нету. Потому что операционки слишком отличаются. И запрогать под это всё что бы оно хотя бы работало везде - это проблема. А вот запрогать так, что бы оно везде хотя бы быстро работало - это очень сложно. А уж запрогать так что бы оно максимально быстро работало везде - это нерешаемая задача. Ну и как? Линукс лучшая ос? А для кого лучшая то?) Для дурачька торвальдса который двадцать лет ядро не меняет и векторы в ядро завести не может? Который не может уже накорячить прям в ядро линукса аналог GDI который работает вообще без видеокарты и выпилить нахрен никому не нужные бестолковые иксы? Вот потому то в этих ваших линуксах ничего и не работает. Для прогера. Потому что даже шрифт толком однообразно не прикрутишь. Потому что убожественное ядро линукса ничего не может. Потому и даже шрифты "у вас" никогда толком и не работали. А казалось бы это банальность вроде как. Ну да ну да. Везде это банальность, кроме линуксов. Отличная "ос" что тут скажешь. И т.д. и т.п.

  4. У вас не какой то непонятный плагин должен картиночки загружать. Он вообще ничего не должен. Боже упаси))) Потому что не должен. Ибо непонятно будет ли "постпроцессинг" с картиночками в дальнейшем.

    1. Нужен "калупатор" картиночек с диска. Это одно. С калупатора вам нужен указатель на картиночку и всё.

    2. Нужен рендер картиночек получающий пачку указателей на картиночки.

    3. Нужен "пробросчик" указателей из одного в другое. Это отдельный модуль. Смысл тут в том, что вы можете имея этот отдельный "пробросчик" - что либо сделать с картиночками ещё, дорисовать на них что-то изменить, балансы цвета подправить, анализировать это всё можно как то и т.д. и т.п. Не факт что оно будет юзаться в прадакшене, так оно вам должно быть нужно а не прадакшену)) Похоже у вас там как обычно набраны никчомные либы которые как обычно не соединяются) Впрочем нынче прогать так модно стильно маладёжно. Глючная фигня получается как обычно, ну да ладно. Пробросчик изменит картиночку, но она доложна в памяти как то лежать уже готовая, иначе как её изменить то?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации