Add update propagator thread pool
This commit is contained in:
@@ -907,7 +907,7 @@ public class Config
|
||||
ThreadPresetConfigEventHandler.getFileHandlerDefaultThreadCount(),
|
||||
Runtime.getRuntime().availableProcessors())
|
||||
.comment(""
|
||||
+ "How many threads should be used when reading in LOD data from disk? \n"
|
||||
+ "How many threads should be used when reading/writing LOD data to/from disk? \n"
|
||||
+ "\n"
|
||||
+ "Increasing this number will cause LODs to load in faster, \n"
|
||||
+ "but may cause lag when loading a new world or when \n"
|
||||
@@ -920,6 +920,31 @@ public class Config
|
||||
.comment(THREAD_RUN_TIME_RATIO_NOTE)
|
||||
.build();
|
||||
|
||||
public static final ConfigEntry<Integer> numberOfUpdatePropagatorThreads = new ConfigEntry.Builder<Integer>()
|
||||
.setMinDefaultMax(1,
|
||||
ThreadPresetConfigEventHandler.getUpdatePropagatorDefaultThreadCount(),
|
||||
Runtime.getRuntime().availableProcessors())
|
||||
.comment(""
|
||||
+ "How many threads should be used when applying LOD updates? \n"
|
||||
+ "An LOD update is the operation of down-sampling a high detail LOD \n"
|
||||
+ "into a lower detail one.\n"
|
||||
+ "\n"
|
||||
+ "This config can have a much higher number of threads \n"
|
||||
+ "assigned and much lower run time ratio vs other thread pools \n"
|
||||
+ "because the amount of time any particular thread may run is relatively low.\n"
|
||||
+ "\n"
|
||||
+ "This is because LOD updating only only partially thread safe, \n"
|
||||
+ "so between 40% and 60% of the time a given thread may end up \n"
|
||||
+ "waiting on another thread to finish updating the same LOD it also wants\n"
|
||||
+ "to work on.\n"
|
||||
+ "\n"
|
||||
+ THREAD_NOTE)
|
||||
.build();
|
||||
public static final ConfigEntry<Double> runTimeRatioForUpdatePropagatorThreads = new ConfigEntry.Builder<Double>()
|
||||
.setMinDefaultMax(0.01, ThreadPresetConfigEventHandler.getUpdatePropagatorDefaultRunTimeRatio(), 1.0)
|
||||
.comment(THREAD_RUN_TIME_RATIO_NOTE)
|
||||
.build();
|
||||
|
||||
public static final ConfigEntry<Integer> numberOfLodBuilderThreads = new ConfigEntry.Builder<Integer>()
|
||||
.setMinDefaultMax(1,
|
||||
ThreadPresetConfigEventHandler.getLodBuilderDefaultThreadCount(),
|
||||
|
||||
+25
@@ -85,6 +85,28 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
|
||||
}});
|
||||
|
||||
|
||||
public static int getUpdatePropagatorDefaultThreadCount() { return getThreadCountByPercent(0.5); }
|
||||
private final ConfigEntryWithPresetOptions<EThreadPreset, Integer> UpdatePropagatorThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfUpdatePropagatorThreads,
|
||||
new HashMap<EThreadPreset, Integer>()
|
||||
{{
|
||||
this.put(EThreadPreset.MINIMAL_IMPACT, 1);
|
||||
this.put(EThreadPreset.LOW_IMPACT, getUpdatePropagatorDefaultThreadCount());
|
||||
this.put(EThreadPreset.BALANCED, getThreadCountByPercent(0.75));
|
||||
this.put(EThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.75));
|
||||
this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0));
|
||||
}});
|
||||
public static double getUpdatePropagatorDefaultRunTimeRatio() { return 0.25; }
|
||||
private final ConfigEntryWithPresetOptions<EThreadPreset, Double> UpdatePropagatorRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForUpdatePropagatorThreads,
|
||||
new HashMap<EThreadPreset, Double>()
|
||||
{{
|
||||
this.put(EThreadPreset.MINIMAL_IMPACT, 0.25);
|
||||
this.put(EThreadPreset.LOW_IMPACT, getUpdatePropagatorDefaultRunTimeRatio());
|
||||
this.put(EThreadPreset.BALANCED, 0.5);
|
||||
this.put(EThreadPreset.AGGRESSIVE, 1.0);
|
||||
this.put(EThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0);
|
||||
}});
|
||||
|
||||
|
||||
public static int getLodBuilderDefaultThreadCount() { return getThreadCountByPercent(0.1); }
|
||||
private final ConfigEntryWithPresetOptions<EThreadPreset, Integer> lodBuilderThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads,
|
||||
new HashMap<EThreadPreset, Integer>()
|
||||
@@ -122,6 +144,9 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
|
||||
this.configList.add(this.fileHandlerThreadCount);
|
||||
this.configList.add(this.fileHandlerRunTime);
|
||||
|
||||
this.configList.add(this.UpdatePropagatorThreadCount);
|
||||
this.configList.add(this.UpdatePropagatorRunTime);
|
||||
|
||||
this.configList.add(this.lodBuilderThreadCount);
|
||||
this.configList.add(this.lodBuilderRunTime);
|
||||
|
||||
|
||||
+20
-11
@@ -168,7 +168,7 @@ public abstract class AbstractNewDataSourceHandler
|
||||
@Override
|
||||
public CompletableFuture<Void> updateDataSourceAsync(NewFullDataSource inputDataSource)
|
||||
{
|
||||
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||
ThreadPoolExecutor executor = ThreadPoolUtil.getUpdatePropagatorExecutor();
|
||||
if (executor == null || executor.isTerminated())
|
||||
{
|
||||
return CompletableFuture.completedFuture(null);
|
||||
@@ -214,18 +214,27 @@ public abstract class AbstractNewDataSourceHandler
|
||||
|
||||
if (dataModified)
|
||||
{
|
||||
// save the updated data to the database
|
||||
TDTO dto = this.createDtoFromDataSource(dataSource);
|
||||
this.repo.save(dto);
|
||||
|
||||
|
||||
for (IDataSourceUpdateFunc<TDataSource> listener : this.dateSourceUpdateListeners)
|
||||
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||
if (executor == null || executor.isTerminated())
|
||||
{
|
||||
if (listener != null)
|
||||
{
|
||||
listener.OnDataSourceUpdated(dataSource);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
executor.execute(() ->
|
||||
{
|
||||
// save the updated data to the database
|
||||
TDTO dto = this.createDtoFromDataSource(dataSource);
|
||||
this.repo.save(dto);
|
||||
|
||||
|
||||
for (IDataSourceUpdateFunc<TDataSource> listener : this.dateSourceUpdateListeners)
|
||||
{
|
||||
if (listener != null)
|
||||
{
|
||||
listener.OnDataSourceUpdated(dataSource);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
+5
-4
@@ -58,7 +58,7 @@ public class NewFullDataFileHandler
|
||||
private static final int MAX_PARENT_UPDATE_TASK_COUNT = NUMBER_OF_PARENT_UPDATE_TASKS_PER_THREAD * Config.Client.Advanced.MultiThreading.numberOfFileHandlerThreads.get();
|
||||
|
||||
/** indicates how long the update queue thread should wait between queuing ticks */
|
||||
private static final int UPDATE_QUEUE_THREAD_DELAY_IN_MS = 500;
|
||||
private static final int UPDATE_QUEUE_THREAD_DELAY_IN_MS = 1_000;
|
||||
|
||||
/** the list of queued positions that need to update their parents */
|
||||
Set<DhSectionPos> parentApplicationPositionSet = ConcurrentHashMap.newKeySet();
|
||||
@@ -210,7 +210,7 @@ public class NewFullDataFileHandler
|
||||
if (updatePosList.size() != 0)
|
||||
{
|
||||
// stop if the file handler has been shut down
|
||||
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||
ThreadPoolExecutor executor = ThreadPoolUtil.getUpdatePropagatorExecutor();
|
||||
if (executor == null || executor.isTerminated())
|
||||
{
|
||||
this.updateQueueThreadRunningRef.set(false);
|
||||
@@ -222,6 +222,9 @@ public class NewFullDataFileHandler
|
||||
int queueCount = 0;
|
||||
for (DhSectionPos pos : updatePosList)
|
||||
{
|
||||
// James thought batching together updates
|
||||
// based on the parent they were going to update would reduce update locks,
|
||||
// but after testing it didn't, so we're just queing each section individually
|
||||
if (this.parentApplicationPositionSet.add(pos))
|
||||
{
|
||||
queueCount++;
|
||||
@@ -230,8 +233,6 @@ public class NewFullDataFileHandler
|
||||
NewFullDataSource inputData = this.get(pos);
|
||||
// update the parent position with this new data
|
||||
this.updateDataSourceAtPos(pos.getParentPos(), inputData, true);
|
||||
|
||||
// TODO add comparable interface to make this low priority
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -126,13 +126,18 @@ public class RenderSourceFileHandler extends AbstractLegacyDataSourceHandler<Col
|
||||
/** Returns what should be displayed in Minecraft's F3 debug menu */
|
||||
private String[] f3Log()
|
||||
{
|
||||
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||
String queueSize = (executor != null) ? executor.getQueue().size()+"" : "-";
|
||||
String completedTaskSize = (executor != null) ? executor.getCompletedTaskCount()+"" : "-";
|
||||
ThreadPoolExecutor fileExecutor = ThreadPoolUtil.getFileHandlerExecutor();
|
||||
String fileQueueSize = (fileExecutor != null) ? fileExecutor.getQueue().size()+"" : "-";
|
||||
String fileCompletedTaskSize = (fileExecutor != null) ? fileExecutor.getCompletedTaskCount()+"" : "-";
|
||||
|
||||
ThreadPoolExecutor updateExecutor = ThreadPoolUtil.getUpdatePropagatorExecutor();
|
||||
String updateQueueSize = (updateExecutor != null) ? updateExecutor.getQueue().size()+"" : "-";
|
||||
String updateCompletedTaskSize = (updateExecutor != null) ? updateExecutor.getCompletedTaskCount()+"" : "-";
|
||||
|
||||
ArrayList<String> lines = new ArrayList<>();
|
||||
lines.add("File Handler [" + this.level.getLevelWrapper().getDimensionType().getDimensionName() + "]");
|
||||
lines.add(" Thread pool tasks: " + queueSize + " (completed: " + completedTaskSize + ")");
|
||||
lines.add(" File thread pool tasks: " + fileQueueSize + " (completed: " + fileCompletedTaskSize + ")");
|
||||
lines.add(" Update thread pool tasks: " + updateQueueSize + " (completed: " + updateCompletedTaskSize + ")");
|
||||
lines.add(" Unsaved render sources: " + this.unsavedDataSourceBySectionPos.size());
|
||||
|
||||
return lines.toArray(new String[0]);
|
||||
|
||||
+9
-1
@@ -46,11 +46,17 @@ public class ThreadPoolUtil
|
||||
@Nullable
|
||||
public static ThreadPoolExecutor getFileHandlerExecutor() { return fileHandlerThreadPool.executor; }
|
||||
|
||||
public static final DhThreadFactory UPDATE_PROPAGATOR_THREAD_FACTORY = new DhThreadFactory("LOD Update Propagator", Thread.MIN_PRIORITY);
|
||||
private static RateLimitedThreadPoolExecutor updatePropagatorThreadPool;
|
||||
@Nullable
|
||||
public static ThreadPoolExecutor getUpdatePropagatorExecutor() { return updatePropagatorThreadPool; }
|
||||
|
||||
public static final DhThreadFactory WORLD_GEN_THREAD_FACTORY = new DhThreadFactory("World Gen", Thread.MIN_PRIORITY);
|
||||
private static ConfigThreadPool worldGenThreadPool;
|
||||
@Nullable
|
||||
public static ThreadPoolExecutor getWorldGenExecutor() { return worldGenThreadPool.executor; }
|
||||
|
||||
public static final String BUFFER_UPLOADER_THREAD_NAME = "Buffer Uploader";
|
||||
private static ThreadPoolExecutor bufferUploaderThreadPool;
|
||||
@Nullable
|
||||
public static ThreadPoolExecutor getBufferUploaderExecutor() { return bufferUploaderThreadPool; }
|
||||
@@ -99,8 +105,9 @@ public class ThreadPoolUtil
|
||||
// standalone threads //
|
||||
|
||||
fileHandlerThreadPool = new ConfigThreadPool(FILE_HANDLER_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfFileHandlerThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForFileHandlerThreads, null);
|
||||
updatePropagatorThreadPool = new RateLimitedThreadPoolExecutor(8, 1.0, UPDATE_PROPAGATOR_THREAD_FACTORY);
|
||||
worldGenThreadPool = new ConfigThreadPool(WORLD_GEN_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads, null);
|
||||
bufferUploaderThreadPool = ThreadUtil.makeSingleThreadPool("Buffer Uploader");
|
||||
bufferUploaderThreadPool = ThreadUtil.makeSingleThreadPool(BUFFER_UPLOADER_THREAD_NAME);
|
||||
|
||||
|
||||
|
||||
@@ -138,6 +145,7 @@ public class ThreadPoolUtil
|
||||
{
|
||||
// standalone threads
|
||||
fileHandlerThreadPool.shutdownExecutorService();
|
||||
updatePropagatorThreadPool.shutdown();
|
||||
worldGenThreadPool.shutdownExecutorService();
|
||||
bufferUploaderThreadPool.shutdown();
|
||||
|
||||
|
||||
@@ -395,6 +395,13 @@
|
||||
"distanthorizons.config.client.advanced.multiThreading.runTimeRatioForFileHandlerThreads":
|
||||
"Runtime % for file handler threads",
|
||||
|
||||
"distanthorizons.config.client.advanced.multiThreading.numberOfUpdatePropagatorThreads":
|
||||
"NO. of update propagator threads",
|
||||
"distanthorizons.config.client.advanced.multiThreading.numberOfUpdatePropagatorThreads.@tooltip":
|
||||
"How many threads should be used when applying LOD updates? \nAn LOD update is the operation of down-sampling a high detail LOD \ninto a lower detail one. \n\nThis config can have a much higher number of threads \nassigned and much lower run time ratio vs other thread pools \nbecause the amount of time any particular thread may run is relatively low.",
|
||||
"distanthorizons.config.client.advanced.multiThreading.runTimeRatioForUpdatePropagatorThreads":
|
||||
"Runtime % for update propagator threads",
|
||||
|
||||
"distanthorizons.config.client.advanced.multiThreading.numberOfLodBuilderThreads":
|
||||
"NO. of LOD builder threads",
|
||||
"distanthorizons.config.client.advanced.multiThreading.numberOfLodBuilderThreads.@tooltip":
|
||||
|
||||
Reference in New Issue
Block a user