Помогите Итерация по всей коллекции или загрузка определенных данных если игрок рядом с ними?

MurlikMurlik

Активный участник
Пользователь
Баллы
96
Доброго времени суток.
Начала тревожить мысль производительности, если я делаю итерацию по огромной коллекции, скажем HashSet.
Например я пишу плагин на свои кровати. Каждый раз когда игрок просыпается с кровати, записывается в бд и в HashSet координаты, имя игрока. (если уже на ней спал то не записывается)
Когда кто либо ломает блок кровати, я тупо делаю итерацию по всей коллекции и ищу совпадения координат, что бы удалить кровать ну и например оповестить владельца. Что произойдет, если скажем, на сервере будет более 100к таких кроватей с разными игроками? (я возможно преувеличил) При разрушении кровати, будет большая задержка, и даже в некоторых случаев просто так, ибо совпадения может и не быть.
Дак вот ближе к сути. Каким образом можно оптимизировать это дело? Слышал что можно каким то образом подгружать поблизости от игрока объекты, правда я не понимаю каким образом, ибо наличие уже такого количества объектов при подгрузке возле игрока, тоже сильно скажется на производительности возможно..
Каким то образом WorldGuard же с огромным количеством приватов спокойно держит на плаву сервер.
 
Ну ты же не подгружаешь всё кровати при запуске сервера, я надеюсь))
загружай кровати, когда заходит игрок, не будет дофига записей (если конечно онлайн не 500+)
 
Ну ты же не подгружаешь всё кровати при запуске сервера, я надеюсь))
загружай кровати, когда заходит игрок, не будет дофига записей (если конечно онлайн не 500+)
К сожалению, в этом и есть вся основная проблема, что я все загружаю в память. Можно взять аналогию с приватами. Владельца привата нет.. но он чудом есть. Тут тоже самое, мне жизненно важно так сказать, держать их всех в памяти, что бы при разрушении другим игроком, был всегда результат.
 
Используй TreeMap. Скорость поиска в больших списках в разы быстрее чем в листе или том же hashset, потому что данные в нем автоматически сортируются. Ну и итерировать самому ничего не надо, просто containsKey(Location).
 
Используй TreeMap. Скорость поиска в больших списках в разы быстрее чем в листе или том же hashset, потому что данные в нем автоматически сортируются. Ну и итерировать самому ничего не надо, просто containsKey(Location).
Ну.. я делаю итерацию что бы получить ссылку на объект. А объект у меня не простой, хранит локацию, баккит игрока, ник. И при сравнении, мне нужно получить объект свой, что бы там уже достать нужные данные этого игрока, у меня там не просто проверка локации)
 
Ещё предложу вариант.
Раздели данные на те, которые формируют ключ, и на остальные.
Например, ключ может включать название мира и x, y, z. Перенеси их в свой маленький pojo, переопредели equals и hashcode (например, lombok-ом). Используй объект такого типа как K в Map<K, V>.
Поиск (когда кто-то ломает кровать) будет O(1).
 
К сожалению, в этом и есть вся основная проблема, что я все загружаю в память. Можно взять аналогию с приватами. Владельца привата нет.. но он чудом есть. Тут тоже самое, мне жизненно важно так сказать, держать их всех в памяти, что бы при разрушении другим игроком, был всегда результат.
Никогда все приваты не висели в памяти, они загружаются по требованию и если какое то время не юзаются - выгружаются. В WG для этого своя система, но есть готовый вариант в гугл либе: https://pastebin.com/2WSe7HN1
Не забудь прочитать документацию, потом что там нужно знать некоторые делали + посмотреть примеры.
 
Ещё предложу вариант.
Раздели данные на те, которые формируют ключ, и на остальные.
Например, ключ может включать название мира и x, y, z. Перенеси их в свой маленький pojo, переопредели equals и hashcode (например, lombok-ом). Используй объект такого типа как K в Map<K, V>.
Поиск (когда кто-то ломает кровать) будет O(1).
Честно говоря, большая часть терминов мне не знакома) Но в остальном, третий раз перечитав, я понял), разве что я без понятия что значит "будет O(1)"? Я слышал про это в некоторых коллекциях, но не могу понять что это значит.
В принципе, я когда выбирал между мапой и сетом, меня больше заинтересовало то, что за одну итерацию я сразу же получу целый объект. По карте более ресурсоемко по моему. Ну вот так я по крайней мере делал:
Код:
private Set<ObjectTest> test = new HashSet<ObjectTest>();

public void testRun(String name) {
ObjectTest ot = null;
for (ObjectTest o : test) {
if (o.getName().equals(name)) {
ot = 0;
break;
}
//а тут я уже делаю что нибудь например
if (ot != null) {
//что то
}

}
}

Код:
private Map<String, ObjectTest> test = new HashMap<String, ObjectTest>();

