From 3b9bbd3fbeeefa16dbc7068fe0c1101a0e1668c0 Mon Sep 17 00:00:00 2001 From: iMoHax Date: Tue, 18 Aug 2015 11:49:12 +0300 Subject: [PATCH] optimize berkeleyDB --- .../java/ru/trader/core/VendorsIterator.java | 2 +- .../ru/trader/store/berkeley/BDBMarket.java | 19 +++++++ .../ru/trader/store/berkeley/BDBStore.java | 2 +- .../ru/trader/store/berkeley/PlaceProxy.java | 51 +++++++++++++++---- .../ru/trader/store/berkeley/VendorProxy.java | 37 ++++++++++++-- .../ru/trader/store/berkeley/dao/DAUtils.java | 29 +++++++++-- .../ru/trader/store/berkeley/dao/ItemDA.java | 5 ++ .../ru/trader/store/berkeley/dao/PlaceDA.java | 22 ++++---- .../trader/store/berkeley/dao/VendorDA.java | 1 - .../store/berkeley/entities/BDBPlace.java | 3 +- 10 files changed, 135 insertions(+), 36 deletions(-) diff --git a/core/src/main/java/ru/trader/core/VendorsIterator.java b/core/src/main/java/ru/trader/core/VendorsIterator.java index 54423f8..622ac68 100644 --- a/core/src/main/java/ru/trader/core/VendorsIterator.java +++ b/core/src/main/java/ru/trader/core/VendorsIterator.java @@ -26,7 +26,7 @@ public class VendorsIterator implements Iterator { if (places.hasNext()){ Place place = places.next(); Collection v = place.get(); - if (place.count() > 0){ + if (!v.isEmpty()){ vendors = v.iterator(); nextVendor(); } else { diff --git a/core/src/main/java/ru/trader/store/berkeley/BDBMarket.java b/core/src/main/java/ru/trader/store/berkeley/BDBMarket.java index 9902c5f..79198d7 100644 --- a/core/src/main/java/ru/trader/store/berkeley/BDBMarket.java +++ b/core/src/main/java/ru/trader/store/berkeley/BDBMarket.java @@ -102,6 +102,11 @@ public class BDBMarket extends AbstractMarket { buyItems.remove(item); } + @Override + public Place get(String name) { + return store.getPlaceAccessor().get(name); + } + @Override public Collection get() { return store.getPlaceAccessor().getAll(); @@ -112,11 +117,25 @@ public class BDBMarket extends AbstractMarket { return store.getGroupAccessor().getAll(); } + @Override + public Item getItem(String name) { + return store.getItemAccessor().get(name); + } + @Override public Collection getItems() { return store.getItemAccessor().getAll(); } + @Override + public Collection getVendors(boolean includeTransit) { + Collection vendors = store.getVendorAccessor().getAll(); + if (includeTransit){ + store.getPlaceAccessor().getAll().stream().map(Place::asTransit).forEach(vendors::add); + } + return vendors; + } + @Override public ItemStat getStat(OFFER_TYPE type, Item item) { ItemStat entry = getItemCache(type).get(item); diff --git a/core/src/main/java/ru/trader/store/berkeley/BDBStore.java b/core/src/main/java/ru/trader/store/berkeley/BDBStore.java index 42ec19c..763641e 100644 --- a/core/src/main/java/ru/trader/store/berkeley/BDBStore.java +++ b/core/src/main/java/ru/trader/store/berkeley/BDBStore.java @@ -29,7 +29,7 @@ public class BDBStore { EnvironmentConfig envConfig = new EnvironmentConfig(); envConfig.setAllowCreate(true); envConfig.setSharedCache(true); - envConfig.setTransactional(true); + envConfig.setTransactional(false); dbEnvironment = new Environment(new File(path), envConfig); try { diff --git a/core/src/main/java/ru/trader/store/berkeley/PlaceProxy.java b/core/src/main/java/ru/trader/store/berkeley/PlaceProxy.java index 08da317..42e9f18 100644 --- a/core/src/main/java/ru/trader/store/berkeley/PlaceProxy.java +++ b/core/src/main/java/ru/trader/store/berkeley/PlaceProxy.java @@ -6,16 +6,19 @@ import ru.trader.store.berkeley.entities.BDBPlace; import ru.trader.store.berkeley.entities.BDBVendor; import java.util.Collection; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; public class PlaceProxy extends AbstractPlace { private final BDBPlace place; private BDBStore store; - private long count; + private Collection vendors; + private final ReentrantLock lock = new ReentrantLock(); public PlaceProxy(BDBPlace place, BDBStore store) { this.place = place; this.store = store; - count = -1; + vendors = null; } public PlaceProxy(BDBPlace place, BDBMarket market, BDBStore store) { @@ -51,13 +54,25 @@ public class PlaceProxy extends AbstractPlace { @Override protected void addVendor(Vendor vendor) { store.getVendorAccessor().put(((VendorProxy)vendor).getEntity()); - if (count != -1) count++; + if (vendors != null || lock.isLocked()) { + unsafe( (v) -> { + if (vendors != null){ + vendors.add(vendor); + } + }); + } } @Override protected void removeVendor(Vendor vendor) { store.getVendorAccessor().delete(((VendorProxy)vendor).getEntity()); - if (count != -1) count--; + if (vendors != null || lock.isLocked()) { + unsafe( (v) -> { + if (vendors != null){ + vendors.remove(vendor); + } + }); + } } @Override @@ -82,21 +97,28 @@ public class PlaceProxy extends AbstractPlace { @Override public Collection get() { - return store.getVendorAccessor().getAllByPlace(place.getId()); + if (vendors == null){ + unsafe( (v) -> { + if (vendors == null){ + vendors = store.getVendorAccessor().getAllByPlace(place.getId()); + } + }); + } + return vendors; } @Override public long count() { - if (count == -1){ - count = store.getVendorAccessor().count(place.getId()); + if (vendors != null){ + return vendors.size(); } - return count; + return get().size(); } @Override public boolean isEmpty() { - if (count > -1){ - return count == 0; + if (vendors != null){ + return vendors.isEmpty(); } return !store.getVendorAccessor().contains(place.getId()); } @@ -117,4 +139,13 @@ public class PlaceProxy extends AbstractPlace { public int hashCode() { return place.hashCode(); } + + private void unsafe(Consumer operation){ + lock.lock(); + try { + operation.accept(null); + } finally { + lock.unlock(); + } + } } diff --git a/core/src/main/java/ru/trader/store/berkeley/VendorProxy.java b/core/src/main/java/ru/trader/store/berkeley/VendorProxy.java index 25184c3..7af9847 100644 --- a/core/src/main/java/ru/trader/store/berkeley/VendorProxy.java +++ b/core/src/main/java/ru/trader/store/berkeley/VendorProxy.java @@ -7,6 +7,8 @@ import ru.trader.store.berkeley.entities.BDBVendor; import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; public class VendorProxy extends AbstractVendor { private final BDBVendor vendor; @@ -14,6 +16,7 @@ public class VendorProxy extends AbstractVendor { private Place place; protected Map sell; protected Map buy; + private final ReentrantLock lock = new ReentrantLock(); public VendorProxy(BDBVendor vendor, BDBStore store) { this.vendor = vendor; @@ -21,28 +24,38 @@ public class VendorProxy extends AbstractVendor { } private void initSellCache(){ - sell = new ConcurrentHashMap<>(20, 0.9f, 2); + Map sell = new ConcurrentHashMap<>(20, 0.9f, 2); for (Offer offer : store.getOfferAccessor().getAllByType(vendor.getId(), OFFER_TYPE.SELL)) { sell.put(((ItemProxy)offer.getItem()).getId(), offer); } + this.sell = sell; } private void initBuyCache(){ - buy = new ConcurrentHashMap<>(20, 0.9f, 2); + Map buy = new ConcurrentHashMap<>(20, 0.9f, 2); for (Offer offer : store.getOfferAccessor().getAllByType(vendor.getId(), OFFER_TYPE.BUY)) { buy.put(((ItemProxy)offer.getItem()).getId(), offer); } + this.buy = buy; } private Map getCache(OFFER_TYPE type){ if (type == OFFER_TYPE.SELL){ if (sell == null){ - initSellCache(); + unsafe((v) -> { + if (sell == null){ + initSellCache(); + } + }); } return sell; } else { if (buy == null){ - initBuyCache(); + unsafe((v) -> { + if (buy == null){ + initBuyCache(); + } + }); } return buy; } @@ -120,7 +133,11 @@ public class VendorProxy extends AbstractVendor { @Override public Place getPlace() { if (place == null){ - place = store.getPlaceAccessor().get(vendor.getPlaceId()); + unsafe((v) -> { + if (place == null){ + place = store.getPlaceAccessor().get(vendor.getPlaceId()); + } + }); } return place; } @@ -166,4 +183,14 @@ public class VendorProxy extends AbstractVendor { public int hashCode() { return vendor.hashCode(); } + + private void unsafe(Consumer operation){ + lock.lock(); + try { + operation.accept(null); + } finally { + lock.unlock(); + } + } + } diff --git a/core/src/main/java/ru/trader/store/berkeley/dao/DAUtils.java b/core/src/main/java/ru/trader/store/berkeley/dao/DAUtils.java index c4d5045..dc5068c 100644 --- a/core/src/main/java/ru/trader/store/berkeley/dao/DAUtils.java +++ b/core/src/main/java/ru/trader/store/berkeley/dao/DAUtils.java @@ -4,6 +4,7 @@ package ru.trader.store.berkeley.dao; import java.util.Collection; import java.util.LinkedList; import java.util.function.Function; +import java.util.function.Predicate; import com.sleepycat.persist.EntityCursor; import com.sleepycat.persist.EntityIndex; @@ -12,34 +13,52 @@ import com.sleepycat.persist.SecondaryIndex; public class DAUtils { public static T get(EntityIndex index, K key, Function convertFunc){ - return convertFunc.apply(index.get(key)); + E entry = index.get(key); + return entry != null ? convertFunc.apply(entry) : null; } public static Collection get(EntityIndex index, K from, K to, Function convertFunc){ + return get(index, from, to, convertFunc, null); + } + + public static Collection get(EntityIndex index, K from, K to, Function convertFunc, Predicate filter){ Collection res = new LinkedList<>(); try (EntityCursor cursor = index.entities(from, true, to, true)){ for(E entity : cursor){ - res.add(convertFunc.apply(entity)); + if (filter == null || filter.test(entity)){ + res.add(convertFunc.apply(entity)); + } } } return res; } - public static Collection getAll(EntityIndex index, Function convertFunc){ + return getAll(index, convertFunc, null); + } + + public static Collection getAll(EntityIndex index, Function convertFunc, Predicate filter){ Collection res = new LinkedList<>(); try (EntityCursor cursor = index.entities()){ for(E entity : cursor){ - res.add(convertFunc.apply(entity)); + if (filter == null || filter.test(entity)){ + res.add(convertFunc.apply(entity)); + } } } return res; } public static Collection getAll(SecondaryIndex index, K key, Function convertFunc){ + return getAll(index, key, convertFunc, null); + } + + public static Collection getAll(SecondaryIndex index, K key, Function convertFunc, Predicate filter){ Collection res = new LinkedList<>(); try (EntityCursor cursor = index.subIndex(key).entities()){ for(E entity : cursor){ - res.add(convertFunc.apply(entity)); + if (filter == null || filter.test(entity)){ + res.add(convertFunc.apply(entity)); + } } } return res; diff --git a/core/src/main/java/ru/trader/store/berkeley/dao/ItemDA.java b/core/src/main/java/ru/trader/store/berkeley/dao/ItemDA.java index c468ed4..63a2eb4 100644 --- a/core/src/main/java/ru/trader/store/berkeley/dao/ItemDA.java +++ b/core/src/main/java/ru/trader/store/berkeley/dao/ItemDA.java @@ -23,6 +23,11 @@ public class ItemDA { return DAUtils.get(indexById, id, convertFunc); } + public T get(String name){ + Collection items = DAUtils.getAll(indexById, convertFunc, item -> item.getName().equals(name)); + return items.isEmpty() ? null : items.iterator().next(); + } + public Collection getAll(){ return DAUtils.getAll(indexById, convertFunc); } diff --git a/core/src/main/java/ru/trader/store/berkeley/dao/PlaceDA.java b/core/src/main/java/ru/trader/store/berkeley/dao/PlaceDA.java index 23914ac..fc292c8 100644 --- a/core/src/main/java/ru/trader/store/berkeley/dao/PlaceDA.java +++ b/core/src/main/java/ru/trader/store/berkeley/dao/PlaceDA.java @@ -1,23 +1,23 @@ package ru.trader.store.berkeley.dao; -import com.sleepycat.persist.EntityCursor; import com.sleepycat.persist.EntityStore; import com.sleepycat.persist.PrimaryIndex; import com.sleepycat.persist.SecondaryIndex; import ru.trader.store.berkeley.entities.BDBPlace; import java.util.Collection; -import java.util.LinkedList; import java.util.function.Function; public class PlaceDA { private final PrimaryIndex indexById; + private final SecondaryIndex indexByName; private final SecondaryIndex indexByDistance; private Function convertFunc; public PlaceDA(EntityStore store, Function convertFunc) { this.convertFunc = convertFunc; this.indexById = store.getPrimaryIndex(Long.class, BDBPlace.class); + this.indexByName = store.getSecondaryIndex(indexById, String.class, "name"); this.indexByDistance = store.getSecondaryIndex(indexById, Double.class, "distance"); } @@ -29,22 +29,20 @@ public class PlaceDA { return DAUtils.get(indexById, id, convertFunc); } + public T get(String name){ + return DAUtils.get(indexByName, name, convertFunc); + } + public Collection getAll(){ return DAUtils.getAll(indexById, convertFunc); } public Collection getAll(double x, double y, double z, double radius){ double center = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)); - Collection res = new LinkedList<>(); - try (EntityCursor cursor = indexByDistance.entities(center < radius? 0 : center - radius, true, center + radius, true)) - { - for(BDBPlace entity : cursor){ - double distance = Math.sqrt(Math.pow(x - entity.getX(), 2) + Math.pow(y - entity.getY(), 2) + Math.pow(z - entity.getZ(), 2)); - if (distance <= radius) - res.add(convertFunc.apply(entity)); - } - } - return res; + return DAUtils.get(indexByDistance, center < radius? 0 : center - radius, center + radius, convertFunc, entity -> { + double distance = Math.sqrt(Math.pow(x - entity.getX(), 2) + Math.pow(y - entity.getY(), 2) + Math.pow(z - entity.getZ(), 2)); + return distance <= radius; + }); } public BDBPlace put(BDBPlace place){ diff --git a/core/src/main/java/ru/trader/store/berkeley/dao/VendorDA.java b/core/src/main/java/ru/trader/store/berkeley/dao/VendorDA.java index 8921833..c0bda4d 100644 --- a/core/src/main/java/ru/trader/store/berkeley/dao/VendorDA.java +++ b/core/src/main/java/ru/trader/store/berkeley/dao/VendorDA.java @@ -4,7 +4,6 @@ import com.sleepycat.persist.*; import ru.trader.store.berkeley.entities.BDBVendor; import java.util.Collection; -import java.util.LinkedList; import java.util.function.Function; public class VendorDA { diff --git a/core/src/main/java/ru/trader/store/berkeley/entities/BDBPlace.java b/core/src/main/java/ru/trader/store/berkeley/entities/BDBPlace.java index b1410f0..bed448d 100644 --- a/core/src/main/java/ru/trader/store/berkeley/entities/BDBPlace.java +++ b/core/src/main/java/ru/trader/store/berkeley/entities/BDBPlace.java @@ -5,7 +5,7 @@ import com.sleepycat.persist.model.PrimaryKey; import com.sleepycat.persist.model.Relationship; import com.sleepycat.persist.model.SecondaryKey; -@Entity(version = 1) +@Entity(version = 2) public class BDBPlace { @PrimaryKey(sequence = "P_ID") @@ -14,6 +14,7 @@ public class BDBPlace { @SecondaryKey(relate = Relationship.MANY_TO_ONE) private double distance; + @SecondaryKey(relate = Relationship.MANY_TO_ONE) private String name; private double x; private double y;