feat: 轻量化 ScaledProcessingPattern,改为最小字段与延迟计算,
减少构造时的大量临时对象分配,降低 GC 压力并提升高并发/多 provider 场景下的性能
This commit is contained in:
parent
ef8fa756ed
commit
d4095e64ea
|
|
@ -17,27 +17,21 @@ import java.util.Objects;
|
||||||
*/
|
*/
|
||||||
public final class ScaledProcessingPattern implements IPatternDetails {
|
public final class ScaledProcessingPattern implements IPatternDetails {
|
||||||
|
|
||||||
|
// 最小化实例字段:只保留原始样板引用、定义和倍数
|
||||||
private final AEProcessingPattern original; // 原始样板引用
|
private final AEProcessingPattern original; // 原始样板引用
|
||||||
private final AEItemKey definition; // 样板物品
|
private final AEItemKey definition; // 样板物品(直接委托自 original)
|
||||||
private final GenericStack[] sparseInputs; // 缩放后的稀疏输入
|
private final long multiplier; // 乘数(外部可视为视图参数)
|
||||||
private final GenericStack[] sparseOutputs; // 缩放后的稀疏输出
|
|
||||||
private final IInput[] inputs; // 缩放后的压缩输入
|
|
||||||
private final GenericStack[] condensedOutputs; // 缩放后的压缩输出
|
|
||||||
|
|
||||||
public ScaledProcessingPattern(
|
// 延迟计算缓存(轻量化实例时避免在构造器中分配大数组)
|
||||||
AEProcessingPattern original,
|
private transient volatile IInput[] inputsCache;
|
||||||
AEItemKey definition,
|
private transient volatile GenericStack[] outputsCache;
|
||||||
GenericStack[] sparseInputs,
|
private transient volatile GenericStack[] sparseInputsCache;
|
||||||
GenericStack[] sparseOutputs,
|
private transient volatile GenericStack[] sparseOutputsCache;
|
||||||
IInput[] inputs,
|
|
||||||
GenericStack[] condensedOutputs
|
public ScaledProcessingPattern(AEProcessingPattern original, AEItemKey definition, long multiplier) {
|
||||||
) {
|
|
||||||
this.original = Objects.requireNonNull(original);
|
this.original = Objects.requireNonNull(original);
|
||||||
this.definition = Objects.requireNonNull(definition);
|
this.definition = Objects.requireNonNull(definition);
|
||||||
this.sparseInputs = Objects.requireNonNull(sparseInputs);
|
this.multiplier = multiplier <= 0 ? 1L : multiplier;
|
||||||
this.sparseOutputs = Objects.requireNonNull(sparseOutputs);
|
|
||||||
this.inputs = Objects.requireNonNull(inputs);
|
|
||||||
this.condensedOutputs = Objects.requireNonNull(condensedOutputs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------- API 实现 -------------------- */
|
/* -------------------- API 实现 -------------------- */
|
||||||
|
|
@ -53,25 +47,91 @@ public final class ScaledProcessingPattern implements IPatternDetails {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IInput[] getInputs() {
|
public IInput[] getInputs() {
|
||||||
return inputs;
|
IInput[] cached = this.inputsCache;
|
||||||
|
if (cached == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
cached = this.inputsCache;
|
||||||
|
if (cached == null) {
|
||||||
|
var base = original.getInputs();
|
||||||
|
IInput[] arr = new IInput[base.length];
|
||||||
|
for (int i = 0; i < base.length; i++) {
|
||||||
|
var in = base[i];
|
||||||
|
// 不复制 template 数组,直接复用原始的 possible inputs;仅放大 multiplier
|
||||||
|
arr[i] = new Input(in.getPossibleInputs(), in.getMultiplier() * this.multiplier);
|
||||||
|
}
|
||||||
|
this.inputsCache = arr;
|
||||||
|
cached = arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GenericStack[] getOutputs() {
|
public GenericStack[] getOutputs() {
|
||||||
return condensedOutputs;
|
GenericStack[] cached = this.outputsCache;
|
||||||
|
if (cached == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
cached = this.outputsCache;
|
||||||
|
if (cached == null) {
|
||||||
|
var baseOutputs = original.getOutputs();
|
||||||
|
GenericStack[] arr = new GenericStack[baseOutputs.length];
|
||||||
|
for (int i = 0; i < baseOutputs.length; i++) {
|
||||||
|
var o = baseOutputs[i];
|
||||||
|
if (o != null) arr[i] = new GenericStack(o.what(), o.amount() * this.multiplier);
|
||||||
|
}
|
||||||
|
this.outputsCache = arr;
|
||||||
|
cached = arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GenericStack[] getSparseInputs() {
|
public GenericStack[] getSparseInputs() {
|
||||||
return sparseInputs;
|
GenericStack[] cached = this.sparseInputsCache;
|
||||||
|
if (cached == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
cached = this.sparseInputsCache;
|
||||||
|
if (cached == null) {
|
||||||
|
var base = original.getSparseInputs();
|
||||||
|
GenericStack[] arr = new GenericStack[base.length];
|
||||||
|
for (int i = 0; i < base.length; i++) {
|
||||||
|
var v = base[i];
|
||||||
|
if (v != null) arr[i] = new GenericStack(v.what(), v.amount() * this.multiplier);
|
||||||
|
}
|
||||||
|
this.sparseInputsCache = arr;
|
||||||
|
cached = arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GenericStack[] getSparseOutputs() {
|
public GenericStack[] getSparseOutputs() {
|
||||||
return sparseOutputs;
|
GenericStack[] cached = this.sparseOutputsCache;
|
||||||
|
if (cached == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
cached = this.sparseOutputsCache;
|
||||||
|
if (cached == null) {
|
||||||
|
var base = original.getSparseOutputs();
|
||||||
|
GenericStack[] arr = new GenericStack[base.length];
|
||||||
|
for (int i = 0; i < base.length; i++) {
|
||||||
|
var v = base[i];
|
||||||
|
if (v != null) arr[i] = new GenericStack(v.what(), v.amount() * this.multiplier);
|
||||||
|
}
|
||||||
|
this.sparseOutputsCache = arr;
|
||||||
|
cached = arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GenericStack getPrimaryOutput() {
|
public GenericStack getPrimaryOutput() {
|
||||||
if (condensedOutputs.length > 0) return condensedOutputs[0];
|
var outs = getOutputs();
|
||||||
|
if (outs.length > 0 && outs[0] != null) return outs[0];
|
||||||
return original.getPrimaryOutput();
|
return original.getPrimaryOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,15 +142,19 @@ public final class ScaledProcessingPattern implements IPatternDetails {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushInputsToExternalInventory(KeyCounter[] inputHolder, PatternInputSink inputSink) {
|
public void pushInputsToExternalInventory(KeyCounter[] inputHolder, PatternInputSink inputSink) {
|
||||||
// 保持和 AEProcessingPattern 一致,用 sparseInputs 驱动
|
// 使用 lazy 计算的 sparseInputs 与 inputs 来驱动;当两者长度一致时直接委托
|
||||||
if (sparseInputs.length == inputs.length) {
|
GenericStack[] sInputs = getSparseInputs();
|
||||||
|
IInput[] ins = getInputs();
|
||||||
|
if (sInputs.length == ins.length) {
|
||||||
IPatternDetails.super.pushInputsToExternalInventory(inputHolder, inputSink);
|
IPatternDetails.super.pushInputsToExternalInventory(inputHolder, inputSink);
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
KeyCounter allInputs = new KeyCounter();
|
KeyCounter allInputs = new KeyCounter();
|
||||||
for (KeyCounter counter : inputHolder) {
|
for (KeyCounter counter : inputHolder) {
|
||||||
allInputs.addAll(counter);
|
allInputs.addAll(counter);
|
||||||
}
|
}
|
||||||
for (GenericStack sparseInput : sparseInputs) {
|
for (GenericStack sparseInput : sInputs) {
|
||||||
if (sparseInput != null) {
|
if (sparseInput != null) {
|
||||||
AEKey key = sparseInput.what();
|
AEKey key = sparseInput.what();
|
||||||
long amount = sparseInput.amount();
|
long amount = sparseInput.amount();
|
||||||
|
|
@ -104,7 +168,6 @@ public final class ScaledProcessingPattern implements IPatternDetails {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------- 缩放输入代理 -------------------- */
|
/* -------------------- 缩放输入代理 -------------------- */
|
||||||
|
|
||||||
|
|
@ -117,18 +180,22 @@ public final class ScaledProcessingPattern implements IPatternDetails {
|
||||||
this.multiplier = multiplier;
|
this.multiplier = multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public GenericStack[] getPossibleInputs() {
|
public GenericStack[] getPossibleInputs() {
|
||||||
return this.template;
|
return this.template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public long getMultiplier() {
|
public long getMultiplier() {
|
||||||
return this.multiplier;
|
return this.multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isValid(AEKey input, Level level) {
|
public boolean isValid(AEKey input, Level level) {
|
||||||
return input.matches(this.template[0]);
|
return input.matches(this.template[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public @Nullable AEKey getRemainingKey(AEKey template) {
|
public @Nullable AEKey getRemainingKey(AEKey template) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,48 +71,7 @@ public final class PatternScaler {
|
||||||
// 配置读取异常时不施加上限
|
// 配置读取异常时不施加上限
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建压缩输入(将每个输入的 multiplier 翻倍,保留每个模板的原始数量)
|
// 仅使用 multiplier 构建轻量化 ScaledProcessingPattern(具体视图按需计算)
|
||||||
IInput[] scaledInputs = new IInput[baseInputs.length];
|
return new ScaledProcessingPattern(base, base.getDefinition(), multiplier);
|
||||||
for (int i = 0; i < baseInputs.length; i++) {
|
|
||||||
var in = baseInputs[i];
|
|
||||||
var template = in.getPossibleInputs();
|
|
||||||
GenericStack[] scaledTemplates = new GenericStack[template.length];
|
|
||||||
for (int j = 0; j < template.length; j++) {
|
|
||||||
scaledTemplates[j] = new GenericStack(template[j].what(), template[j].amount());
|
|
||||||
}
|
|
||||||
scaledInputs[i] = new ScaledProcessingPattern.Input(scaledTemplates, in.getMultiplier() * multiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 4. 构建压缩输出 */
|
|
||||||
GenericStack[] scaledCondensedOutputs = new GenericStack[baseOutputs.length];
|
|
||||||
for (int i = 0; i < baseOutputs.length; i++) {
|
|
||||||
GenericStack out = baseOutputs[i];
|
|
||||||
if (out != null) {
|
|
||||||
scaledCondensedOutputs[i] = new GenericStack(out.what(), out.amount() * multiplier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建并打印稀疏表示(直接按 multiplier 放大)
|
|
||||||
GenericStack[] scaledSparseInputs = new GenericStack[baseSparseInputs.length];
|
|
||||||
for (int i = 0; i < baseSparseInputs.length; i++) {
|
|
||||||
var in = baseSparseInputs[i];
|
|
||||||
if (in != null) {
|
|
||||||
scaledSparseInputs[i] = new GenericStack(in.what(), in.amount() * multiplier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GenericStack[] scaledSparseOutputs = new GenericStack[baseSparseOutputs.length];
|
|
||||||
for (int i = 0; i < baseSparseOutputs.length; i++) {
|
|
||||||
var out = baseSparseOutputs[i];
|
|
||||||
if (out != null) {
|
|
||||||
scaledSparseOutputs[i] = new GenericStack(out.what(), out.amount() * multiplier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ScaledProcessingPattern(base,
|
|
||||||
base.getDefinition(),
|
|
||||||
scaledSparseInputs,
|
|
||||||
scaledSparseOutputs,
|
|
||||||
scaledInputs,
|
|
||||||
scaledCondensedOutputs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@
|
||||||
"ae2.autopattern.CraftingTreeNodeMixin",
|
"ae2.autopattern.CraftingTreeNodeMixin",
|
||||||
"ae2.autopattern.CraftingTreeProcessMixin",
|
"ae2.autopattern.CraftingTreeProcessMixin",
|
||||||
"ae2.autopattern.PatternProviderLogicContainsRedirectMixin",
|
"ae2.autopattern.PatternProviderLogicContainsRedirectMixin",
|
||||||
"ae2.autopattern.adaptation.AdvPatternProviderLogicContainsRedirectMixin",
|
|
||||||
"ae2.helpers.PatternProviderLogicAdvancedMixin",
|
"ae2.helpers.PatternProviderLogicAdvancedMixin",
|
||||||
"ae2.helpers.PatternProviderLogicDoublingMixin",
|
"ae2.helpers.PatternProviderLogicDoublingMixin",
|
||||||
"ae2.menu.ContainerPatternEncodingTermMenuMixin",
|
"ae2.menu.ContainerPatternEncodingTermMenuMixin",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user