Commit c1efacb9 authored by Tong Li's avatar Tong Li

Merge remote-tracking branch 'origin/master' into tl

parents ced8be43 491dbbe8
......@@ -8,6 +8,7 @@ import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.DiscreteParameterDuration;
import com.aps.entity.ProdEquipment;
import com.aps.entity.Routingsupporting;
import com.aps.entity.Stock;
import com.aps.entity.basic.*;
import com.aps.service.DiscreteParameterDurationService;
import com.aps.service.DiscreteParameterMatrixService;
......@@ -43,6 +44,13 @@ public class GeneticDecoder {
// 线程安全锁:避免多线程下缓存操作冲突(可选,若单线程可移除)
// private final ReentrantLock cacheLock = new ReentrantLock();
private LocalDateTime baseTime;
// 性能日志辅助方法
private static String fmtMs(long nano) {
if (nano < 1000000L) return (nano / 1000L) + "μs";
if (nano < 1000000000L) return (nano / 1000000L) + "ms";
return String.format("%.2fs", nano / 1_000_000_000.0);
}
private final List<Machine> machines;
private final MachineSchedulerService machineScheduler;
private final List<Order> orders;
......@@ -401,19 +409,25 @@ public class GeneticDecoder {
}
public void serialDecode(Chromosome chromosome) {
long decodeStart = System.nanoTime();
chromosome.setScenarioID(sceneId);
if (rebuildStructureForCurrentDecode) {
long t1 = System.nanoTime();
//创建半成品订单
materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
// FileHelper.writeLogFile("[PERF] serialDecode buildMultiLevelRequirementNetwork 耗时=" + fmtMs(System.nanoTime() - t1));
}
if(rebuildStructureForCurrentDecode && _globalParam.isIsCheckSf()) {
long t1 = System.nanoTime();
int isnew= generateGlobalOpList(chromosome);
// FileHelper.writeLogFile("[PERF] serialDecode generateGlobalOpList 耗时=" + fmtMs(System.nanoTime() - t1) + ", isnew=" + isnew);
if(isnew==1) {
long t2 = System.nanoTime();
CreateNewOpSequence(chromosome);
// FileHelper.writeLogFile("[PERF] serialDecode CreateNewOpSequence 耗时=" + fmtMs(System.nanoTime() - t2));
}
}
......@@ -506,6 +520,8 @@ public class GeneticDecoder {
// List<Entry> allScheduledOps = new ArrayList<>();
// 缓存机器任务
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>();
int opCount = 0;
long slowOpThresholdNs = 500_000_000L; // 500ms
for (int groupId : chromosome.getOperationSequencing()) {
int scheduledCount = orderProcessCounter.get(groupId);
......@@ -532,59 +548,35 @@ public class GeneticDecoder {
}
}
// 从映射表中获取机器和加工时间
// OpMachine machineOption=opMachineMap.stream()
// .filter(m -> m.getGroupId() == groupId&&m.getSequence()==opSequence)
// .findFirst()
// .orElse(null);
String opMachineKey = groupId + "_" + opSequence;
OpMachine machineOption = opMachineKeyMap.get(opMachineKey);
Long machineId = machineOption.getMachineId();
double processTime = machineOption.getProcessingTime();
// Machine targetMachine = chromosome.getMachines().stream()
// .filter(m -> m.getId() == machineId)
// .findFirst()
// .orElse(null);
// Machine targetMachine = machineIdMap.get(machineId);
// int prevtime = 0;
// //后处理时间
// int teardownTime = currentOp.getTeardownTime();
// if (!currentOp.getPrevEntryIds().isEmpty()) {
// // 处理多个前工序
// prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine);
// }
// 上个离散参数
// String lastDiscreteParameter = machineState.get(machineId);
// int bomtime = getOperationBOMTime(currentOp,chromosome);
// int prevendtime=prevtime;
// prevtime = Math.max(prevtime, bomtime);
// Machine machine = chromosome.getMachines().stream()
// .filter(m -> m.getId() == machineId)
// .findFirst()
// .orElse(null);
// Machine machine = machineIdMap.get(machineId);
// int changeoverTime =0; //(lastDiscreteParameter.isEmpty() ||
// lastDiscreteParameter.equals(currentOp.getDiscreteParameter())) ? 0 : 0;
long opStart = System.nanoTime();
int actualEndTime = processOperation(currentOp,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache,entryIndexById,scheduleIndexById);
// int actualEndTime = processWithSingleMachine(currentOp, machine, processTime, prevtime,machineOption, chromosome,false,prevendtime,machineTasksCache);
long opElapsed = System.nanoTime() - opStart;
opCount++;
// if (opElapsed > slowOpThresholdNs) {
// FileHelper.writeLogFile("[PERF] serialDecode 慢工序 opId=" + currentOp.getId()
// + ", groupId=" + groupId + ", seq=" + opSequence
// + ", machineId=" + machineId + ", hasBOM="
// + (currentOp.getMaterialRequirements() != null && currentOp.getMaterialRequirements().size() > 0)
// + ", 耗时=" + fmtMs(opElapsed));
// }
orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);
orderLastEndTime.put(groupId, actualEndTime);
// machineState.put(machineId, currentOp.getDiscreteParameter());
}
if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) {
chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t));
}
// 步骤4:计算调度指标
long calcStart = System.nanoTime();
calculateScheduleResult(chromosome);
// FileHelper.writeLogFile("[PERF] serialDecode calculateScheduleResult 耗时=" + fmtMs(System.nanoTime() - calcStart));
// FileHelper.writeLogFile("[PERF] serialDecode 总耗时=" + fmtMs(System.nanoTime() - decodeStart) + ", 工序数=" + opCount + ", 全局工序数=" + globalOpList.size());
}
......@@ -1048,6 +1040,7 @@ public class GeneticDecoder {
private int processWithSingleMachine(Entry operation, Machine machine, double processingTime,
int prevOperationEndTime,OpMachine machineOption, Chromosome chromosome,boolean calbom,int prevendtime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {
long pwsStart = System.nanoTime();
int processingTimeTotal=0;
int earliestStartTime = prevOperationEndTime;
if(operation.getConstTime()==1)//常数时间
......@@ -1108,7 +1101,7 @@ public class GeneticDecoder {
long machineId = machine.getId();
// 只有存在物料约束(或本次被强制要求重算 BOM)的工序,才需要联立求解“机台何时能排”和“物料何时可用”。
// targetFinishedOperationId != null 的工序通常由前置成品工序驱动,这里不再额外触发一轮 BOM 试算。
boolean needMaterialCheck =false;// (operation.getMaterialRequirements()!=null&&operation.getMaterialRequirements().size()>0&&operation.getTargetFinishedOperationId()==null)||calbom;
boolean needMaterialCheck =(operation.getMaterialRequirements()!=null&&operation.getMaterialRequirements().size()>0&&operation.getTargetFinishedOperationId()==null)||calbom;
// 正式落排后还要再做一次带提交的物料校验,把试算阶段推导出的 BOM 状态真正写回 chromosome。
boolean commitMaterialCheck = needMaterialCheck;
// baseEarliestStartTime:不考虑 BOM 推迟时的理论最早开工时间。
......@@ -1149,9 +1142,13 @@ public class GeneticDecoder {
{
candidateStartTime = Math.max(candidateStartTime,lastGeneOnMachine.getEndTime());
}
// 先在机台侧做一次“试排”,geneDetails 中会记录本轮临时占用的机台时间段。
// 先在机台侧做一次”试排”,geneDetails 中会记录本轮临时占用的机台时间段。
long iterStart = System.nanoTime();
long previewStart = System.nanoTime();
machinePreview = buildMachinePreview(scheduledOperation, scheduledMachine, processingTime, processingTimeTotal,
candidateStartTime, lastGeneOnMachine, machineTasks, chromosome);
long previewTime = System.nanoTime() - previewStart;
long bomTimeStart = System.nanoTime();
try {
// 物料侧只做试算,不提交最终状态;本轮只关心 BOM 约束会把开工时间推迟到哪里。
bomtime = EditOperationBOMTime(scheduledOperation,chromosome,machinePreview.getStartTime(),machineTasksCache, entryIndexById, scheduleIndexById, false);
......@@ -1165,6 +1162,13 @@ public class GeneticDecoder {
AddMachineAvailable(scheduledMachine, machinePreview.getGeneDetails());
}
}
// long bomTimeElapsed = System.nanoTime() - bomTimeStart;
// long iterElapsed = System.nanoTime() - iterStart;
// if (iterElapsed > 200_000_000L) { // 200ms
// FileHelper.writeLogFile("[PERF] processWithSingleMachine 固定点迭代慢 opId=" + operationId
// + ", iter=" + iteration + ", preview=" + fmtMs(previewTime)
// + ", BOM=" + fmtMs(bomTimeElapsed) + ", total=" + fmtMs(iterElapsed));
// }
// 下一轮候选开工时间取“基准最早开工”和“物料最早可开工”两者中的较晚值。
int nextCandidateStartTime = Math.max(baseEarliestStartTime, bomtime);
......@@ -1314,7 +1318,14 @@ public class GeneticDecoder {
// 1. 按最终 startTime 重新计算一次物料占用,并把状态真正写回;
// 2. 如果提交后的 BOM 时间仍然晚于 startTime,说明机台时间与物料时间没有收敛,需要直接报错。
if (commitMaterialCheck) {
long commitStart = System.nanoTime();
int committedBomTime = EditOperationBOMTime(operation,chromosome,startTime,machineTasksCache, entryIndexById, scheduleIndexById, true);
long commitElapsed = System.nanoTime() - commitStart;
// if (commitElapsed > 200_000_000L) {
// FileHelper.writeLogFile("[PERF] processWithSingleMachine 正式提交BOM慢 opId=" + operationId
// + ", startTime=" + startTime + ", commitBomTime=" + committedBomTime
// + ", 耗时=" + fmtMs(commitElapsed));
// }
bomtime = Math.max(bomtime, committedBomTime);
if (committedBomTime > startTime) {
throw new IllegalStateException(String.format(
......@@ -1393,6 +1404,12 @@ public class GeneticDecoder {
}
updateSemiJitTargets(operation, startTime, chromosome);
scheduleIndexById.put(operation.getId(),result);
// long pwsElapsed = System.nanoTime() - pwsStart;
// if (pwsElapsed > 500_000_000L) {
// FileHelper.writeLogFile("[PERF] processWithSingleMachine 总慢 opId=" + operationId
// + ", groupId=" + operation.getGroupId() + ", machineId=" + machineId
// + ", hasBOM=" + commitMaterialCheck + ", 耗时=" + fmtMs(pwsElapsed));
// }
return endTime;
}
......@@ -1746,6 +1763,7 @@ public class GeneticDecoder {
* commitChanges=false:只做试算,方法结束后恢复 chromosome 和相关索引缓存。
*/
private int EditOperationBOMTime(Entry currentOp, Chromosome chromosome,int earliestStartTime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById, boolean commitChanges) {
long t0 = System.nanoTime();
List<OrderMaterialRequirement> opboms= currentOp.getMaterialRequirements();
if(opboms==null)
{
......@@ -1755,65 +1773,181 @@ public class GeneticDecoder {
if(commitChanges) {
// 正式提交模式:直接把当前开工时间对应的物料占用/供应结果写回业务对象。
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById, baseTime, true);
return getOperationBOMTime(currentOp, chromosome);
int bomTime = getOperationBOMTime(currentOp, chromosome);
long elapsed = System.nanoTime() - t0;
// if (elapsed > 200_000_000L) {
// FileHelper.writeLogFile("[PERF] EditOperationBOMTime 正式提交慢 opId=" + currentOp.getId()
// + ", 耗时=" + fmtMs(elapsed));
// }
return bomTime;
}
// 试算模式:先复制一份完整状态,等 BOM 计算完成后再整体恢复。
TrialDecodeSnapshot snapshot = createTrialDecodeSnapshot(chromosome);
long snapStart = System.nanoTime();
TrialDecodeSnapshot snapshot = createTrialDecodeSnapshot(currentOp, chromosome);
long snapElapsed = System.nanoTime() - snapStart;
try {
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById, baseTime, true);
materialRequirementService.EditOperationBOM(currentOp,chromosome,earliestStartTime1,this,machineTasksCache, entryIndexById, scheduleIndexById, baseTime, false);
return getOperationBOMTime(currentOp, chromosome);
} finally {
// 试算期间 materialRequirementService 可能会改动 machine/order/material/result,这里统一回滚。
restoreTrialDecodeSnapshot(snapshot, chromosome, machineTasksCache, entryIndexById, scheduleIndexById);
// long restoreStart = System.nanoTime();
restoreTrialDecodeSnapshot(snapshot);
// long restoreElapsed = System.nanoTime() - restoreStart;
// long total = System.nanoTime() - t0;
// if (total > 200_000_000L) {
// FileHelper.writeLogFile("[PERF] EditOperationBOMTime 试算慢 opId=" + currentOp.getId()
// + ", 快照=" + fmtMs(snapElapsed) + ", 恢复=" + fmtMs(restoreElapsed)
// + ", 总耗时=" + fmtMs(total));
// }
}
}
// 试算 BOM 会改动多类状态对象,因此先把排程求解会依赖的核心集合做一次深拷贝快照。
private TrialDecodeSnapshot createTrialDecodeSnapshot(Chromosome chromosome) {
private TrialDecodeSnapshot createTrialDecodeSnapshot(Entry currentOp, Chromosome chromosome) {
TrialDecodeSnapshot snapshot = new TrialDecodeSnapshot();
snapshot.machines = ProductionDeepCopyUtil.deepCopyList(chromosome.getMachines(), Machine.class);
snapshot.orders = ProductionDeepCopyUtil.deepCopyList(chromosome.getOrders(), Order.class);
snapshot.materials = ProductionDeepCopyUtil.deepCopyList(chromosome.getMaterials(), Material.class);
snapshot.allOperations = ProductionDeepCopyUtil.deepCopyList(chromosome.getAllOperations(), Entry.class);
snapshot.results = ProductionDeepCopyUtil.deepCopyList(chromosome.getResult(), GAScheduleResult.class);
snapshot.reOrderIds = new ArrayList<>(chromosome.getReOrderids());
long t0 = System.nanoTime();
if (currentOp.getMaterialRequirements() != null) {
for (OrderMaterialRequirement requirement : currentOp.getMaterialRequirements()) {
snapshot.requirementStates.add(new RequirementSnapshot(requirement));
snapshot.captureStocks(chromosome, requirement.getMaterialId());
if (requirement.getReplaceMaterial() != null) {
for (OrderMaterialRequirement replace : requirement.getReplaceMaterial()) {
snapshot.captureStocks(chromosome, replace.getMaterialId());
}
}
}
}
// long total = System.nanoTime() - t0;
// if (total > 100_000_000L) {
// FileHelper.writeLogFile("[PERF] createTrialDecodeSnapshot 慢 requirements=" + snapshot.requirementStates.size()
// + ", stocks=" + snapshot.stockStates.size() + ", transit=" + snapshot.transitStates.size()
// + ", total=" + fmtMs(total));
// }
return snapshot;
}
// 恢复试算前的 chromosome 状态,并同步重建几个按 id/机台组织的缓存索引。
private void restoreTrialDecodeSnapshot(TrialDecodeSnapshot snapshot, Chromosome chromosome,
Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
Map<Integer, Entry> entryIndexById,
Map<Integer, GAScheduleResult> scheduleIndexById) {
chromosome.setMachines(snapshot.machines);
chromosome.setOrders(snapshot.orders);
chromosome.setMaterials(snapshot.materials);
chromosome.setAllOperations(snapshot.allOperations);
chromosome.setResult(snapshot.results);
chromosome.setReOrderids(snapshot.reOrderIds);
private void restoreTrialDecodeSnapshot(TrialDecodeSnapshot snapshot) {
for (RequirementSnapshot requirementState : snapshot.requirementStates) {
requirementState.restore();
}
for (StockSnapshot stockState : snapshot.stockStates) {
stockState.restore();
}
for (MaterialSupplySnapshot transitState : snapshot.transitStates) {
transitState.restore();
}
}
machineTasksCache.clear();
entryIndexById.clear();
for (Entry entry : chromosome.getAllOperations()) {
entryIndexById.put(entry.getId(), entry);
private static class TrialDecodeSnapshot {
private final List<RequirementSnapshot> requirementStates = new ArrayList<>();
private final List<StockSnapshot> stockStates = new ArrayList<>();
private final List<MaterialSupplySnapshot> transitStates = new ArrayList<>();
private final Set<Stock> seenStocks = Collections.newSetFromMap(new IdentityHashMap<>());
private final Set<MaterialSupply> seenTransit = Collections.newSetFromMap(new IdentityHashMap<>());
private void captureStocks(Chromosome chromosome, String materialId) {
if (materialId == null) {
return;
}
Material material = chromosome.getMaterials().stream()
.filter(t -> materialId.equals(t.getId()))
.findFirst()
.orElse(null);
if (material == null) {
return;
}
if (material.getMaterialStocks() != null) {
for (Stock stock : material.getMaterialStocks()) {
if (seenStocks.add(stock)) {
stockStates.add(new StockSnapshot(stock));
}
}
}
if (material.getInTransit() != null) {
for (MaterialSupply supply : material.getInTransit()) {
if (seenTransit.add(supply)) {
transitStates.add(new MaterialSupplySnapshot(supply));
}
}
}
}
}
scheduleIndexById.clear();
for (GAScheduleResult scheduleResult : chromosome.getResult()) {
scheduleIndexById.put(scheduleResult.getOperationId(), scheduleResult);
machineTasksCache.computeIfAbsent(scheduleResult.getMachineId(), key -> new CopyOnWriteArrayList<>()).add(scheduleResult);
private static class RequirementSnapshot {
private final OrderMaterialRequirement requirement;
private final double requiredQuantity;
private final double ypQty;
private final double qjQty;
private final double useStock;
private final double useTransit;
private final LocalDateTime arrivalTime;
private final LocalDateTime useTime;
private final LocalDateTime purchaseStartTime;
private final LocalDateTime purchaseEndTime;
private final Integer checkLeadTime;
private final Integer purchaseTime;
private final List<OrderMaterialRequirement> replaceMaterial;
private RequirementSnapshot(OrderMaterialRequirement requirement) {
this.requirement = requirement;
this.requiredQuantity = requirement.getRequiredQuantity();
this.ypQty = requirement.getYpQty();
this.qjQty = requirement.getQjQty();
this.useStock = requirement.getUseStock();
this.useTransit = requirement.getUseTransit();
this.arrivalTime = requirement.getArrivalTime();
this.useTime = requirement.getUseTime();
this.purchaseStartTime = requirement.getPurchaseStartTime();
this.purchaseEndTime = requirement.getPurchaseEndTime();
this.checkLeadTime = requirement.getCheckLeadTime();
this.purchaseTime = requirement.getPurchaseTime();
this.replaceMaterial = ProductionDeepCopyUtil.deepCopyList(requirement.getReplaceMaterial(), OrderMaterialRequirement.class);
}
private void restore() {
requirement.setRequiredQuantity(requiredQuantity);
requirement.setYpQty(ypQty);
requirement.setQjQty(qjQty);
requirement.setUseStock(useStock);
requirement.setUseTransit(useTransit);
requirement.setArrivalTime(arrivalTime);
requirement.setUseTime(useTime);
requirement.setPurchaseStartTime(purchaseStartTime);
requirement.setPurchaseEndTime(purchaseEndTime);
requirement.setCheckLeadTime(checkLeadTime);
requirement.setPurchaseTime(purchaseTime);
requirement.setReplaceMaterial(replaceMaterial == null ? new ArrayList<>() : ProductionDeepCopyUtil.deepCopyList(replaceMaterial, OrderMaterialRequirement.class));
}
}
private static class TrialDecodeSnapshot {
private List<Machine> machines;
private CopyOnWriteArrayList<Order> orders;
private List<Material> materials;
private CopyOnWriteArrayList<Entry> allOperations;
private CopyOnWriteArrayList<GAScheduleResult> results;
private List<Integer> reOrderIds;
private static class StockSnapshot {
private final Stock stock;
private final double usedInventory;
private StockSnapshot(Stock stock) {
this.stock = stock;
this.usedInventory = stock.getUsedInventory();
}
private void restore() {
stock.setUsedInventory(usedInventory);
}
}
private static class MaterialSupplySnapshot {
private final MaterialSupply supply;
private final double quantity;
private MaterialSupplySnapshot(MaterialSupply supply) {
this.supply = supply;
this.quantity = supply.getQuantity();
}
private void restore() {
supply.setQuantity(quantity);
}
}
public void EditorderOperation(Chromosome chromosome, int groupId,double needed,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment