mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 10:12:53 +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.loader.IrisData;
|
||||
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.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
@ -450,6 +451,8 @@ public class Iris extends VolmitPlugin implements Listener {
|
||||
J.a(ServerConfigurator::configure, 20);
|
||||
splash();
|
||||
|
||||
J.sr(() -> Iris.service(PreservationSVC.class).printCaches(), 20);
|
||||
|
||||
if (IrisSettings.get().getStudio().isAutoStartDefaultStudio()) {
|
||||
Iris.info("Starting up auto Studio!");
|
||||
try {
|
||||
|
@ -64,7 +64,11 @@ public class IrisSettings {
|
||||
@Data
|
||||
public static class IrisSettingsPerformance {
|
||||
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
|
||||
|
@ -71,6 +71,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
private static final KMap<File, IrisData> dataLoaders = new KMap<>();
|
||||
private final File dataFolder;
|
||||
private final int id;
|
||||
private boolean closed = false;
|
||||
private ResourceLoader<IrisBiome> biomeLoader;
|
||||
private ResourceLoader<IrisLootTable> lootLoader;
|
||||
private ResourceLoader<IrisRegion> regionLoader;
|
||||
@ -115,7 +116,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
int m = 0;
|
||||
for (IrisData i : dataLoaders.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) {
|
||||
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) {
|
||||
@ -274,6 +275,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
closed = true;
|
||||
dump();
|
||||
}
|
||||
|
||||
@ -286,11 +288,11 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
IrisRegistrant rr = registrant.getConstructor().newInstance();
|
||||
ResourceLoader<T> r = null;
|
||||
if (registrant.equals(IrisObject.class)) {
|
||||
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
|
||||
} else if (registrant.equals(IrisMatter.class)) {
|
||||
r = (ResourceLoader<T>) new MatterResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
|
||||
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(),
|
||||
rr.getTypeName());
|
||||
} 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 {
|
||||
J.attempt(() -> registrant.getConstructor().newInstance().registerTypeAdapters(builder));
|
||||
r = new ResourceLoader<>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
||||
@ -460,4 +462,8 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
||||
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;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisObject;
|
||||
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.data.KCache;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.math.M;
|
||||
@ -34,94 +36,29 @@ import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
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) {
|
||||
super(root, idm, folderName, resourceTypeName, IrisObject.class);
|
||||
cl = new ChronoLatch(30000);
|
||||
unload = new AtomicInteger(0);
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getMaxObjectLoaderCacheSize());
|
||||
}
|
||||
|
||||
public boolean supportsSchemas() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return loadCache.size();
|
||||
public long getSize() {
|
||||
return loadCache.getSize();
|
||||
}
|
||||
|
||||
public int getTotalStorage() {
|
||||
int m = 0;
|
||||
|
||||
for (IrisObject i : loadCache.values()) {
|
||||
m += i.getBlocks().size();
|
||||
public long getTotalStorage() {
|
||||
return getSize();
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
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 IrisObject loadFile(File j, String key, String name) {
|
||||
protected IrisObject loadFile(File j, String name) {
|
||||
lock.lock();
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisObject t = new IrisObject(0, 0, 0);
|
||||
t.read(j);
|
||||
loadCache.put(key, t);
|
||||
t.setLoadKey(name);
|
||||
t.setLoader(manager);
|
||||
t.setLoadFile(j);
|
||||
@ -198,31 +135,21 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||
return load(name, true);
|
||||
}
|
||||
|
||||
public IrisObject load(String name, boolean warn) {
|
||||
String key = name + "-" + objectClass.getCanonicalName();
|
||||
|
||||
if (loadCache.containsKey(key)) {
|
||||
IrisObject t = loadCache.get(key);
|
||||
useCache.put(key, M.ms());
|
||||
return t;
|
||||
}
|
||||
|
||||
private IrisObject loadRaw(String name){
|
||||
lock.lock();
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".iob") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
useCache.put(key, M.ms());
|
||||
lock.unlock();
|
||||
return loadFile(j, key, name);
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
File file = new File(i, name + ".iob");
|
||||
|
||||
if (file.exists()) {
|
||||
useCache.put(key, M.ms());
|
||||
lock.unlock();
|
||||
return loadFile(file, key, name);
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,4 +158,8 @@ public class ObjectResourceLoader extends ResourceLoader<IrisObject> {
|
||||
lock.unlock();
|
||||
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.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
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.KMap;
|
||||
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.Form;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
@ -42,13 +46,13 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Data
|
||||
public class ResourceLoader<T extends IrisRegistrant> {
|
||||
public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
|
||||
public static final AtomicDouble tlt = new AtomicDouble(0);
|
||||
private static final int CACHE_SIZE = 100000;
|
||||
protected File root;
|
||||
protected String folderName;
|
||||
protected String resourceTypeName;
|
||||
protected KMap<String, T> loadCache;
|
||||
protected KCache<String, T> loadCache;
|
||||
protected KList<File> folderCache;
|
||||
protected Class<? extends T> objectClass;
|
||||
protected String cname;
|
||||
@ -68,8 +72,9 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
this.resourceTypeName = resourceTypeName;
|
||||
this.root = root;
|
||||
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.service(PreservationSVC.class).registerCache(this);
|
||||
}
|
||||
|
||||
public JSONObject buildSchema() {
|
||||
@ -122,7 +127,7 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
|
||||
if (sec.flip()) {
|
||||
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);
|
||||
});
|
||||
}
|
||||
@ -177,10 +182,10 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
}
|
||||
|
||||
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 {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
T t = getManager().getGson()
|
||||
@ -189,7 +194,6 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
t.setLoadFile(j);
|
||||
t.setLoader(manager);
|
||||
getManager().preprocessObject(t);
|
||||
loadCache.put(key, t);
|
||||
logLoad(j, t);
|
||||
lock.unlock();
|
||||
tlt.addAndGet(p.getMilliseconds());
|
||||
@ -242,6 +246,28 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
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) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
@ -251,33 +277,7 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
return null;
|
||||
}
|
||||
|
||||
String key = name + "-" + cname;
|
||||
|
||||
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;
|
||||
return loadCache.get(name);
|
||||
}
|
||||
|
||||
public KList<File> getFolders() {
|
||||
@ -323,7 +323,7 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
public void clearCache() {
|
||||
lock.lock();
|
||||
possibleKeys = null;
|
||||
loadCache.clear();
|
||||
loadCache.invalidate();
|
||||
folderCache = null;
|
||||
lock.unlock();
|
||||
}
|
||||
@ -347,7 +347,7 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
}
|
||||
|
||||
public boolean isLoaded(String next) {
|
||||
return loadCache.containsKey(next);
|
||||
return loadCache.contains(next);
|
||||
}
|
||||
|
||||
public void clearList() {
|
||||
@ -377,11 +377,21 @@ public class ResourceLoader<T extends IrisRegistrant> {
|
||||
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return loadCache.size();
|
||||
public long getSize() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -19,34 +19,35 @@
|
||||
package com.volmit.iris.core.loader;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisScript;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
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.scheduling.PrecisionStopwatch;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
|
||||
public ScriptResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||
super(root, idm, folderName, resourceTypeName, IrisScript.class);
|
||||
loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getMaxScriptLoaderCacheSize());
|
||||
}
|
||||
|
||||
public boolean supportsSchemas() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return loadCache.size();
|
||||
public long getSize() {
|
||||
return loadCache.getSize();
|
||||
}
|
||||
|
||||
public IrisScript loadFile(File j, String key, String name) {
|
||||
protected IrisScript loadFile(File j, String name) {
|
||||
lock.lock();
|
||||
try {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
IrisScript t = new IrisScript(IO.readAll(j));
|
||||
loadCache.put(key, t);
|
||||
t.setLoadKey(name);
|
||||
t.setLoader(manager);
|
||||
t.setLoadFile(j);
|
||||
@ -119,20 +120,14 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisScript load(String name, boolean warn) {
|
||||
String key = name + "-" + objectClass.getCanonicalName();
|
||||
|
||||
if (loadCache.containsKey(key)) {
|
||||
IrisScript t = loadCache.get(key);
|
||||
return t;
|
||||
}
|
||||
|
||||
private IrisScript loadRaw(String name)
|
||||
{
|
||||
lock.lock();
|
||||
for (File i : getFolders(name)) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||
lock.unlock();
|
||||
return loadFile(j, key, name);
|
||||
return loadFile(j, name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,7 +135,7 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
|
||||
if (file.exists()) {
|
||||
lock.unlock();
|
||||
return loadFile(file, key, name);
|
||||
return loadFile(file, name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,4 +144,8 @@ public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||
lock.unlock();
|
||||
return null;
|
||||
}
|
||||
|
||||
public IrisScript load(String name, boolean warn) {
|
||||
return loadCache.get(name);
|
||||
}
|
||||
}
|
||||
|
@ -19,19 +19,27 @@
|
||||
package com.volmit.iris.core.service;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
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.context.IrisContext;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.IrisService;
|
||||
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;
|
||||
|
||||
public class PreservationSVC implements IrisService {
|
||||
private final KList<Thread> threads = new KList<>();
|
||||
private final KList<ExecutorService> services = new KList<>();
|
||||
private Looper dereferencer;
|
||||
private final KList<MeteredCache> caches = new KList<>();
|
||||
|
||||
public void register(Thread t) {
|
||||
threads.add(t);
|
||||
@ -45,11 +53,35 @@ public class PreservationSVC implements IrisService {
|
||||
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() {
|
||||
IrisContext.dereference();
|
||||
IrisData.dereference();
|
||||
threads.removeWhere((i) -> !i.isAlive());
|
||||
services.removeWhere(ExecutorService::isShutdown);
|
||||
updateCaches();
|
||||
}
|
||||
|
||||
@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) {
|
||||
int cacheSize = IrisSettings.get().getPerformance().getCacheSize();
|
||||
int cacheSize = IrisSettings.get().getPerformance().getMaxStreamCacheSize();
|
||||
IrisBiome emptyBiome = new IrisBiome();
|
||||
UUID focusUUID = UUID.nameUUIDFromBytes("focus".getBytes());
|
||||
this.rng = new RNG(engine.getSeedManager().getComplex());
|
||||
@ -124,7 +124,7 @@ public class IrisComplex implements DataProvider {
|
||||
Interpolated.of(a -> 0D, a -> focusRegion))
|
||||
: regionStyleStream
|
||||
.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));
|
||||
caveBiomeStream = regionStream.convert((r)
|
||||
-> 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)
|
||||
.setInferredType(InferredType.CAVE);
|
||||
})
|
||||
).convertAware2D(ProceduralStream::get).cache2D(cacheSize);
|
||||
).convertAware2D(ProceduralStream::get).cache2D(engine, cacheSize);
|
||||
inferredStreams.put(InferredType.CAVE, caveBiomeStream);
|
||||
landBiomeStream = regionStream.convert((r)
|
||||
-> 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)
|
||||
.setInferredType(InferredType.LAND))
|
||||
).convertAware2D(ProceduralStream::get)
|
||||
.cache2D(cacheSize);
|
||||
.cache2D(engine, cacheSize);
|
||||
inferredStreams.put(InferredType.LAND, landBiomeStream);
|
||||
seaBiomeStream = regionStream.convert((r)
|
||||
-> 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)
|
||||
.setInferredType(InferredType.SEA))
|
||||
).convertAware2D(ProceduralStream::get)
|
||||
.cache2D(cacheSize);
|
||||
.cache2D(engine, cacheSize);
|
||||
inferredStreams.put(InferredType.SEA, seaBiomeStream);
|
||||
shoreBiomeStream = regionStream.convert((r)
|
||||
-> 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))
|
||||
.convertCached((s) -> data.getBiomeLoader().load(s)
|
||||
.setInferredType(InferredType.SHORE))
|
||||
).convertAware2D(ProceduralStream::get).cache2D(cacheSize);
|
||||
).convertAware2D(ProceduralStream::get).cache2D(engine, cacheSize);
|
||||
inferredStreams.put(InferredType.SHORE, shoreBiomeStream);
|
||||
bridgeStream = focus != null ? ProceduralStream.of((x, z) -> focus.getInferredType(),
|
||||
Interpolated.of(a -> 0D, a -> focus.getInferredType())) :
|
||||
engine.getDimension().getContinentalStyle().create(rng.nextParallelRNG(234234565), getData())
|
||||
.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,
|
||||
Interpolated.of(a -> 0D, a -> focus)) :
|
||||
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) -> {
|
||||
IrisBiome b = focus != null ? focus : baseBiomeStream.get(x, z);
|
||||
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();
|
||||
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,
|
||||
b -> focus))
|
||||
.cache2D(cacheSize) : heightStream
|
||||
.cache2D(engine, cacheSize) : heightStream
|
||||
.convertAware2D((h, x, z) ->
|
||||
fixBiomeType(h, baseBiomeStream.get(x, z),
|
||||
regionStream.get(x, z), x, z, fluidHeight))
|
||||
.cache2D(cacheSize);
|
||||
.cache2D(engine, cacheSize);
|
||||
trueBiomeStream = focus != null ? ProceduralStream.of((x, y) -> focus, Interpolated.of(a -> 0D,
|
||||
b -> focus))
|
||||
.cache2D(cacheSize) : heightStream
|
||||
.cache2D(engine, cacheSize) : heightStream
|
||||
.convertAware2D((h, x, z) ->
|
||||
fixBiomeType(h, baseBiomeStream.get(x, z),
|
||||
regionStream.get(x, z), x, z, fluidHeight))
|
||||
.cache2D(cacheSize);
|
||||
trueBiomeDerivativeStream = trueBiomeStream.convert(IrisBiome::getDerivative).cache2D(cacheSize);
|
||||
heightFluidStream = heightStream.max(fluidHeight).cache2D(cacheSize);
|
||||
.cache2D(engine, cacheSize);
|
||||
trueBiomeDerivativeStream = trueBiomeStream.convert(IrisBiome::getDerivative).cache2D(engine, cacheSize);
|
||||
heightFluidStream = heightStream.max(fluidHeight).cache2D(engine, cacheSize, true);
|
||||
maxHeightStream = ProceduralStream.ofDouble((x, z) -> height);
|
||||
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
|
||||
.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
|
||||
.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
|
||||
.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
|
||||
.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
|
||||
.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
|
||||
.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) -> {
|
||||
UUID d = regionIDStream.get(x, z);
|
||||
return new UUID(b.getLoadKey().hashCode() * 818223L,
|
||||
d.hashCode());
|
||||
})
|
||||
.cache2D(cacheSize);
|
||||
.cache2D(engine, cacheSize);
|
||||
//@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.slices.MarkerMatter;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import com.volmit.iris.util.stream.utility.CachedStream2D;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Material;
|
||||
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.core.loader.IrisData;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IRare;
|
||||
import com.volmit.iris.engine.object.IrisStyledRange;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@ -287,8 +288,12 @@ public interface ProceduralStream<T> extends ProceduralLayer, Interpolated<T> {
|
||||
return new To3DStream<T>(this);
|
||||
}
|
||||
|
||||
default ProceduralStream<T> cache2D(int maxSize) {
|
||||
return new CachedStream2D<T>(this, maxSize);
|
||||
default ProceduralStream<T> cache2D(Engine engine, int 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) {
|
||||
|
@ -18,23 +18,30 @@
|
||||
|
||||
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.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.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.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 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();
|
||||
this.stream = stream;
|
||||
cache = new ConcurrentLinkedHashMap.Builder<Long, T>()
|
||||
.initialCapacity(size)
|
||||
.maximumWeightedCapacity(size)
|
||||
.concurrencyLevel(32)
|
||||
.build();
|
||||
this.engine = engine;
|
||||
cache = new KCache<>(k -> stream.get(Cache.keyX(k), Cache.keyZ(k)), size);
|
||||
Iris.service(PreservationSVC.class).registerCache(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,11 +56,26 @@ public class CachedStream2D<T> extends BasicStream<T> implements ProceduralStrea
|
||||
|
||||
@Override
|
||||
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
|
||||
public T get(double x, double y, double 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