Мы взрослые люди, какие минусы? не вижу смысла ставить ни плюс, ни минус, если честно (и тем более гадить в карму без оснований).
Если честно, не ожидал, что вы примете мой комментарий вот так, «в штыки».
По ссылке весь этот класс сплошной говнокод (и я понимаю, что его писали не вы), его очень сложно даже читать, не то, чтобы вникать в суть его работы.
Все это конечно же мое имхо, но было бы лучше (если уж решили написать статью по этому поводу) разжевать проблему, а не приводить в примеры код и отправлять на ссылку к исходникам.
«Вот есть реализация DCL, реализована правильно, но не нужна, так как сам метод ничего не возвращает, к тому же использование вот тут… неправильное, так как вот тут… возникнет проблема такая-то.»
Так какой же в итоге посыл статьи? «не надо так делать»?
Везде есть разработчики, которые как разработчики так себе, это нормально.
Все же, вы не вчитались в мой комментарий. Я понимаю, что написано как не надо делать, но в вашей статье нету полной информации об этом, а та, которая имеется, недостаточна для выводов.
К примеру, я уверен, что вызвав метод prepareFind() в 1000 разных потоков я получу одинаковый результат, т.е. DCL реализован нормально, но вот как он связан с классом TZDBTimeZoneNames я не вижу, потому само место «как не нужно делать» отсутствует в коде.
P.S.
Посмотрел другие ваши статьи — видимо, вы часто встречаетесь с такого рода говнокодом и этот пост стал своеобразной точкой кипения.
Какой посыл у вашей статьи?
Код отвратителен, именования переменных тоже.
Как относится prepareFind() с TZDBTimeZoneNames? В статье ни строки про это.
Если TZDB_NAMES_TRIE не константа, зачем в ее имени капс? Почему не sSingleton?
В тоже самое время, в Java отлично работает вот этот код (взято с википедии):
// Работает с новой семантикой volatile
// Не работает в Java 1.4 и более ранних версиях из-за семантики volatile
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
// и остальные члены класса…
}
Думаю, вы просто не поняли, что вам пытается сказать dampirik
Картинка не будет весить 500 мегабайт, так как это всего лишь её декодированное представление в формате RGBA, т.е. на один пиксель 4 байта. Фактический ее размер в фотмате jpeg будет около нескольких мегабайт.
Путь решения броблемы — загрузить картинку и разбить на тайлы, т.е. по факту картинка станет сеткой (произвольного размера, пусть 256х256 пикселей).
Почему ваш способ плох — для картинки формата jpeg, когда вы запросите определенный ее участок, то ВСЯ картинка дешифруется.
Логика сводится к простому — LoadTilesInsideScreen + UnloadTilesOutsideScreen.
для простоты имена тайлов такие — «poster_cell_X_cell_Y.jpg»
В итоге всё будет производительно и без лагов, так же работает google_maps.
Про фразу «Растровые карты — прошлый век»: Я не очень представляю, как хранить это в векторе LINK
Понял, спасибо.
Ради любопытства посмотрел в исходники ArrayList в Java. Там множитель 1.5 (size + (size>>1)), при этом минимальный инкремент равен 12.
Интересная статья. Но если им так критично выделение памяти, зачем копировать объекты на новый участок и удалять со старого? Ведь можно иметь много массивов. К примеру, есть вектор, в нем массив A[2000], в него нужно добавить 2001 элемент, мы создаем массив B[vector.length*1.3], добавляем в B[0] наш элемент, length вернет 2001, capacity будет 4600.
Вектор же при вызове get(2001) просто пройдет все массивы (по какому-либо оптимизированному алгоритму, ведь суммарная длина всех известна) и вернет из нужного искомый элемент.
Если ресурсы были подготовлены под разрешение 1920х1080, а игра запускается на телефоне с разрешением 800х480, то смысла сохранять исходный размер я не вижу, так как в результате картинки в любом случае будут меньшего размера.
Повторюсь - проблемы с ООМ часто бывают из-за кривых рук.
Устройство для тестов 2011 года с разрешением 800х480, 512 ОЗУ, 1 ГГЦ:
Игра «Swing copters» имеет лишь одну текстуру 2048х2048 и падает с ООМ сразу после старта.
Игра «Mad Bomber» загружает на старте много больше текстур и всё работает.
Игра «GTA 3» загружается без проблем и работает.
Вашу проблему с ООМ в libgdx идеально решил бы TextureFilter.MipMapNearestNearest.
По поводу «плавной» смены скринов — я не говорил, что буду это рассматривать,
ведь статья о загрузчике и о загрузке зашифрованных ресурсов.
Я рассматривал ситауцию, в которой нужно показать скрин, ресурсы для которого еще не загружены.
Спасибо за отзыв!
Вообще, архитектура приложения очень гибкая, и каждый скрин предоставляет своего загрузчика (это может быть один и тот же загрузчик, а могут быть и разные) при утрате контекста (pause/resume).
Потому, при необходимости удалять ресурсы до загрузки, ничего не мешает переопределить метод базового класса в очередном своем загрузчике.
На эту проблему можно посмотреть с другой стороны — на игровом экране имеются 60% неуникальных объектов (главный герой, боты, ui и прочее) и только 40% уникального контента, который тоже может быть неуникальным (тайлы карты, при смене левела могут быть новые, а могут остаться те же). В вашем случае пользователю придется ожидать загрузки ресурсов, которые уже были загружены. Выход — иметь разные загрузчики для разных ситуаций, и данная архитектура это позволяет.
Что вы подразумеваете под плавной сменой скринов?
Я не верю в OutOfMemory
Я написал игру, в которой на старте загружались вообще все ресурсы. Проблемы возникали лишь при утрате контекста — тогда пользователю приходилось ждать по 10 секунд на слабом девайсе для загрузки текстур. OutOfMemory может возникнуть, если что-то было не учтено, например одна текстура не помещается в видеопамять (такая проблема в игре «Swing Copters» с текстурой 2048х2048, но на том же устройстве работает игра, где на старте грузятся 6 таких текстур, да и работает GTA). Решение этой проблемы кроется в использовании TextureFilter.MipMapNearestNearest. При загрузке текстуры на устройство с маленьким экраном текстура размером 2048х2048 будет уменьшена (например) до 512х512.
Не нужно дерзить мне.
Мне не нужно знать, что вы подразумевали под прослойкой, этот вопрос задал автор, и получил хамский ответ.
Также не нужно притягивать за уши аналогии — ваши слова «сервак зачастую является прослойкой между БД и клиентом» в корне неверны, так как между БД и клиентом всегда будет сервер, обзывайте его как хотите — «сервер баз данных», «сервер, дающий из базы клиенту JSON».
Клиент-серверные приложения так потому и называются — там может не быть БД или быть много чего еще, но клиент и сервер всегда.
Пока от вас много воды и мало по делу. Что вы мне пытаетесь доказать? Ответьте, что может быть между БД и клиентом, как не сервер?
А я прочитал и получил такой смысл:
Если бы было «Ваш перевод не дает моей мечте сбыться» было бы другое дело.
Тут же говорится именно о том, что перевод пусть не идеальный, но хороший, и потому благодаря таким переводам как ваш мечта не увядает (хотя и не исполняется).
Единственное, в чем видеокарта от ATI уступает — количеством памяти, а именно 8 GB против 12 GB.
Производительность же 11.5 TFLOPS против 8 TFLOPS.
Если учесть цену 1500$ против 3000$, можно сделать объективные выводы.
Если честно, не ожидал, что вы примете мой комментарий вот так, «в штыки».
По ссылке весь этот класс сплошной говнокод (и я понимаю, что его писали не вы), его очень сложно даже читать, не то, чтобы вникать в суть его работы.
Все это конечно же мое имхо, но было бы лучше (если уж решили написать статью по этому поводу) разжевать проблему, а не приводить в примеры код и отправлять на ссылку к исходникам.
Везде есть разработчики, которые как разработчики так себе, это нормально.
Все же, вы не вчитались в мой комментарий. Я понимаю, что написано как не надо делать, но в вашей статье нету полной информации об этом, а та, которая имеется, недостаточна для выводов.
К примеру, я уверен, что вызвав метод prepareFind() в 1000 разных потоков я получу одинаковый результат, т.е. DCL реализован нормально, но вот как он связан с классом TZDBTimeZoneNames я не вижу, потому само место «как не нужно делать» отсутствует в коде.
P.S.
Посмотрел другие ваши статьи — видимо, вы часто встречаетесь с такого рода говнокодом и этот пост стал своеобразной точкой кипения.
Код отвратителен, именования переменных тоже.
Как относится prepareFind() с TZDBTimeZoneNames? В статье ни строки про это.
Если TZDB_NAMES_TRIE не константа, зачем в ее имени капс? Почему не sSingleton?
В тоже самое время, в Java отлично работает вот этот код (взято с википедии):
Картинка не будет весить 500 мегабайт, так как это всего лишь её декодированное представление в формате RGBA, т.е. на один пиксель 4 байта. Фактический ее размер в фотмате jpeg будет около нескольких мегабайт.
Путь решения броблемы — загрузить картинку и разбить на тайлы, т.е. по факту картинка станет сеткой (произвольного размера, пусть 256х256 пикселей).
Почему ваш способ плох — для картинки формата jpeg, когда вы запросите определенный ее участок, то ВСЯ картинка дешифруется.
Логика сводится к простому — LoadTilesInsideScreen + UnloadTilesOutsideScreen.
для простоты имена тайлов такие — «poster_cell_X_cell_Y.jpg»
В итоге всё будет производительно и без лагов, так же работает google_maps.
Про фразу «Растровые карты — прошлый век»: Я не очень представляю, как хранить это в векторе LINK
Ради любопытства посмотрел в исходники ArrayList в Java. Там множитель 1.5 (size + (size>>1)), при этом минимальный инкремент равен 12.
Вектор же при вызове get(2001) просто пройдет все массивы (по какому-либо оптимизированному алгоритму, ведь суммарная длина всех известна) и вернет из нужного искомый элемент.
Игра «Swing copters» имеет лишь одну текстуру 2048х2048 и падает с ООМ сразу после старта.
Игра «Mad Bomber» загружает на старте много больше текстур и всё работает.
Игра «GTA 3» загружается без проблем и работает.
По поводу «плавной» смены скринов — я не говорил, что буду это рассматривать,
ведь статья о загрузчике и о загрузке зашифрованных ресурсов.
Я рассматривал ситауцию, в которой нужно показать скрин, ресурсы для которого еще не загружены.
Вообще, архитектура приложения очень гибкая, и каждый скрин предоставляет своего загрузчика (это может быть один и тот же загрузчик, а могут быть и разные) при утрате контекста (pause/resume).
Потому, при необходимости удалять ресурсы до загрузки, ничего не мешает переопределить метод базового класса в очередном своем загрузчике.
На эту проблему можно посмотреть с другой стороны — на игровом экране имеются 60% неуникальных объектов (главный герой, боты, ui и прочее) и только 40% уникального контента, который тоже может быть неуникальным (тайлы карты, при смене левела могут быть новые, а могут остаться те же). В вашем случае пользователю придется ожидать загрузки ресурсов, которые уже были загружены. Выход — иметь разные загрузчики для разных ситуаций, и данная архитектура это позволяет.
Что вы подразумеваете под плавной сменой скринов?
Вы же говорите так, словно это невозможно:
Мяч для игры в гольф
Шарики с водой
Футбольный мяч (о лицо, но суть ясна)
Мне не нужно знать, что вы подразумевали под прослойкой, этот вопрос задал автор, и получил хамский ответ.
Также не нужно притягивать за уши аналогии — ваши слова «сервак зачастую является прослойкой между БД и клиентом» в корне неверны, так как между БД и клиентом всегда будет сервер, обзывайте его как хотите — «сервер баз данных», «сервер, дающий из базы клиенту JSON».
Клиент-серверные приложения так потому и называются — там может не быть БД или быть много чего еще, но клиент и сервер всегда.
Пока от вас много воды и мало по делу. Что вы мне пытаетесь доказать? Ответьте, что может быть между БД и клиентом, как не сервер?
Если бы было «Ваш перевод не дает моей мечте сбыться» было бы другое дело.
Тут же говорится именно о том, что перевод пусть не идеальный, но хороший, и потому благодаря таким переводам как ваш мечта не увядает (хотя и не исполняется).
Производительность же 11.5 TFLOPS против 8 TFLOPS.
Если учесть цену 1500$ против 3000$, можно сделать объективные выводы.