Java tutorial
/* * Copyright 2010-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package gemlite.core.internal.measurement; import gemlite.core.annotations.logic.CheckPoint; import gemlite.core.annotations.logic.RemoteService; import gemlite.core.api.logic.LogicSession; import gemlite.core.internal.admin.measurement.ScannedMethodItem; import gemlite.core.internal.context.registryClass.RemoteServiceRegistry; import gemlite.core.internal.support.annotations.GemliteAnnotation; import gemlite.core.internal.support.context.GemliteContext; import gemlite.core.internal.support.context.IModuleContext; import gemlite.core.util.GemliteHelper; import gemlite.core.util.LogUtil; import gemlite.core.util.Util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.apache.commons.lang.math.NumberUtils; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.LdcInsnNode; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.VarInsnNode; public class MeasureHelper { private static int queueSize = NumberUtils.toInt(System.getProperty("gemlite.core.measure.queue-size", "1024")); private static ArrayBlockingQueue<RemoteServiceStatItem> measureQueue = new ArrayBlockingQueue<>(queueSize); private static MeasureMonitorTask monitorTask; private static String checkPointDesc = Util.getInternalDesc(CheckPoint.class); private static MeasureTPSTask tpsTask; private static ScheduledExecutorService scheduledService; static class MeasureMonitorTask extends Thread { private boolean flag = false; public MeasureMonitorTask() { super.setDaemon(true); } /*** * ? * ??? * * * */ @Override public void run() { while (!flag) { try { RemoteServiceStatItem rsi = measureQueue.take(); RemoteServiceStat rss = getRemoteServiceStat(rsi.getModuleName(), rsi.getServiceName()); rss.recordItem(rsi); // if (LogUtil.getJMXLog().isDebugEnabled()) LogUtil.getJMXLog().debug(rsi.toString()); } catch (Exception e) { e.printStackTrace(); } } if (LogUtil.getCoreLog().isInfoEnabled()) LogUtil.getCoreLog().info("Measure monitor task stopped."); } } static class MeasureTPSTask extends Thread { public MeasureTPSTask() { super.setDaemon(true); } @Override public void run() { try { Iterator<IModuleContext> it = GemliteContext.getModuleContexts(); while (it.hasNext()) { IModuleContext ctx = it.next(); RemoteServiceRegistry reg = (RemoteServiceRegistry) ctx.getRegistry(RemoteService.class); if (reg != null && reg.getMbeanMap() != null) { Iterator<RemoteServiceStat> rsit = reg.getMbeanMap().values().iterator(); while (rsit.hasNext()) { RemoteServiceStat rs = rsit.next(); rs.calcuteTPS(); } } } } catch (Throwable e) { LogUtil.getCoreLog().debug("", e); } } } public final static void init() { monitorTask = new MeasureMonitorTask(); monitorTask.start(); scheduledService = new ScheduledThreadPoolExecutor(1); tpsTask = new MeasureTPSTask(); scheduledService.scheduleWithFixedDelay(tpsTask, 1, 2, TimeUnit.SECONDS); if (LogUtil.getCoreLog().isInfoEnabled()) LogUtil.getCoreLog().info("Measure monitor task started."); } public final static RemoteServiceStat getRemoteServiceStat(String moduleName, String serviceName) { IModuleContext ctx = GemliteContext.getModuleContext(moduleName); if (ctx != null) { RemoteServiceRegistry reg = (RemoteServiceRegistry) ctx.getRegistry(RemoteService.class); RemoteServiceStat rss = reg.getStatItem(serviceName); return rss; } return null; } /*** * ? */ public final static void remoteServiceEnd(RemoteServiceStatItem si) { if (LogUtil.getCoreLog().isDebugEnabled()) LogUtil.getCoreLog().debug( "Record service:" + si.getServiceName() + " start:" + si.getStart() + " end:" + si.getEnd()); if (si != null) { measureQueue.offer(si); } } /*** * * @param className * @param checkPoint * @param start * @param end */ public final static void recordCheckPoint(String className, String checkPoint, long start, long end) { try { RemoteServiceStatItem si = LogicSession.getSession().getRemoteServiceStatItem(); CheckPointStat item = new CheckPointStat(); item.setCheckPoint(checkPoint); item.setStart(start); item.setEnd(end); item.setClassName(className); si.addCheckPoint(item); if (LogUtil.getCoreLog().isDebugEnabled()) LogUtil.getCoreLog().debug("End timer:" + className + "." + si.getServiceName() + ":" + checkPoint + " end:" + item.getEnd() + " thread:" + Thread.currentThread().getId()); } catch (Exception e) { LogUtil.getCoreLog().error("Measure error,className:" + className + " checkPoint:" + checkPoint, e); } } /*** * /*** * 1.??=LogicBean.className $$$ TraceCostBean * 2.LogicBean * Class ****LogicBean$$$TraceCostBean * public long methodName1Cost; * public long methodName2Cost; * * @param cn * @param context * @param className * @param cn * @return */ private final static boolean checkMethodName(ClassNode cn, MethodNode mn, Set<ScannedMethodItem> methods) { ScannedMethodItem check = new ScannedMethodItem(cn.name, mn.name, mn.desc); if (methods != null && methods.contains(check)) return true; if (methods == null) { GemliteAnnotation ga = GemliteHelper.readAnnotations(cn); return ga.getAnnotation(checkPointDesc) != null; } return false; } public final static int instrumentCheckPoint(String className, ClassNode cn) { return instrumentCheckPoint(className, cn, null); } public final static void instrumentCheckPoint(String className, MethodNode mn) { if (LogUtil.getCoreLog().isTraceEnabled()) LogUtil.getCoreLog().trace("Found check point, class:" + className + " method:" + mn.name); InsnList insn = mn.instructions; List<AbstractInsnNode> returnIndex = new ArrayList<>(); // return int localVarCount = mn.localVariables.size(); for (int i = 0; i < insn.size(); i++) { AbstractInsnNode insnNode = (AbstractInsnNode) insn.get(i); switch (insnNode.getOpcode()) { case Opcodes.ARETURN: case Opcodes.IRETURN: case Opcodes.DRETURN: case Opcodes.LRETURN: case Opcodes.FRETURN: returnIndex.add(insnNode.getPrevious()); break; case Opcodes.RETURN: returnIndex.add(insnNode); break; } } // insn.insert(new VarInsnNode(Opcodes.LSTORE, localVarCount + 2)); insn.insert( new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false)); // ? for (AbstractInsnNode insnNode : returnIndex) { insn.insertBefore(insnNode, new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false)); insn.insertBefore(insnNode, new VarInsnNode(Opcodes.LSTORE, localVarCount + 4)); insn.insertBefore(insnNode, new LdcInsnNode(className)); insn.insertBefore(insnNode, new LdcInsnNode(mn.name)); insn.insertBefore(insnNode, new VarInsnNode(Opcodes.LLOAD, localVarCount + 2)); insn.insertBefore(insnNode, new VarInsnNode(Opcodes.LLOAD, localVarCount + 4)); insn.insertBefore(insnNode, new MethodInsnNode(Opcodes.INVOKESTATIC, "gemlite/core/internal/measurement/MeasureHelper", "recordCheckPoint", "(Ljava/lang/String;Ljava/lang/String;JJ)V", false)); } } /*** * * @param className * @param cn * @param methods * @return */ public final static int instrumentCheckPoint(String className, ClassNode cn, Set<ScannedMethodItem> methods) { int num = 0; for (Object obj : cn.methods) { MethodNode mn = (MethodNode) obj; if (checkMethodName(cn, mn, methods)) { instrumentCheckPoint(className, mn); num++; } } return num; } }