mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-19 18:55:18 +00:00
f
This commit is contained in:
parent
4489197d01
commit
5c19ae0e94
@ -26,6 +26,7 @@ import com.volmit.iris.core.link.MythicMobsLink;
|
|||||||
import com.volmit.iris.core.link.OraxenLink;
|
import com.volmit.iris.core.link.OraxenLink;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
|
import com.volmit.iris.core.service.PreservationSVC;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.engine.object.IrisBiome;
|
import com.volmit.iris.engine.object.IrisBiome;
|
||||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||||
@ -450,6 +451,8 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
J.a(ServerConfigurator::configure, 20);
|
J.a(ServerConfigurator::configure, 20);
|
||||||
splash();
|
splash();
|
||||||
|
|
||||||
|
J.sr(() -> Iris.service(PreservationSVC.class).printCaches(), 20);
|
||||||
|
|
||||||
if (IrisSettings.get().getStudio().isAutoStartDefaultStudio()) {
|
if (IrisSettings.get().getStudio().isAutoStartDefaultStudio()) {
|
||||||
Iris.info("Starting up auto Studio!");
|
Iris.info("Starting up auto Studio!");
|
||||||
try {
|
try {
|
||||||
|
@ -64,7 +64,11 @@ public class IrisSettings {
|
|||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsPerformance {
|
public static class IrisSettingsPerformance {
|
||||||
public int mantleKeepAliveSeconds = 60;
|
public int mantleKeepAliveSeconds = 60;
|
||||||
public int cacheSize = 131072;
|
public int maxStreamCacheSize = 1_000_000;
|
||||||
|
public int maxResourceLoaderCacheSize = 1_000;
|
||||||
|
public int maxObjectLoaderCacheSize = 3_000;
|
||||||
|
public int maxScriptLoaderCacheSize = 500;
|
||||||
|
public double cacheMemoryPercentage = 0.65;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -71,6 +71,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
private static final KMap<File, IrisData> dataLoaders = new KMap<>();
|
private static final KMap<File, IrisData> dataLoaders = new KMap<>();
|
||||||
private final File dataFolder;
|
private final File dataFolder;
|
||||||
private final int id;
|
private final int id;
|
||||||
|
private boolean closed = false;
|
||||||
private ResourceLoader<IrisBiome> biomeLoader;
|
private ResourceLoader<IrisBiome> biomeLoader;
|
||||||
private ResourceLoader<IrisLootTable> lootLoader;
|
private ResourceLoader<IrisLootTable> lootLoader;
|
||||||
private ResourceLoader<IrisRegion> regionLoader;
|
private ResourceLoader<IrisRegion> regionLoader;
|
||||||
@ -115,7 +116,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
int m = 0;
|
int m = 0;
|
||||||
for (IrisData i : dataLoaders.values()) {
|
for (IrisData i : dataLoaders.values()) {
|
||||||
for (ResourceLoader<?> j : i.getLoaders().values()) {
|
for (ResourceLoader<?> j : i.getLoaders().values()) {
|
||||||
m += j.getLoadCache().size();
|
m += j.getLoadCache().getSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +124,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void printData(ResourceLoader<?> rl) {
|
private static void printData(ResourceLoader<?> rl) {
|
||||||
Iris.warn(" " + rl.getResourceTypeName() + " @ /" + rl.getFolderName() + ": Cache=" + rl.getLoadCache().size() + " Folders=" + rl.getFolders().size());
|
Iris.warn(" " + rl.getResourceTypeName() + " @ /" + rl.getFolderName() + ": Cache=" + rl.getLoadCache().getSize() + " Folders=" + rl.getFolders().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IrisObject loadAnyObject(String key) {
|
public static IrisObject loadAnyObject(String key) {
|
||||||
@ -274,6 +275,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
closed = true;
|
||||||
dump();
|
dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,11 +288,11 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
IrisRegistrant rr = registrant.getConstructor().newInstance();
|
IrisRegistrant rr = registrant.getConstructor().newInstance();
|
||||||
ResourceLoader<T> r = null;
|
ResourceLoader<T> r = null;
|
||||||
if (registrant.equals(IrisObject.class)) {
|
if (registrant.equals(IrisObject.class)) {
|
||||||
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
|
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||||
} else if (registrant.equals(IrisMatter.class)) {
|
rr.getTypeName());
|
||||||
r = (ResourceLoader<T>) new MatterResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
|
|
||||||
} else if (registrant.equals(IrisScript.class)) {
|
} else if (registrant.equals(IrisScript.class)) {
|
||||||
r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
|
r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||||
|
rr.getTypeName());
|
||||||
} else {
|
} else {
|
||||||
J.attempt(() -> registrant.getConstructor().newInstance().registerTypeAdapters(builder));
|
J.attempt(() -> registrant.getConstructor().newInstance().registerTypeAdapters(builder));
|
||||||
r = new ResourceLoader<>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
r = new ResourceLoader<>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
||||||
@ -460,4 +462,8 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
return l;
|
return l;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClosed() {
|
||||||
|
return closed;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,228 +0,0 @@
|
|||||||
/*
|
|
||||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
|
||||||
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.volmit.iris.core.loader;
|
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
|
||||||
import com.volmit.iris.util.collection.KList;
|
|
||||||
import com.volmit.iris.util.collection.KMap;
|
|
||||||
import com.volmit.iris.util.collection.KSet;
|
|
||||||
import com.volmit.iris.util.format.C;
|
|
||||||
import com.volmit.iris.util.format.Form;
|
|
||||||
import com.volmit.iris.util.math.M;
|
|
||||||
import com.volmit.iris.util.matter.IrisMatter;
|
|
||||||
import com.volmit.iris.util.matter.Matter;
|
|
||||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
|
||||||
import com.volmit.iris.util.scheduling.J;
|
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
public class MatterResourceLoader extends ResourceLoader<IrisMatter> {
|
|
||||||
private final ChronoLatch useFlip = new ChronoLatch(2222);
|
|
||||||
private final KMap<String, Long> useCache = new KMap<>();
|
|
||||||
private final ChronoLatch cl;
|
|
||||||
private final AtomicInteger unload;
|
|
||||||
|
|
||||||
public MatterResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
|
||||||
super(root, idm, folderName, resourceTypeName, IrisMatter.class);
|
|
||||||
cl = new ChronoLatch(30000);
|
|
||||||
unload = new AtomicInteger(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean supportsSchemas() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSize() {
|
|
||||||
return loadCache.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotalStorage() {
|
|
||||||
return getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clean() {
|
|
||||||
if (useFlip.flip()) {
|
|
||||||
unloadLast(30000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unloadLast(long age) {
|
|
||||||
String v = getOldest();
|
|
||||||
|
|
||||||
if (v == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (M.ms() - useCache.get(v) > age) {
|
|
||||||
unload(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getOldest() {
|
|
||||||
long min = M.ms();
|
|
||||||
String v = null;
|
|
||||||
|
|
||||||
for (String i : useCache.k()) {
|
|
||||||
long t = useCache.get(i);
|
|
||||||
if (t < min) {
|
|
||||||
min = t;
|
|
||||||
v = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unload(String v) {
|
|
||||||
lock.lock();
|
|
||||||
useCache.remove(v);
|
|
||||||
loadCache.remove(v);
|
|
||||||
lock.unlock();
|
|
||||||
unload.getAndIncrement();
|
|
||||||
|
|
||||||
if (unload.get() == 1) {
|
|
||||||
cl.flip();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cl.flip()) {
|
|
||||||
J.a(() -> {
|
|
||||||
Iris.verbose("Unloaded " + C.WHITE + unload.get() + " " + resourceTypeName + (unload.get() == 1 ? "" : "s") + C.GRAY + " to optimize memory usage." + " (" + Form.f(getLoadCache().size()) + " " + resourceTypeName + (loadCache.size() == 1 ? "" : "s") + " Loaded)");
|
|
||||||
unload.set(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IrisMatter loadFile(File j, String key, String name) {
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
|
||||||
IrisMatter t = (IrisMatter) Matter.read(j);
|
|
||||||
loadCache.put(key, t);
|
|
||||||
t.setLoadKey(name);
|
|
||||||
t.setLoader(manager);
|
|
||||||
t.setLoadFile(j);
|
|
||||||
logLoad(j, t);
|
|
||||||
lock.unlock();
|
|
||||||
tlt.addAndGet(p.getMilliseconds());
|
|
||||||
return t;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Iris.reportError(e);
|
|
||||||
lock.unlock();
|
|
||||||
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getPossibleKeys() {
|
|
||||||
if (possibleKeys != null) {
|
|
||||||
return possibleKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
|
||||||
KSet<String> m = new KSet<>();
|
|
||||||
|
|
||||||
for (File i : getFolders()) {
|
|
||||||
for (File j : i.listFiles()) {
|
|
||||||
if (j.isFile() && j.getName().endsWith(".matter")) {
|
|
||||||
m.add(j.getName().replaceAll("\\Q.matter\\E", ""));
|
|
||||||
} else if (j.isDirectory()) {
|
|
||||||
for (File k : j.listFiles()) {
|
|
||||||
if (k.isFile() && k.getName().endsWith(".matter")) {
|
|
||||||
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.matter\\E", ""));
|
|
||||||
} else if (k.isDirectory()) {
|
|
||||||
for (File l : k.listFiles()) {
|
|
||||||
if (l.isFile() && l.getName().endsWith(".matter")) {
|
|
||||||
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.matter\\E", ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KList<String> v = new KList<>(m);
|
|
||||||
possibleKeys = v.toArray(new String[0]);
|
|
||||||
return possibleKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File findFile(String name) {
|
|
||||||
lock.lock();
|
|
||||||
for (File i : getFolders(name)) {
|
|
||||||
for (File j : i.listFiles()) {
|
|
||||||
if (j.isFile() && j.getName().endsWith(".matter") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
|
||||||
lock.unlock();
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = new File(i, name + ".matter");
|
|
||||||
|
|
||||||
if (file.exists()) {
|
|
||||||
lock.unlock();
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
|
||||||
|
|
||||||
lock.unlock();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IrisMatter load(String name) {
|
|
||||||
return load(name, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IrisMatter load(String name, boolean warn) {
|
|
||||||
String key = name + "-" + objectClass.getCanonicalName();
|
|
||||||
|
|
||||||
if (loadCache.containsKey(key)) {
|
|
||||||
IrisMatter t = loadCache.get(key);
|
|
||||||
useCache.put(key, M.ms());
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock.lock();
|
|
||||||
for (File i : getFolders(name)) {
|
|
||||||
for (File j : i.listFiles()) {
|
|
||||||
if (j.isFile() && j.getName().endsWith(".matter") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
|
||||||
useCache.put(key, M.ms());
|
|
||||||
lock.unlock();
|
|
||||||
return loadFile(j, key, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = new File(i, name + ".matter");
|
|
||||||
|
|
||||||
if (file.exists()) {
|
|
||||||
useCache.put(key, M.ms());
|
|
||||||
lock.unlock();
|
|
||||||
return loadFile(file, key, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
|
||||||
|
|
||||||
lock.unlock();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,10 +19,12 @@
|
|||||||
package com.volmit.iris.core.loader;
|
package com.volmit.iris.core.loader;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.engine.object.IrisObject;
|
import com.volmit.iris.engine.object.IrisObject;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.data.KCache;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.math.M;
|
import com.volmit.iris.util.math.M;
|
||||||
@ -34,94 +36,29 @@ import java.io.File;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||||
private final ChronoLatch useFlip = new ChronoLatch(2222);
|
|
||||||
private final KMap<String, Long> useCache = new KMap<>();
|
|
||||||
private final ChronoLatch cl;
|
|
||||||
private final AtomicInteger unload;
|
|
||||||
|
|
||||||
public ObjectResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
public ObjectResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||||
super(root, idm, folderName, resourceTypeName, IrisObject.class);
|
super(root, idm, folderName, resourceTypeName, IrisObject.class);
|
||||||
cl = new ChronoLatch(30000);
|
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getMaxObjectLoaderCacheSize());
|
||||||
unload = new AtomicInteger(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supportsSchemas() {
|
public boolean supportsSchemas() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
public long getSize() {
|
||||||
return loadCache.size();
|
return loadCache.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTotalStorage() {
|
public long getTotalStorage() {
|
||||||
int m = 0;
|
return getSize();
|
||||||
|
|
||||||
for (IrisObject i : loadCache.values()) {
|
|
||||||
m += i.getBlocks().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clean() {
|
protected IrisObject loadFile(File j, String name) {
|
||||||
if (useFlip.flip()) {
|
|
||||||
unloadLast(30000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unloadLast(long age) {
|
|
||||||
String v = getOldest();
|
|
||||||
|
|
||||||
if (v == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (M.ms() - useCache.get(v) > age) {
|
|
||||||
unload(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getOldest() {
|
|
||||||
long min = M.ms();
|
|
||||||
String v = null;
|
|
||||||
|
|
||||||
for (String i : useCache.k()) {
|
|
||||||
long t = useCache.get(i);
|
|
||||||
if (t < min) {
|
|
||||||
min = t;
|
|
||||||
v = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unload(String v) {
|
|
||||||
lock.lock();
|
|
||||||
useCache.remove(v);
|
|
||||||
loadCache.remove(v);
|
|
||||||
lock.unlock();
|
|
||||||
unload.getAndIncrement();
|
|
||||||
|
|
||||||
if (unload.get() == 1) {
|
|
||||||
cl.flip();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cl.flip()) {
|
|
||||||
J.a(() -> {
|
|
||||||
Iris.verbose("Unloaded " + C.WHITE + unload.get() + " " + resourceTypeName + (unload.get() == 1 ? "" : "s") + C.GRAY + " to optimize memory usage." + " (" + Form.f(getLoadCache().size()) + " " + resourceTypeName + (loadCache.size() == 1 ? "" : "s") + " Loaded)");
|
|
||||||
unload.set(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IrisObject loadFile(File j, String key, String name) {
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
IrisObject t = new IrisObject(0, 0, 0);
|
IrisObject t = new IrisObject(0, 0, 0);
|
||||||
t.read(j);
|
t.read(j);
|
||||||
loadCache.put(key, t);
|
|
||||||
t.setLoadKey(name);
|
t.setLoadKey(name);
|
||||||
t.setLoader(manager);
|
t.setLoader(manager);
|
||||||
t.setLoadFile(j);
|
t.setLoadFile(j);
|
||||||
@ -198,31 +135,21 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
|||||||
return load(name, true);
|
return load(name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IrisObject load(String name, boolean warn) {
|
private IrisObject loadRaw(String name){
|
||||||
String key = name + "-" + objectClass.getCanonicalName();
|
|
||||||
|
|
||||||
if (loadCache.containsKey(key)) {
|
|
||||||
IrisObject t = loadCache.get(key);
|
|
||||||
useCache.put(key, M.ms());
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
for (File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for (File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if (j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
useCache.put(key, M.ms());
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
return loadFile(j, key, name);
|
return loadFile(j, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(i, name + ".iob");
|
File file = new File(i, name + ".iob");
|
||||||
|
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
useCache.put(key, M.ms());
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
return loadFile(file, key, name);
|
return loadFile(file, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,4 +158,8 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
|||||||
lock.unlock();
|
lock.unlock();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IrisObject load(String name, boolean warn) {
|
||||||
|
return loadCache.get(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,14 @@ package com.volmit.iris.core.loader;
|
|||||||
|
|
||||||
import com.google.common.util.concurrent.AtomicDouble;
|
import com.google.common.util.concurrent.AtomicDouble;
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.project.SchemaBuilder;
|
import com.volmit.iris.core.project.SchemaBuilder;
|
||||||
|
import com.volmit.iris.core.service.PreservationSVC;
|
||||||
|
import com.volmit.iris.engine.framework.MeteredCache;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KMap;
|
import com.volmit.iris.util.collection.KMap;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.data.KCache;
|
||||||
import com.volmit.iris.util.format.C;
|
import com.volmit.iris.util.format.C;
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
@ -42,13 +46,13 @@ import java.util.function.Predicate;
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ResourceLoader<T extends IrisRegistrant> {
|
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||||
private static final int CACHE_SIZE = 100000;
|
private static final int CACHE_SIZE = 100000;
|
||||||
protected File root;
|
protected File root;
|
||||||
protected String folderName;
|
protected String folderName;
|
||||||
protected String resourceTypeName;
|
protected String resourceTypeName;
|
||||||
protected KMap<String, T> loadCache;
|
protected KCache<String, T> loadCache;
|
||||||
protected KList<File> folderCache;
|
protected KList<File> folderCache;
|
||||||
protected Class<? extends T> objectClass;
|
protected Class<? extends T> objectClass;
|
||||||
protected String cname;
|
protected String cname;
|
||||||
@ -68,8 +72,9 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
this.resourceTypeName = resourceTypeName;
|
this.resourceTypeName = resourceTypeName;
|
||||||
this.root = root;
|
this.root = root;
|
||||||
this.folderName = folderName;
|
this.folderName = folderName;
|
||||||
loadCache = new KMap<>();
|
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getMaxResourceLoaderCacheSize());
|
||||||
Iris.debug("Loader<" + C.GREEN + resourceTypeName + C.LIGHT_PURPLE + "> created in " + C.RED + "IDM/" + manager.getId() + C.LIGHT_PURPLE + " on " + C.GRAY + manager.getDataFolder().getPath());
|
Iris.debug("Loader<" + C.GREEN + resourceTypeName + C.LIGHT_PURPLE + "> created in " + C.RED + "IDM/" + manager.getId() + C.LIGHT_PURPLE + " on " + C.GRAY + manager.getDataFolder().getPath());
|
||||||
|
Iris.service(PreservationSVC.class).registerCache(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject buildSchema() {
|
public JSONObject buildSchema() {
|
||||||
@ -122,7 +127,7 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
|
|
||||||
if (sec.flip()) {
|
if (sec.flip()) {
|
||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
Iris.verbose("Loaded " + C.WHITE + loads.get() + " " + resourceTypeName + (loads.get() == 1 ? "" : "s") + C.GRAY + " (" + Form.f(getLoadCache().size()) + " " + resourceTypeName + (loadCache.size() == 1 ? "" : "s") + " Loaded)");
|
Iris.verbose("Loaded " + C.WHITE + loads.get() + " " + resourceTypeName + (loads.get() == 1 ? "" : "s") + C.GRAY + " (" + Form.f(getLoadCache().getSize()) + " " + resourceTypeName + (loadCache.getSize() == 1 ? "" : "s") + " Loaded)");
|
||||||
loads.set(0);
|
loads.set(0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -177,10 +182,10 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long count() {
|
public long count() {
|
||||||
return loadCache.size();
|
return loadCache.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected T loadFile(File j, String key, String name) {
|
protected T loadFile(File j, String name) {
|
||||||
try {
|
try {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
T t = getManager().getGson()
|
T t = getManager().getGson()
|
||||||
@ -189,7 +194,6 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
t.setLoadFile(j);
|
t.setLoadFile(j);
|
||||||
t.setLoader(manager);
|
t.setLoader(manager);
|
||||||
getManager().preprocessObject(t);
|
getManager().preprocessObject(t);
|
||||||
loadCache.put(key, t);
|
|
||||||
logLoad(j, t);
|
logLoad(j, t);
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
tlt.addAndGet(p.getMilliseconds());
|
tlt.addAndGet(p.getMilliseconds());
|
||||||
@ -242,6 +246,28 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
return load(name, true);
|
return load(name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private T loadRaw(String name)
|
||||||
|
{
|
||||||
|
lock.lock();
|
||||||
|
for (File i : getFolders(name)) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
for (File j : i.listFiles()) {
|
||||||
|
if (j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
|
return loadFile(j, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(i, name + ".json");
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
return loadFile(file, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public T load(String name, boolean warn) {
|
public T load(String name, boolean warn) {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -251,33 +277,7 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = name + "-" + cname;
|
return loadCache.get(name);
|
||||||
|
|
||||||
if (loadCache.containsKey(key)) {
|
|
||||||
return loadCache.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
lock.lock();
|
|
||||||
for (File i : getFolders(name)) {
|
|
||||||
for (File j : i.listFiles()) {
|
|
||||||
if (j.isFile() && j.getName().endsWith(".json") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
|
||||||
return loadFile(j, key, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = new File(i, name + ".json");
|
|
||||||
|
|
||||||
if (file.exists()) {
|
|
||||||
return loadFile(file, key, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (warn && !resourceTypeName.equals("Dimension")) {
|
|
||||||
J.a(() -> Iris.warn("Couldn't find " + resourceTypeName + ": " + name));
|
|
||||||
}
|
|
||||||
|
|
||||||
lock.unlock();
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public KList<File> getFolders() {
|
public KList<File> getFolders() {
|
||||||
@ -323,7 +323,7 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
public void clearCache() {
|
public void clearCache() {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
possibleKeys = null;
|
possibleKeys = null;
|
||||||
loadCache.clear();
|
loadCache.invalidate();
|
||||||
folderCache = null;
|
folderCache = null;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
@ -347,7 +347,7 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLoaded(String next) {
|
public boolean isLoaded(String next) {
|
||||||
return loadCache.containsKey(next);
|
return loadCache.contains(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearList() {
|
public void clearList() {
|
||||||
@ -377,11 +377,21 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
public long getSize() {
|
||||||
return loadCache.size();
|
return loadCache.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTotalStorage() {
|
@Override
|
||||||
|
public long getMaxSize() {
|
||||||
|
return loadCache.getMaxSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosed() {
|
||||||
|
return getManager().isClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTotalStorage() {
|
||||||
return getSize();
|
return getSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,34 +19,35 @@
|
|||||||
package com.volmit.iris.core.loader;
|
package com.volmit.iris.core.loader;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.engine.object.IrisScript;
|
import com.volmit.iris.engine.object.IrisScript;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.collection.KSet;
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.data.KCache;
|
||||||
import com.volmit.iris.util.io.IO;
|
import com.volmit.iris.util.io.IO;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||||
|
|
||||||
public ScriptResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
public ScriptResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||||
super(root, idm, folderName, resourceTypeName, IrisScript.class);
|
super(root, idm, folderName, resourceTypeName, IrisScript.class);
|
||||||
|
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getMaxScriptLoaderCacheSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supportsSchemas() {
|
public boolean supportsSchemas() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSize() {
|
public long getSize() {
|
||||||
return loadCache.size();
|
return loadCache.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IrisScript loadFile(File j, String key, String name) {
|
protected IrisScript loadFile(File j, String name) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
IrisScript t = new IrisScript(IO.readAll(j));
|
IrisScript t = new IrisScript(IO.readAll(j));
|
||||||
loadCache.put(key, t);
|
|
||||||
t.setLoadKey(name);
|
t.setLoadKey(name);
|
||||||
t.setLoader(manager);
|
t.setLoader(manager);
|
||||||
t.setLoadFile(j);
|
t.setLoadFile(j);
|
||||||
@ -119,20 +120,14 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IrisScript load(String name, boolean warn) {
|
private IrisScript loadRaw(String name)
|
||||||
String key = name + "-" + objectClass.getCanonicalName();
|
{
|
||||||
|
|
||||||
if (loadCache.containsKey(key)) {
|
|
||||||
IrisScript t = loadCache.get(key);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
for (File i : getFolders(name)) {
|
for (File i : getFolders(name)) {
|
||||||
for (File j : i.listFiles()) {
|
for (File j : i.listFiles()) {
|
||||||
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
return loadFile(j, key, name);
|
return loadFile(j, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +135,7 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
|
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
return loadFile(file, key, name);
|
return loadFile(file, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,4 +144,8 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
|||||||
lock.unlock();
|
lock.unlock();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IrisScript load(String name, boolean warn) {
|
||||||
|
return loadCache.get(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,19 +19,27 @@
|
|||||||
package com.volmit.iris.core.service;
|
package com.volmit.iris.core.service;
|
||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.framework.MeteredCache;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.context.IrisContext;
|
import com.volmit.iris.util.context.IrisContext;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.parallel.MultiBurst;
|
import com.volmit.iris.util.parallel.MultiBurst;
|
||||||
import com.volmit.iris.util.plugin.IrisService;
|
import com.volmit.iris.util.plugin.IrisService;
|
||||||
import com.volmit.iris.util.scheduling.Looper;
|
import com.volmit.iris.util.scheduling.Looper;
|
||||||
|
import com.volmit.iris.util.stream.utility.CachedStream2D;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
public class PreservationSVC implements IrisService {
|
public class PreservationSVC implements IrisService {
|
||||||
private final KList<Thread> threads = new KList<>();
|
private final KList<Thread> threads = new KList<>();
|
||||||
private final KList<ExecutorService> services = new KList<>();
|
private final KList<ExecutorService> services = new KList<>();
|
||||||
private Looper dereferencer;
|
private Looper dereferencer;
|
||||||
|
private final KList<MeteredCache> caches = new KList<>();
|
||||||
|
|
||||||
public void register(Thread t) {
|
public void register(Thread t) {
|
||||||
threads.add(t);
|
threads.add(t);
|
||||||
@ -45,11 +53,35 @@ public class PreservationSVC implements IrisService {
|
|||||||
services.add(service);
|
services.add(service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void printCaches()
|
||||||
|
{
|
||||||
|
long s = caches.stream().filter(i -> !i.isClosed()).mapToLong(MeteredCache::getSize).sum();
|
||||||
|
long m = caches.stream().filter(i -> !i.isClosed()).mapToLong(MeteredCache::getMaxSize).sum();
|
||||||
|
double p = 0;
|
||||||
|
double mf = 0;
|
||||||
|
|
||||||
|
for(MeteredCache i : caches)
|
||||||
|
{
|
||||||
|
if(i.isClosed())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mf++;
|
||||||
|
p+= i.getUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
mf = mf == 0 ? 1 : mf;
|
||||||
|
|
||||||
|
Iris.info("Cached " + Form.f(s) + " / " + Form.f(m) + " (" + Form.pc(p/mf) + ") from " + caches.size() + " Caches");
|
||||||
|
}
|
||||||
|
|
||||||
public void dereference() {
|
public void dereference() {
|
||||||
IrisContext.dereference();
|
IrisContext.dereference();
|
||||||
IrisData.dereference();
|
IrisData.dereference();
|
||||||
threads.removeWhere((i) -> !i.isAlive());
|
threads.removeWhere((i) -> !i.isAlive());
|
||||||
services.removeWhere(ExecutorService::isShutdown);
|
services.removeWhere(ExecutorService::isShutdown);
|
||||||
|
updateCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -94,4 +126,13 @@ public class PreservationSVC implements IrisService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateCaches()
|
||||||
|
{
|
||||||
|
caches.removeWhere(MeteredCache::isClosed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerCache(MeteredCache cache) {
|
||||||
|
caches.add(cache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IrisComplex(Engine engine, boolean simple) {
|
public IrisComplex(Engine engine, boolean simple) {
|
||||||
int cacheSize = IrisSettings.get().getPerformance().getCacheSize();
|
int cacheSize = IrisSettings.get().getPerformance().getMaxStreamCacheSize();
|
||||||
IrisBiome emptyBiome = new IrisBiome();
|
IrisBiome emptyBiome = new IrisBiome();
|
||||||
UUID focusUUID = UUID.nameUUIDFromBytes("focus".getBytes());
|
UUID focusUUID = UUID.nameUUIDFromBytes("focus".getBytes());
|
||||||
this.rng = new RNG(engine.getSeedManager().getComplex());
|
this.rng = new RNG(engine.getSeedManager().getComplex());
|
||||||
@ -124,7 +124,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
Interpolated.of(a -> 0D, a -> focusRegion))
|
Interpolated.of(a -> 0D, a -> focusRegion))
|
||||||
: regionStyleStream
|
: regionStyleStream
|
||||||
.selectRarity(engine.getDimension().getRegions(), (i) -> data.getRegionLoader().load(i))
|
.selectRarity(engine.getDimension().getRegions(), (i) -> data.getRegionLoader().load(i))
|
||||||
.convertCached((s) -> data.getRegionLoader().load(s)).cache2D(cacheSize);
|
.convertCached((s) -> data.getRegionLoader().load(s)).cache2D(engine, cacheSize);
|
||||||
regionIDStream = regionIdentityStream.convertCached((i) -> new UUID(Double.doubleToLongBits(i), String.valueOf(i * 38445).hashCode() * 3245556666L));
|
regionIDStream = regionIdentityStream.convertCached((i) -> new UUID(Double.doubleToLongBits(i), String.valueOf(i * 38445).hashCode() * 3245556666L));
|
||||||
caveBiomeStream = regionStream.convert((r)
|
caveBiomeStream = regionStream.convert((r)
|
||||||
-> engine.getDimension().getCaveBiomeStyle().create(rng.nextParallelRNG(InferredType.CAVE.ordinal()), getData()).stream()
|
-> engine.getDimension().getCaveBiomeStyle().create(rng.nextParallelRNG(InferredType.CAVE.ordinal()), getData()).stream()
|
||||||
@ -139,7 +139,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
return data.getBiomeLoader().load(s)
|
return data.getBiomeLoader().load(s)
|
||||||
.setInferredType(InferredType.CAVE);
|
.setInferredType(InferredType.CAVE);
|
||||||
})
|
})
|
||||||
).convertAware2D(ProceduralStream::get).cache2D(cacheSize);
|
).convertAware2D(ProceduralStream::get).cache2D(engine, cacheSize);
|
||||||
inferredStreams.put(InferredType.CAVE, caveBiomeStream);
|
inferredStreams.put(InferredType.CAVE, caveBiomeStream);
|
||||||
landBiomeStream = regionStream.convert((r)
|
landBiomeStream = regionStream.convert((r)
|
||||||
-> engine.getDimension().getLandBiomeStyle().create(rng.nextParallelRNG(InferredType.LAND.ordinal()), getData()).stream()
|
-> engine.getDimension().getLandBiomeStyle().create(rng.nextParallelRNG(InferredType.LAND.ordinal()), getData()).stream()
|
||||||
@ -148,7 +148,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
.convertCached((s) -> data.getBiomeLoader().load(s)
|
.convertCached((s) -> data.getBiomeLoader().load(s)
|
||||||
.setInferredType(InferredType.LAND))
|
.setInferredType(InferredType.LAND))
|
||||||
).convertAware2D(ProceduralStream::get)
|
).convertAware2D(ProceduralStream::get)
|
||||||
.cache2D(cacheSize);
|
.cache2D(engine, cacheSize);
|
||||||
inferredStreams.put(InferredType.LAND, landBiomeStream);
|
inferredStreams.put(InferredType.LAND, landBiomeStream);
|
||||||
seaBiomeStream = regionStream.convert((r)
|
seaBiomeStream = regionStream.convert((r)
|
||||||
-> engine.getDimension().getSeaBiomeStyle().create(rng.nextParallelRNG(InferredType.SEA.ordinal()), getData()).stream()
|
-> engine.getDimension().getSeaBiomeStyle().create(rng.nextParallelRNG(InferredType.SEA.ordinal()), getData()).stream()
|
||||||
@ -157,7 +157,7 @@ public class IrisComplex implements DataProvider {
|
|||||||
.convertCached((s) -> data.getBiomeLoader().load(s)
|
.convertCached((s) -> data.getBiomeLoader().load(s)
|
||||||
.setInferredType(InferredType.SEA))
|
.setInferredType(InferredType.SEA))
|
||||||
).convertAware2D(ProceduralStream::get)
|
).convertAware2D(ProceduralStream::get)
|
||||||
.cache2D(cacheSize);
|
.cache2D(engine, cacheSize);
|
||||||
inferredStreams.put(InferredType.SEA, seaBiomeStream);
|
inferredStreams.put(InferredType.SEA, seaBiomeStream);
|
||||||
shoreBiomeStream = regionStream.convert((r)
|
shoreBiomeStream = regionStream.convert((r)
|
||||||
-> engine.getDimension().getShoreBiomeStyle().create(rng.nextParallelRNG(InferredType.SHORE.ordinal()), getData()).stream()
|
-> engine.getDimension().getShoreBiomeStyle().create(rng.nextParallelRNG(InferredType.SHORE.ordinal()), getData()).stream()
|
||||||
@ -165,60 +165,60 @@ public class IrisComplex implements DataProvider {
|
|||||||
.selectRarity(r.getShoreBiomes(), (i) -> data.getBiomeLoader().load(i))
|
.selectRarity(r.getShoreBiomes(), (i) -> data.getBiomeLoader().load(i))
|
||||||
.convertCached((s) -> data.getBiomeLoader().load(s)
|
.convertCached((s) -> data.getBiomeLoader().load(s)
|
||||||
.setInferredType(InferredType.SHORE))
|
.setInferredType(InferredType.SHORE))
|
||||||
).convertAware2D(ProceduralStream::get).cache2D(cacheSize);
|
).convertAware2D(ProceduralStream::get).cache2D(engine, cacheSize);
|
||||||
inferredStreams.put(InferredType.SHORE, shoreBiomeStream);
|
inferredStreams.put(InferredType.SHORE, shoreBiomeStream);
|
||||||
bridgeStream = focus != null ? ProceduralStream.of((x, z) -> focus.getInferredType(),
|
bridgeStream = focus != null ? ProceduralStream.of((x, z) -> focus.getInferredType(),
|
||||||
Interpolated.of(a -> 0D, a -> focus.getInferredType())) :
|
Interpolated.of(a -> 0D, a -> focus.getInferredType())) :
|
||||||
engine.getDimension().getContinentalStyle().create(rng.nextParallelRNG(234234565), getData())
|
engine.getDimension().getContinentalStyle().create(rng.nextParallelRNG(234234565), getData())
|
||||||
.bake().scale(1D / engine.getDimension().getContinentZoom()).bake().stream()
|
.bake().scale(1D / engine.getDimension().getContinentZoom()).bake().stream()
|
||||||
.convert((v) -> v >= engine.getDimension().getLandChance() ? InferredType.SEA : InferredType.LAND).cache2D(cacheSize);
|
.convert((v) -> v >= engine.getDimension().getLandChance() ? InferredType.SEA : InferredType.LAND).cache2D(engine, cacheSize);
|
||||||
baseBiomeStream = focus != null ? ProceduralStream.of((x, z) -> focus,
|
baseBiomeStream = focus != null ? ProceduralStream.of((x, z) -> focus,
|
||||||
Interpolated.of(a -> 0D, a -> focus)) :
|
Interpolated.of(a -> 0D, a -> focus)) :
|
||||||
bridgeStream.convertAware2D((t, x, z) -> inferredStreams.get(t).get(x, z))
|
bridgeStream.convertAware2D((t, x, z) -> inferredStreams.get(t).get(x, z))
|
||||||
.convertAware2D(this::implode).cache2D(cacheSize);
|
.convertAware2D(this::implode).cache2D(engine, cacheSize);
|
||||||
heightStream = ProceduralStream.of((x, z) -> {
|
heightStream = ProceduralStream.of((x, z) -> {
|
||||||
IrisBiome b = focus != null ? focus : baseBiomeStream.get(x, z);
|
IrisBiome b = focus != null ? focus : baseBiomeStream.get(x, z);
|
||||||
return getHeight(engine, b, x, z, engine.getSeedManager().getHeight());
|
return getHeight(engine, b, x, z, engine.getSeedManager().getHeight());
|
||||||
}, Interpolated.DOUBLE).clamp(0, engine.getHeight()).cache2D(cacheSize);
|
}, Interpolated.DOUBLE).clamp(0, engine.getHeight()).cache2D(engine, cacheSize, true);
|
||||||
roundedHeighteightStream = heightStream.round();
|
roundedHeighteightStream = heightStream.round();
|
||||||
slopeStream = heightStream.slope(3).cache2D(cacheSize);
|
slopeStream = heightStream.slope(3).cache2D(engine, cacheSize);
|
||||||
trueBiomeStream = focus != null ? ProceduralStream.of((x, y) -> focus, Interpolated.of(a -> 0D,
|
trueBiomeStream = focus != null ? ProceduralStream.of((x, y) -> focus, Interpolated.of(a -> 0D,
|
||||||
b -> focus))
|
b -> focus))
|
||||||
.cache2D(cacheSize) : heightStream
|
.cache2D(engine, cacheSize) : heightStream
|
||||||
.convertAware2D((h, x, z) ->
|
.convertAware2D((h, x, z) ->
|
||||||
fixBiomeType(h, baseBiomeStream.get(x, z),
|
fixBiomeType(h, baseBiomeStream.get(x, z),
|
||||||
regionStream.get(x, z), x, z, fluidHeight))
|
regionStream.get(x, z), x, z, fluidHeight))
|
||||||
.cache2D(cacheSize);
|
.cache2D(engine, cacheSize);
|
||||||
trueBiomeStream = focus != null ? ProceduralStream.of((x, y) -> focus, Interpolated.of(a -> 0D,
|
trueBiomeStream = focus != null ? ProceduralStream.of((x, y) -> focus, Interpolated.of(a -> 0D,
|
||||||
b -> focus))
|
b -> focus))
|
||||||
.cache2D(cacheSize) : heightStream
|
.cache2D(engine, cacheSize) : heightStream
|
||||||
.convertAware2D((h, x, z) ->
|
.convertAware2D((h, x, z) ->
|
||||||
fixBiomeType(h, baseBiomeStream.get(x, z),
|
fixBiomeType(h, baseBiomeStream.get(x, z),
|
||||||
regionStream.get(x, z), x, z, fluidHeight))
|
regionStream.get(x, z), x, z, fluidHeight))
|
||||||
.cache2D(cacheSize);
|
.cache2D(engine, cacheSize);
|
||||||
trueBiomeDerivativeStream = trueBiomeStream.convert(IrisBiome::getDerivative).cache2D(cacheSize);
|
trueBiomeDerivativeStream = trueBiomeStream.convert(IrisBiome::getDerivative).cache2D(engine, cacheSize);
|
||||||
heightFluidStream = heightStream.max(fluidHeight).cache2D(cacheSize);
|
heightFluidStream = heightStream.max(fluidHeight).cache2D(engine, cacheSize, true);
|
||||||
maxHeightStream = ProceduralStream.ofDouble((x, z) -> height);
|
maxHeightStream = ProceduralStream.ofDouble((x, z) -> height);
|
||||||
terrainSurfaceDecoration = trueBiomeStream
|
terrainSurfaceDecoration = trueBiomeStream
|
||||||
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.NONE)).cache2D(cacheSize);
|
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.NONE)).cache2D(engine, cacheSize);
|
||||||
terrainCeilingDecoration = trueBiomeStream
|
terrainCeilingDecoration = trueBiomeStream
|
||||||
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.CEILING)).cache2D(cacheSize);
|
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.CEILING)).cache2D(engine, cacheSize);
|
||||||
terrainCaveSurfaceDecoration = caveBiomeStream
|
terrainCaveSurfaceDecoration = caveBiomeStream
|
||||||
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.NONE)).cache2D(cacheSize);
|
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.NONE)).cache2D(engine, cacheSize);
|
||||||
terrainCaveCeilingDecoration = caveBiomeStream
|
terrainCaveCeilingDecoration = caveBiomeStream
|
||||||
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.CEILING)).cache2D(cacheSize);
|
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.CEILING)).cache2D(engine, cacheSize);
|
||||||
shoreSurfaceDecoration = trueBiomeStream
|
shoreSurfaceDecoration = trueBiomeStream
|
||||||
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.SHORE_LINE)).cache2D(cacheSize);
|
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.SHORE_LINE)).cache2D(engine, cacheSize);
|
||||||
seaSurfaceDecoration = trueBiomeStream
|
seaSurfaceDecoration = trueBiomeStream
|
||||||
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.SEA_SURFACE)).cache2D(cacheSize);
|
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.SEA_SURFACE)).cache2D(engine, cacheSize);
|
||||||
seaFloorDecoration = trueBiomeStream
|
seaFloorDecoration = trueBiomeStream
|
||||||
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.SEA_FLOOR)).cache2D(cacheSize);
|
.convertAware2D((b, xx, zz) -> decorateFor(b, xx, zz, IrisDecorationPart.SEA_FLOOR)).cache2D(engine, cacheSize);
|
||||||
baseBiomeIDStream = trueBiomeStream.convertAware2D((b, x, z) -> {
|
baseBiomeIDStream = trueBiomeStream.convertAware2D((b, x, z) -> {
|
||||||
UUID d = regionIDStream.get(x, z);
|
UUID d = regionIDStream.get(x, z);
|
||||||
return new UUID(b.getLoadKey().hashCode() * 818223L,
|
return new UUID(b.getLoadKey().hashCode() * 818223L,
|
||||||
d.hashCode());
|
d.hashCode());
|
||||||
})
|
})
|
||||||
.cache2D(cacheSize);
|
.cache2D(engine, cacheSize);
|
||||||
//@done
|
//@done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.engine.framework;
|
||||||
|
|
||||||
|
public interface MeteredCache
|
||||||
|
{
|
||||||
|
long getSize();
|
||||||
|
|
||||||
|
long getMaxSize();
|
||||||
|
|
||||||
|
default double getUsage()
|
||||||
|
{
|
||||||
|
return (double)getSize() / (double)getMaxSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isClosed();
|
||||||
|
}
|
@ -39,6 +39,7 @@ import com.volmit.iris.util.math.RNG;
|
|||||||
import com.volmit.iris.util.matter.MatterCavern;
|
import com.volmit.iris.util.matter.MatterCavern;
|
||||||
import com.volmit.iris.util.matter.slices.MarkerMatter;
|
import com.volmit.iris.util.matter.slices.MarkerMatter;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
import com.volmit.iris.util.stream.utility.CachedStream2D;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
|
82
src/main/java/com/volmit/iris/util/data/KCache.java
Normal file
82
src/main/java/com/volmit/iris/util/data/KCache.java
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||||
|
* Copyright (c) 2021 Arcane Arts (Volmit Software)
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.volmit.iris.util.data;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.CacheLoader;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
|
import com.volmit.iris.engine.framework.MeteredCache;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class KCache<K,V> implements MeteredCache {
|
||||||
|
private long max;
|
||||||
|
private CacheLoader<? super K, ? extends V> loader;
|
||||||
|
private LoadingCache<K, V> cache;
|
||||||
|
|
||||||
|
public KCache(CacheLoader<K, V> loader, long max)
|
||||||
|
{
|
||||||
|
this.max = max;
|
||||||
|
this.loader = loader;
|
||||||
|
this.cache = Caffeine
|
||||||
|
.newBuilder()
|
||||||
|
.maximumSize(max)
|
||||||
|
.build((k) -> loader == null ? null : loader.load(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoader(CacheLoader<? super K, ? extends V> loader)
|
||||||
|
{
|
||||||
|
this.loader = loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidate(K k)
|
||||||
|
{
|
||||||
|
cache.invalidate(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void invalidate()
|
||||||
|
{
|
||||||
|
cache.invalidateAll();
|
||||||
|
cache.cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public V get(K k)
|
||||||
|
{
|
||||||
|
return cache.get(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSize() {
|
||||||
|
return cache.estimatedSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getMaxSize() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(K next) {
|
||||||
|
return cache.getIfPresent(next) != null;
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ package com.volmit.iris.util.stream;
|
|||||||
|
|
||||||
import com.volmit.iris.Iris;
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.IRare;
|
import com.volmit.iris.engine.object.IRare;
|
||||||
import com.volmit.iris.engine.object.IrisStyledRange;
|
import com.volmit.iris.engine.object.IrisStyledRange;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
@ -287,8 +288,12 @@ public interface ProceduralStream<T> extends ProceduralLayer, Interpolated<T> {
|
|||||||
return new To3DStream<T>(this);
|
return new To3DStream<T>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
default ProceduralStream<T> cache2D(int maxSize) {
|
default ProceduralStream<T> cache2D(Engine engine, int maxSize) {
|
||||||
return new CachedStream2D<T>(this, maxSize);
|
return cache2D(engine, maxSize, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
default ProceduralStream<T> cache2D(Engine engine, int maxSize, boolean weak) {
|
||||||
|
return new CachedStream2D<T>(engine, this, maxSize, weak);
|
||||||
}
|
}
|
||||||
|
|
||||||
default ProceduralStream<T> cache3D(int maxSize) {
|
default ProceduralStream<T> cache3D(int maxSize) {
|
||||||
|
@ -18,23 +18,30 @@
|
|||||||
|
|
||||||
package com.volmit.iris.util.stream.utility;
|
package com.volmit.iris.util.stream.utility;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||||
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.service.PreservationSVC;
|
||||||
import com.volmit.iris.engine.data.cache.Cache;
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.framework.MeteredCache;
|
||||||
|
import com.volmit.iris.util.data.KCache;
|
||||||
import com.volmit.iris.util.stream.BasicStream;
|
import com.volmit.iris.util.stream.BasicStream;
|
||||||
import com.volmit.iris.util.stream.ProceduralStream;
|
import com.volmit.iris.util.stream.ProceduralStream;
|
||||||
|
|
||||||
public class CachedStream2D<T> extends BasicStream<T> implements ProceduralStream<T> {
|
public class CachedStream2D<T> extends BasicStream<T> implements ProceduralStream<T>, MeteredCache {
|
||||||
private final ProceduralStream<T> stream;
|
private final ProceduralStream<T> stream;
|
||||||
private final ConcurrentLinkedHashMap<Long, T> cache;
|
private final KCache<Long, T> cache;
|
||||||
|
private final Engine engine;
|
||||||
|
|
||||||
public CachedStream2D(ProceduralStream<T> stream, int size) {
|
public CachedStream2D(Engine engine, ProceduralStream<T> stream, int size, boolean weak) {
|
||||||
super();
|
super();
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
cache = new ConcurrentLinkedHashMap.Builder<Long, T>()
|
this.engine = engine;
|
||||||
.initialCapacity(size)
|
cache = new KCache<>(k -> stream.get(Cache.keyX(k), Cache.keyZ(k)), size);
|
||||||
.maximumWeightedCapacity(size)
|
Iris.service(PreservationSVC.class).registerCache(this);
|
||||||
.concurrencyLevel(32)
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,11 +56,26 @@ public class CachedStream2D<T> extends BasicStream<T> implements ProceduralStrea
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T get(double x, double z) {
|
public T get(double x, double z) {
|
||||||
return cache.compute(Cache.key((int) x, (int) z), (k, v) -> v != null ? v : stream.get((int) x, (int) z));
|
return cache.get(Cache.key((int)x, (int)z));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T get(double x, double y, double z) {
|
public T get(double x, double y, double z) {
|
||||||
return stream.get(x, y, z);
|
return stream.get(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSize() {
|
||||||
|
return cache.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getMaxSize() {
|
||||||
|
return cache.getMaxSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClosed() {
|
||||||
|
return engine.isClosed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user