У меня ненавязчиво не получится - по игровому полю можно перемещаться только в маскеAlex2013 писал(а): Ссылку на ман можно? Вообще сечас ИМХО был бы интересен "виртуальный туризм" по известным мирам с возможностью кое где не навязчиво перейти в "игровой режим" или 3д/Вр-чат . Современные игровые и социальные проекты во многом рассчитаны на практически профессиональных игроманов или не менее профессиональных блогеров то есть все они имеют довольно высокий "прог вхождения " и требуют немалых затрат времени.
Cheb's Game Engine
Модератор: Модераторы
Была в Chasme (chasm the rift) консольная команда Kill All что убивал всех неписей и позволяла гулять по уровням "в режиме прогулки" Вот по моему во все игры нужно добавить что-то подобное как отдельный режим игры. ( Разумеется режим должен быть со своим собственным квестом и разными прибамбасами, но его появление сразу добавит еще один слой пользователей тем более что это будет "не чистый Квест", а особое "призрачное прохождение" так сказать "сон о игре" )
Отличная идея. Все равно, что ночью погулять по родному городу, когда все спят. И ещё чтоб ментов не было )Alex2013 писал(а):Была в Chasme (chasm the rift) консольная команда Kill All что убивал всех неписей и позволяла гулять по уровням "в режиме прогулки" Вот по моему во все игры нужно добавить что-то подобное как отдельный режим игры. ( Разумеется режим должен быть со своим собственным квестом и разными прибамбасами, но его появление сразу добавит еще один слой пользователей тем более что это будет "не чистый Квест", а особое "призрачное прохождение" так сказать "сон о игре" )
В моем случае это выпустить игрока на площадку до начала игры.
Отли..отличеннная идея... [упал, заснул]Alex2013 писал(а):и позволяла гулять по уровням "в режиме прогулки"
Сдвиг парадигмы: отказ от понятия, как "фоновая задача чтения из файла" - предполагалось, что все операции чтения возможны только в одном потоке, чтобы избежать резкого замедления чтения, когда несколько потоков в параллель дёргают головку жёсткого диска на себя (классический идиотизм наивного любителя многопоточности).
Изъян: это было чревато забитием памяти, если задачи обработки данных отставали от задач чтения, поэтому требовало отдельного менеджера прочитанных фрагментов, чтобы замедлял чтение, вычисляя... ФТОПКУ
Теперь чтение из файла - часть фоновой операции, которройнужно что-то там прочитать. Лимитирование расхода памяти эти временныеа буферы получается путём резкого ограничения на число потоков в приложении (4 (2 фоновых) на 4-х ядерном и выше, 3 (1 фоновый) на 2х-ядерном).
Изъян: это было чревато забитием памяти, если задачи обработки данных отставали от задач чтения, поэтому требовало отдельного менеджера прочитанных фрагментов, чтобы замедлял чтение, вычисляя... ФТОПКУ
Теперь чтение из файла - часть фоновой операции, которройнужно что-то там прочитать. Лимитирование расхода памяти эти временныеа буферы получается путём резкого ограничения на число потоков в приложении (4 (2 фоновых) на 4-х ядерном и выше, 3 (1 фоновый) на 2х-ядерном).
Я хотел сделать (пока даже близко не притрагивался, как-нибудь под Новый год...) что-нибудь такое.
Поток (который stream, а не thread) поддерживает (явно включаемую?) предвыборку — например, читая файл блоками по условные 64 Кб, заранее подгружает следующие 64.
Это должно быть полезно, если 1) над содержимым файла выполняется последовательная и нетривиальная обработка, 2) это не простое чтение с диска, а распаковка из архива. Тогда обработка текущего куска и распаковка нового смогут исполняться параллельно.
Поток (который stream, а не thread) поддерживает (явно включаемую?) предвыборку — например, читая файл блоками по условные 64 Кб, заранее подгружает следующие 64.
Это должно быть полезно, если 1) над содержимым файла выполняется последовательная и нетривиальная обработка, 2) это не простое чтение с диска, а распаковка из архива. Тогда обработка текущего куска и распаковка нового смогут исполняться параллельно.
Спасибо! Намотаю на ус.
Нетривиальная - это если я работаю с вложенными архивами. Пока не знаю, как буду такое организовывать - скорей всего, тупым распаковыванием в память.
З.Ы. Освежил свои воспоминания, как работает мой TUnzip (модуль RTL проапгрейженный на работу с потоками) - нет, он не умеет ни поиск, ни переключаться между разными файлами в архиве. Только "найти файл", "открыть файл", "прочитать следующий кусок файла". Любой поток, который позволял бы работать с этим, как с потоком, требовал бы от меня написания целого велосипеда. Отсюда, распаковка файла из архива возможна только целиком, либо в array of byte либо в TMemoryStream. Ну, вложенные архивы - по любому дурацкая идея. Никаких бонусов к сжатию, при работе - либо аццкие тормоза (чтобы достать файл из архива, каждый раз приходится распаковывать весь архив, в худшем случае) либо аццкий расход памяти (весь архив висит распакованный в TMemoryStream), либо ктулху-велосипед с кешированием, пытающийся канатоходствовать между тормозами и расходом памяти.
Делаем мору кирпичом и делаем движок распаковывать вложенные архивы на диск, в папку временных файлов. Ещё на этапе составления списка ресурсов. После чего, если это был pk3 - пихать его в список подключённых архивов и парсить в порядке общей очереди. А при следующем запуске - подхватывать сразу, только проверяя размер и дату, как с любыми файлами, лежащими мимо архива.
Добавлено спустя 20 минут 49 секунд:
З.Ы. Потом сделаю TMemoryMappedFileStream, всё руки не доходят.
Нетривиальная - это если я работаю с вложенными архивами. Пока не знаю, как буду такое организовывать - скорей всего, тупым распаковыванием в память.
З.Ы. Освежил свои воспоминания, как работает мой TUnzip (модуль RTL проапгрейженный на работу с потоками) - нет, он не умеет ни поиск, ни переключаться между разными файлами в архиве. Только "найти файл", "открыть файл", "прочитать следующий кусок файла". Любой поток, который позволял бы работать с этим, как с потоком, требовал бы от меня написания целого велосипеда. Отсюда, распаковка файла из архива возможна только целиком, либо в array of byte либо в TMemoryStream. Ну, вложенные архивы - по любому дурацкая идея. Никаких бонусов к сжатию, при работе - либо аццкие тормоза (чтобы достать файл из архива, каждый раз приходится распаковывать весь архив, в худшем случае) либо аццкий расход памяти (весь архив висит распакованный в TMemoryStream), либо ктулху-велосипед с кешированием, пытающийся канатоходствовать между тормозами и расходом памяти.
Делаем мору кирпичом и делаем движок распаковывать вложенные архивы на диск, в папку временных файлов. Ещё на этапе составления списка ресурсов. После чего, если это был pk3 - пихать его в список подключённых архивов и парсить в порядке общей очереди. А при следующем запуске - подхватывать сразу, только проверяя размер и дату, как с любыми файлами, лежащими мимо архива.
Добавлено спустя 20 минут 49 секунд:
З.Ы. Потом сделаю TMemoryMappedFileStream, всё руки не доходят.
Омг, господа, окститесь. На улице 21 век. Операционная система чихала на все ваши потуги оптимизировать файловое I/O.
В линуксе уже 10 лет, как невозможно ограничить размер кэша файлов - под него по любому выделяется ВСЯ свободная память, ранее присутствовавший лимит убрали. Если вдруг окажется, что лазарус использует memory-mapped files, то ещё хуже - там приложение вообще предсказать не может, когда и какого размера ввод-вывод на самом деле произойдёт. всем рулит менеджер виртуальной памяти, тот же, что отвечает за свап. "Не дергать головками" находится в ведении менеджера очереди запросов ввода-вывода блочного устройства - и у него есть политики "честная очередь", "приоретизация", "приоретизация с изменяющимися весами" + настройки read-ahead, write cache, rotational/SSD - на каждое блочное устройство по своемУ.
Не тратьте время - администратор, который знает как это крутить, окажет влияния (в + или в - неизвестно) радикально больше, чем способен программист, даже если тот будет флушить после записи каждой строчки..
В линуксе уже 10 лет, как невозможно ограничить размер кэша файлов - под него по любому выделяется ВСЯ свободная память, ранее присутствовавший лимит убрали. Если вдруг окажется, что лазарус использует memory-mapped files, то ещё хуже - там приложение вообще предсказать не может, когда и какого размера ввод-вывод на самом деле произойдёт. всем рулит менеджер виртуальной памяти, тот же, что отвечает за свап. "Не дергать головками" находится в ведении менеджера очереди запросов ввода-вывода блочного устройства - и у него есть политики "честная очередь", "приоретизация", "приоретизация с изменяющимися весами" + настройки read-ahead, write cache, rotational/SSD - на каждое блочное устройство по своемУ.
Не тратьте время - администратор, который знает как это крутить, окажет влияния (в + или в - неизвестно) радикально больше, чем способен программист, даже если тот будет флушить после записи каждой строчки..
Я же говорю, юзкейс — последовательно читаемый «файл» лежит в архиве «data.pack» в сжатом виде и читается по два куска, один готов к работе, второй, следующий за ним, распаковывается в фоне. Когда первый кусок заканчивается, второй [дожидается окончания распаковки и] занимает его место (в принципе, первый тоже можно сразу не выбрасывать, на случай, если пользователь захочет к нему вернуться).
Убрал такое понятие, как "правильный поток, из которого единственного можно вызывать библиотеку работы с картинками" - заменил все соответствующие ассерты на вход в критическую секцию.
Поэтому,
1. чтение файла + обработка файла всегда сводится к одной операции, которая для менеджера фоновых задач - чёрный ящик.
2. поскольку TUnzip - не thread-safe, операции распаковки огораживаются критическими секциями.
Вот от такого, как раз, придётся отказаться ради простоты: фоновые задачи - не про скорость, а про плавность работы. Учитывая, что ресурсы грузятся один раз, при первой загрузке игры после запуска приложения, а потом не обновляются без необходимости, быстродействие ~40% от предельно возможного - приемлемый компромисс с простотой системы.runewalsh писал(а):последовательно читаемый «файл» лежит в архиве «data.pack» в сжатом виде и читается по два куска, один готов к работе, второй, следующий за ним, распаковывается в фоне.
Поэтому,
1. чтение файла + обработка файла всегда сводится к одной операции, которая для менеджера фоновых задач - чёрный ящик.
2. поскольку TUnzip - не thread-safe, операции распаковки огораживаются критическими секциями.
В идеальном случае современной ОС (Windows 7) отображение в память не поможет и не помешает, но не забывайте: в Windows XP всё не так радужно, а XP SP2 + 1Гб памяти является официально поддерживаемой платформой.Shleps писал(а):Если вдруг окажется, что лазарус использует memory-mapped files, то ещё хуже - там приложение вообще предсказать не может, когда и какого размера ввод-вывод на самом деле произойдёт.
Значит в линуксе начиная с ядра 2.6 (т.е. RHEL 5,6,7,8 итд) окажется, что опережающее чтение и page cache портят схему и весь data.pack лежит в оперативке, а приложение периодически распаковывает из оперативки в оперативку, а оперативка периодически отсваповывается обратно на диск.runewalsh писал(а):последовательно читаемый «файл» лежит в архиве «data.pack» в сжатом виде и читается по два куска, один готов к работе, второй, следующий за ним, распаковывается в фоне.
И это ещё если в схеме нет прозрачного шифрования, дедупликации или архивации на уровне файловой системы или сетевого хранилища (LVM, ZFS и NAS на их основе, например Netapp )
Cheb, при всём моём уважении...Windows 7 никак не современная ОС, она снята с поддержки, а на сцене 10 и 11 версии, несмотря на их полную ублюдочность. И я не специалист по виндам, но shadow copy, прозрачная архивация и шифрование в них тоже года с 2012 начали появляться начиная с серверных версий.
"отображение в память не поможет и не помешает" - может помешать, при наличии в системе свапа. грубо говоря теперь программисту никакими ухищрениями с IO невозможно определить, где и в каком виде находятся нужные ему данные:
помимо двух понятных и желаемых состояний
- сжатые сериализованные на диске или сетевом хранилище
- разжатые десериализованные в памяти
могут быть ещё
сжатые сериализованные в памяти (кэш файловой системы)
разжатые десериализованные на диске (в свапе)
с полной невозможностью управлять состоянием хотя бы для части данных.
Как по мне - это веский аргумент отказаться от сжатия вообще: если пользователю будет надо - положит данные на том с прозрачной архивацией или дедупликацией. настроенной соответственно конфигурации его железа.
data.pack (даже без сжатия... особенно без сжатия, ха-ха, но я люблю сжатие) всегда будет НАМНОГО быстрее 10 000 отдельных файлов, в этом легко убедиться, попробовав программно обработать (даже просто скопировать куда-нибудь) одно и другое. Потому что реальная файловая система кроме чтения поддерживает запись и много других не интересующих нас вещей.
Я, если что, не про единственный сжатый файл, а про архив вида
заголовок из 10 000 записей «имя файла-размер-смещение данных»
данные файла 1
данные файла 2
...
данные файла 10 000
Это очень древняя и очень популярная идея. Ну и вот, «открываешь» в таком архиве виртуальный лежащий в нём файл data.pack/dungeon/lake/waypoint_graph.dat, который хранит последовательность чисел в формате VLQ, хорошо сжимается и хранится сжатым, а при загрузке ты их преобразуешь в SizeUint (=нетривиальная обработка).
Я, если что, не про единственный сжатый файл, а про архив вида
заголовок из 10 000 записей «имя файла-размер-смещение данных»
данные файла 1
данные файла 2
...
данные файла 10 000
Это очень древняя и очень популярная идея. Ну и вот, «открываешь» в таком архиве виртуальный лежащий в нём файл data.pack/dungeon/lake/waypoint_graph.dat, который хранит последовательность чисел в формате VLQ, хорошо сжимается и хранится сжатым, а при загрузке ты их преобразуешь в SizeUint (=нетривиальная обработка).
Э-э-э-э нет. чтобы скопировать 10000 файлов, надо не только обработать надлежащее количество информации, о котором собственно и шла речь, но и открыть 10000 файлов, и создать 10000 файлов. Кроме того, производительность системы, которая испытывает интенсивный процесс свапования, падает примерно в такое количество раз, в которое производительность устройства памяти превышает производительность устройства свапа.runewalsh писал(а):data.pack ... всегда будет НАМНОГО быстрее 10 000 отдельных файлов, в этом легко убедиться, попробовав программно обработать (даже просто скопировать куда-нибудь) одно и другое.
Если в приложению нужна разом вся махина в десериализованном виде - тогда в результате в памяти осядет объем, равный всем 10000 файлам + этот же объем в виде страничного кеша. Если не вся - то осядет только нужный объем*2, плюс будет выигрыш в латентности по добыче данных из архива. Если памяти под кэш хватать не будет - такой монстр вытеснит оттуда всё реально нужное, включая страницы редко используемых открытых приложений и кэш их файлов (например файрфокса или оконного менеджера) - в результате рабочий стол становится оооочень неотзывчивым. примерно как у долбанного вин10-11 с его плиточным интерфейсом, если система лежит на вращающемся диске, а не на SSD/
Кстати, операция смещения позиции в файле, если он превышает определенный объем, стоит вдвое или втрое дороже, чем для короткого файла, умещающегося в один inode. Это если файловая система типа ext2/3/4/ufs/btrfs без дополнительных слоев виртуализации типа менеджера томов с поддержкой raid или снапшотов, как в zfs или wafl.
Исключая сверхбольшие хранилища типа cephfs/lustre/panfs, которые режут файл на чанки, распределяющиеся по разным устройствам хранения - там уже по барабану, как работает, лишь бы разместить.
в общем-то я против любых крайностей - и когда человек держит в одной директории 1.6 миллиона файлов и когда у него один файл размером 10 терабайт. (а вот весело его чуть-чуть модифицировать?)
это называется tarЯ, если что, не про единственный сжатый файл, а про архив вида
Во времена написания диплома я тоже сделал свой аналог тара, но только потому, что сам тарболл (архив) находился на CD-ROM, а у него с seek-to-seek задержкой совсем плохо. А ещё выпендриться хотелось и потенциально защитить передаваемые материалы. как легко убедиться - мода на хранение ресурсов к играм в виде огромных паков вышла с популяризацией МОДов к играм. Пардон за каламбур.Это очень древняя и очень популярная идея.
обожаю господ, которые хранят на томе с включенной дедупликацией и прозрачной архивацией zip-архивы. двойной выстрел в ногу с точки зрения латентности, нагрузки на СХД и удобства работы.data.pack/dungeon/lake/waypoint_graph.dat, который хранит последовательность чисел в формате VLQ, хорошо сжимается и хранится сжатым
Даже не считая цену открытия отдельного файла, нельзя забывать о налоге антивируса на открытие отдельного файла. Что на двухъядерном проце (или полтораядерно, как мой ноут) становится совершенно неприемлемо. Если есть 10 тысяч файлов - их надо скласть в 1..10 pk3 пак-файлов.runewalsh писал(а):всегда будет НАМНОГО быстрее 10 000 отдельных файлов
Затем все пак файлы мапить в память - и пусть дальше у ОС голова болит, что в какой момент и насколько вперёд. А *поверх* этого, в случае пак файла без сжатия, класс "потока", работающий тупо с заданным куском памяти. И метод в менеджере ресурсов "распакуй и верни указатель на область памяти" - в данном случае возвращает указатель в эту область.
З.Ы. По памяти: на моём ноуте чтение с диска ~ 250 Мб/с, распаковка зип-архива ~30 Мб/с. То есть, в теории, оптимальным хранилищем является ZIP архив без сжатия. Но сжатие я поддерживать обязан просто на всякий случай (а вдруг?). ZIP сжимает файлы в архиве независимо один от другого, дистрибутив в виде 7z аржива пожмёт по любому лучше.
Я постулирую, что они по любому стоят на железе, в дюжину раз превышающем минимальные системные требования, поэтому с точки зрения этих ОСей абсолютно посрать, как у меня всё организовано - there's no kill like overkill. Это как я на днях играл на своём новёхоньком игровом компе в Dark Messiah of Might and Magic - она, на ультра настройках, даже с hdd грузилась секунды за три и видеокарта еле тёплая. Вот так и с моим поделиЁм выйдет. На современной машине никто даже заметить индикатор загрузки не успеет.Shleps писал(а):а на сцене 10 и 11 версии, несмотря на их полную ублюдочность.
По проекту: до компилируемости мне осталось сделать с нуля две подсистемы: менеджер задач и графическую прослойку. Всё остальное - простая копипаста с рефакторингом, урезания лишнего и простой рефакторинг.
Менеджер задач сегодня весь день кодил - посмотрел на получившееся, и отправил в помойку. Недельку ещё на досуге домысливать буду, как с первого раза получить что надо.
Графическая прослойка - ака свой велосипедный вулкан поверх GLES2 - призвана по максимуму отвязать рендер от физики и перепихнуть самые толстые расчёты (типа скиннинга на цпу и распаковки представления мира из 16-битных целых в тьмы и тьмы флоатов для GAPI) из логического потока в основной. А также должно уметь лочить ресурсы под себя и быть в 100500 раз удобнее, чем работа с голым оглём. Тоже семь раз отмерь, убейся об стену, начни сначала - но тут я хорошо представляю, как оно должно работать и что я желаю получить в итоге. У меня уже есть малый кусочек, любой рендер идёт через класс TDumbUniMesh, который я использовал при переезде с glBegin..glEnd. Но оный ужосна неоптимален. У него появятся братья, сёстры и двоюродные дядюшки.
можно. у меня например ни на линуксе, ни на винде антивирей нет. на корпоративном компе только, и на пограничных серверах.Cheb писал(а):нельзя забывать о налоге антивируса на открытие отдельного файла.
Т.е. обороняется только периметр, а внутри чистая бесконтрольная среда.
А уж если антивирь в эвристическом режиме все проверяет, то для него распаковщики - прямо кандидат на подозрение.
Затем все пак файлы мапить в память - и пусть дальше у ОС голова болит, что в какой момент и насколько вперёд.
практика показывает, что открытие большого memory-mapped файла, чтобы поправить в нем пару байт в середине, вызывает тормоза, сопоставимые с полным чтением файла, по крайней мере на ядре 3.10. верните мне досовский hiew
Соответственно, это дешёвый SSD. которму пофиг на оптимизацию движения головок и выстраивание очередей ввода-вывода.на моём ноуте чтение с диска ~ 250 Мб/с, распаковка зип-архива ~30 Мб/с.
Если вдруг пользователь захочет выстрелить себе в ногу - он разместит игру на сетевом диске, с прозрачной архивацией, или на тормозном зеленом Wd на 5400RPM. а если ему очень надо - то на рамдрайве. и профукать весь бонус изза того, что автор программы решил обязательно всё сжимать - просто глупо. нынче на собственное хитрое ИО моральное право имеют только СУБД.Но сжатие я поддерживать обязан просто на всякий случай (а вдруг?).
Тогда тем более не стОит тратить свое время на написание излишне сложного io-кода.На современной машине никто даже заметить индикатор загрузки не успеет.