public void testRun(String name) {
for (String s : test.keySet()) {
if (s.equals(name)) {
ObjectTest ot = test.get(s); //я же получается, делаю итерацию по ключам и потом второй раз итерацию но уже методом карты, что бы вернуть значение.. вроде бы медленнее чем делать тупо по одному сету.
if (ot != null) {
//что то делаю
}
}
}
Поэтому я почти везде использую хешсет. Без понятия, прав ли я, поэтому отписался)
 
https://github.com/alexandrage/Example/blob/master/src/Example/sfg/ChunkConfig.java
И можешь хоть миллиард кровей записывать. Загрузится только проверяемый чанк.
А подгружаемые чанки, должны хранится в какой то коллекции? Я просто еще молод так сказать, вообще без понятия, как реализовать то что вы предлагаете, ну по крайней мере как я понял.
Просто насколько я понял, будет объект в котором информация о координатах самого чанка. А так же, список всех локаций.. и как я понял, при разрушении блока, будет подружатся этот чанк условно говоря, и уже проверка всех кроватей этого объекта? А как я получу этот чанк, если их будет много? Тоже итерацией? Просто вообще не понимаю.
 
Никогда все приваты не висели в памяти, они загружаются по требованию и если какое то время не юзаются - выгружаются. В WG для этого своя система, но есть готовый вариант в гугл либе: https://pastebin.com/2WSe7HN1
Не забудь прочитать документацию, потом что там нужно знать некоторые делали + посмотреть примеры.
Хотел бы узнать принцип работы или хотя бы пример подобной системы)
 
Карты для того нужны, чтобы быстро получить значение по ключу. Они ничего не перебирают.
А стопе, туплю. Я зря делаю итерацию по всем ключам? Мне достаточно просто попробовать достать значение, а там уже в зависимости от данных (например если нулл вернул, значит там пусто и не нашел), я сразу же получу результат?
 
А подгружаемые чанки, должны хранится в какой то коллекции? Я просто еще молод так сказать, вообще без понятия, как реализовать то что вы предлагаете, ну по крайней мере как я понял.
Просто насколько я понял, будет объект в котором информация о координатах самого чанка. А так же, список всех локаций.. и как я понял, при разрушении блока, будет подружатся этот чанк условно говоря, и уже проверка всех кроватей этого объекта? А как я получу этот чанк, если их будет много? Тоже итерацией? Просто вообще не понимаю.
Тут уже все готово же. Тебе только 3 метода юзать add и contains, и время от времени Save для очистки озу. Допишешь сам, если надо записывать больше одного игрока на локацию.
 
Последнее редактирование:
Честно говоря, большая часть терминов мне не знакома) Но в остальном, третий раз перечитав, я понял), разве что я без понятия что значит "будет O(1)"? Я слышал про это в некоторых коллекциях, но не могу понять что это значит.
В принципе, я когда выбирал между мапой и сетом, меня больше заинтересовало то, что за одну итерацию я сразу же получу целый объект. По карте более ресурсоемко по моему. Ну вот так я по крайней мере делал:
Код:
private Set<ObjectTest> test = new HashSet<ObjectTest>();

public void testRun(String name) {
ObjectTest ot = null;
for (ObjectTest o : test) {
if (o.getName().equals(name)) {
ot = 0;
break;
}
//а тут я уже делаю что нибудь например
if (ot != null) {
//что то
}

}
}

Код:
private Map<String, ObjectTest> test = new HashMap<String, ObjectTest>();

public void testRun(String name) {
for (String s : test.keySet()) {
if (s.equals(name)) {
ObjectTest ot = test.get(s); //я же получается, делаю итерацию по ключам и потом второй раз итерацию но уже методом карты, что бы вернуть значение.. вроде бы медленнее чем делать тупо по одному сету.
if (ot != null) {
//что то делаю
}
}
}
Поэтому я почти везде использую хешсет. Без понятия, прав ли я, поэтому отписался)
Хрень ты написал собственно, то что ты скинул, что там, что там везде O(N) (линейное время). Хеш сет использует внутри хеш мапу, открыл бы чтоли посмотрел сорцы
 
Тут уже все готово же. Тебе только 3 метода юзать add и contains, и время от времени Save для очистки озу. Допишешь сам, если надо записывать больше одного игрока на локацию.
Хотел бы узнать, почему используется битовый сдвиг здесь:
int ChunkX = loc.getBlockX() >> 4;
int ChunkZ = loc.getBlockZ() >> 4;
Насколько я понял, это ты получаешь таким образом координаты чанка. Но ведь существует метод loc.getChunk().getX() || loc.getChunk().getZ()
Или без разницы вообще?
 
Хотел бы узнать, почему используется битовый сдвиг здесь:
int ChunkX = loc.getBlockX() >> 4;
int ChunkZ = loc.getBlockZ() >> 4;
Насколько я понял, это ты получаешь таким образом координаты чанка. Но ведь существует метод loc.getChunk().getX() || loc.getChunk().getZ()
Или без разницы вообще?
Ну если там тоже самое, то без разницы.
 
Битовые операции наиболее быстрые.
Так в методе с чанком они же используются, да и посчитаны координаты заранее, так что смысла тут их еще раз выводить из обычных координат нет
 
Назад
Верх