From 278ab67f0b884ee76fee67728bdfee4ea01b4e0b Mon Sep 17 00:00:00 2001 From: Harrison Date: Tue, 8 Mar 2022 14:00:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20KERNEL-10354=20bytebuddy=20/=20?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E5=AF=86=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20@Harrison=20=E9=98=B2=E6=AD=A2=E6=95=B4=E4=B8=AA=20UI=20?= =?UTF-8?q?=E5=A0=B5=E5=A1=9E=EF=BC=8C=E9=97=B4=E6=AD=87=E6=80=A7=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../env/LocalDesignerWorkspaceInfo.java | 31 +++---- .../record/analyzer/DesignerAnalyzer.java | 3 +- .../analyzer/DesignerAnalyzerActivator.java | 55 ++++++----- .../analyzer/DesignerAssemblyFactory.java | 91 +++++++++++++++++++ 4 files changed, 136 insertions(+), 44 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java diff --git a/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java b/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java index a7d6eb6c17..4a488cb2d3 100644 --- a/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java +++ b/designer-base/src/main/java/com/fr/design/env/LocalDesignerWorkspaceInfo.java @@ -1,17 +1,10 @@ package com.fr.design.env; -import com.fr.general.ComparatorUtils; -import com.fr.general.GeneralUtils; -import com.fr.locale.InterProviderFactory; -import com.fr.stable.CoreConstants; -import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; -import com.fr.stable.project.ProjectConstants; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; import com.fr.workspace.connect.WorkspaceConnectionInfo; -import com.fr.workspace.engine.exception.MainVersionNotMatchException; import java.io.File; import java.util.Properties; @@ -101,18 +94,18 @@ public class LocalDesignerWorkspaceInfo implements DesignerWorkspaceInfo { @Override public boolean checkValid(){ File file = new File(this.path); - //判断不是文件夹/路径不在WEB-INF下/代码启动三种情况 - if(!file.isDirectory() || !ComparatorUtils.equals(file.getName(), "WEB-INF") || this.path.startsWith(".")) { - return false; - } - - File engineLib = new File(StableUtils.pathJoin(this.path, ProjectConstants.LIB_NAME, REPORT_ENGINE_JAR)); - // 非安装版本允许自由切换 - boolean notExistLib = !CoreConstants.DOT.equals(StableUtils.getInstallHome()) - && !engineLib.exists(); - if (notExistLib) { - throw new MainVersionNotMatchException(); - } + ////判断不是文件夹/路径不在WEB-INF下/代码启动三种情况 + //if(!file.isDirectory() || !ComparatorUtils.equals(file.getName(), "WEB-INF") || this.path.startsWith(".")) { + // return false; + //} + // + //File engineLib = new File(StableUtils.pathJoin(this.path, ProjectConstants.LIB_NAME, REPORT_ENGINE_JAR)); + //// 非安装版本允许自由切换 + //boolean notExistLib = !CoreConstants.DOT.equals(StableUtils.getInstallHome()) + // && !engineLib.exists(); + //if (notExistLib) { + // throw new MainVersionNotMatchException(); + //} return true; } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java index fe4b308065..bdd437ac14 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzer.java @@ -3,7 +3,6 @@ package com.fr.design.record.analyzer; import com.fr.record.analyzer.AnalyzerConfiguration; import com.fr.record.analyzer.AnalyzerUnit; import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; -import com.fr.record.analyzer.configuration.impl.RedefineAssemblyFactory; /** * created by Harrison on 2022/03/08 @@ -14,7 +13,7 @@ public class DesignerAnalyzer { public static synchronized void init(AnalyzerAssemblyFactory factory, AnalyzerConfiguration... configurations) { - AnalyzerAssemblyFactory redefineFactory = factory.prepare(RedefineAssemblyFactory.getInstance()); + AnalyzerAssemblyFactory redefineFactory = factory.prepare(DesignerAssemblyFactory.getInstance()); ANALYZER.init(redefineFactory, configurations); } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java index 60b65b1a19..45c302c26a 100644 --- a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAnalyzerActivator.java @@ -2,11 +2,16 @@ package com.fr.design.record.analyzer; import com.fr.base.OptimizeUtil; import com.fr.concurrent.NamedThreadFactory; +import com.fr.design.constants.DesignerLaunchStatus; import com.fr.design.record.analyzer.advice.DBMonitorAdvice; import com.fr.design.record.analyzer.advice.FaultToleranceAdvice; import com.fr.design.record.analyzer.advice.FocusAdvice; import com.fr.design.record.analyzer.advice.MonitorAdvice; import com.fr.design.record.analyzer.advice.PerformancePointAdvice; +import com.fr.event.Event; +import com.fr.event.EventDispatcher; +import com.fr.event.Listener; +import com.fr.event.Null; import com.fr.intelli.metrics.Compute; import com.fr.intelli.record.Focus; import com.fr.intelli.record.PerformancePoint; @@ -15,10 +20,10 @@ import com.fr.module.extension.Prepare; import com.fr.record.analyzer.AnalyzerConfiguration; import com.fr.record.analyzer.AnalyzerKey; import com.fr.record.analyzer.DBMetrics; -import com.fr.record.analyzer.FineAdviceTransformer; import com.fr.record.analyzer.FineAnalyzer; import com.fr.record.analyzer.advice.AnalyzerAdviceConfiguration; import com.fr.record.analyzer.advice.AnalyzerAdviceKey; +import com.fr.record.analyzer.advice.FineAdviceTransformer; import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; import com.fr.record.analyzer.configuration.FineAnalyzerAssemblyFactory; import com.fr.stable.collections.CollectionUtils; @@ -38,32 +43,36 @@ public class DesignerAnalyzerActivator extends Activator implements Prepare { public void start() { OptimizeUtil.open(() -> { - ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true)); - - try { - AnalyzerAssemblyFactory basicFactory = createBasicFactory(); + + AnalyzerAssemblyFactory basicFactory = createBasicFactory(); + + // 兼容逻辑 + List backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY); + if (!CollectionUtils.isEmpty(backwardsConfigurations)) { + FineAnalyzer.init(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0])); + } + + EventDispatcher.listen(DesignerLaunchStatus.STARTUP_COMPLETE, new Listener() { - // 兼容逻辑 - List backwardsConfigurations = findMutableBackwards(AnalyzerKey.KEY); - if (!CollectionUtils.isEmpty(backwardsConfigurations)) { - es.submit(() -> { - FineAnalyzer.init(basicFactory, backwardsConfigurations.toArray(new AnalyzerConfiguration[0])); - }); - } + @Override + public void on(Event event, Null param) { - // 加入 retransform 部分的逻辑 - List adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY); + ExecutorService es = newSingleThreadExecutor(new NamedThreadFactory("designer-analyzer", true)); + try { + // 加入 retransform 部分的逻辑 + List adviceConfigurations = findMutable(AnalyzerAdviceKey.KEY); - if (!CollectionUtils.isEmpty(adviceConfigurations)) { - AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations); - es.submit(() -> { - DesignerAnalyzer.init(basicFactory, configurations); - }); + if (!CollectionUtils.isEmpty(adviceConfigurations)) { + AnalyzerConfiguration[] configurations = convertConfigurations(adviceConfigurations); + es.submit(() -> { + DesignerAnalyzer.init(basicFactory, configurations); + }); + } + } finally { + es.shutdown(); + } } - - } finally { - es.shutdown(); - } + }); }); } diff --git a/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java new file mode 100644 index 0000000000..0c8ffa40e2 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/record/analyzer/DesignerAssemblyFactory.java @@ -0,0 +1,91 @@ +package com.fr.design.record.analyzer; + +import com.fr.record.analyzer.configuration.AnalyzerAssemblyFactory; +import com.fr.third.net.bytebuddy.agent.builder.AgentBuilder; + +import java.util.List; +import java.util.Map; + +/** + * 装配 Agent 为后置启动 + *

必须在一个线程中处理 retransform 的事务,否则会阻塞整个的线程,导致效果不佳

+ * + * created by Harrison on 2022/03/07 + **/ +public class DesignerAssemblyFactory implements AnalyzerAssemblyFactory { + + /** + * 每次执行 1 个 class 的 retransform + */ + private static final int FIXED_SIZE = 1; + + /** + * 单位 ms + * 每次间隔 500 ms, 执行一次 + */ + private static final int DELAY_INTERVAL = 500; + + private final AgentBuilder.RedefinitionStrategy.BatchAllocator batchAllocator = AgentBuilder.RedefinitionStrategy.BatchAllocator.ForFixedSize.ofSize(FIXED_SIZE); + + private final AgentBuilder.RedefinitionStrategy.Listener redefinitionListener = new DelayListener(DELAY_INTERVAL); + + public static DesignerAssemblyFactory getInstance() { + return DesignerAssemblyFactoryHolder.INSTANCE; + } + + private static class DesignerAssemblyFactoryHolder { + private static final DesignerAssemblyFactory INSTANCE = new DesignerAssemblyFactory(); + } + + @Override + public AnalyzerAssemblyFactory prepare(Object material) { + + return this; + } + + @Override + public AgentBuilder assembly(AgentBuilder raw) { + + return raw.disableClassFormatChanges() + .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) + // 每次只 transform 一部分否则会导致 UI 变慢 + .with(batchAllocator) + .with(redefinitionListener) + .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE) + .with(AgentBuilder.TypeStrategy.Default.REDEFINE); + } + + private class DelayListener implements AgentBuilder.RedefinitionStrategy.Listener { + + /** + * 单位 ms + */ + private final int interval; + + public DelayListener(int interval) { + this.interval = interval; + } + + /** + * 执行完后,等待一段时间再执行。 + */ + @Override + public void onBatch(int index, List> batch, List> types) { + + try { + Thread.sleep(interval); + } catch (Exception ignore) { + } + } + + @Override + public Iterable>> onError(int index, List> batch, Throwable throwable, List> types) { + return null; + } + + @Override + public void onComplete(int amount, List> types, Map>, Throwable> failures) { + + } + } +}