mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
cache split result as String[], foreach optimization
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package com.taobao.arthas.core.advisor;
|
||||
|
||||
import java.arthas.SpyAPI.AbstractSpy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -25,20 +24,21 @@ import com.taobao.arthas.core.util.StringUtils;
|
||||
*/
|
||||
public class SpyImpl extends AbstractSpy {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SpyImpl.class);
|
||||
private final Map<String, List<String>> splitCache = new ConcurrentHashMap<String, List<String>>();
|
||||
private final Map<String, String[]> splitCache = new ConcurrentHashMap<String, String[]>();
|
||||
|
||||
@Override
|
||||
public void atEnter(Class<?> clazz, String methodInfo, Object target, Object[] args) {
|
||||
ClassLoader classLoader = clazz.getClassLoader();
|
||||
|
||||
List<String> strs = splitMethodInfo(methodInfo);
|
||||
String methodName = strs.get(0);
|
||||
String methodDesc = strs.get(1);
|
||||
String[] info = splitMethodInfo(methodInfo);
|
||||
String methodName = info[0];
|
||||
String methodDesc = info[1];
|
||||
// TODO listener 只用查一次,放到 thread local里保存起来就可以了!
|
||||
List<AdviceListener> listeners = AdviceListenerManager.queryAdviceListeners(classLoader, clazz.getName(),
|
||||
methodName, methodDesc);
|
||||
if (listeners != null) {
|
||||
for (AdviceListener adviceListener : listeners) {
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
AdviceListener adviceListener = listeners.get(i);
|
||||
try {
|
||||
if (skipAdviceListener(adviceListener)) {
|
||||
continue;
|
||||
@@ -58,14 +58,15 @@ public class SpyImpl extends AbstractSpy {
|
||||
public void atExit(Class<?> clazz, String methodInfo, Object target, Object[] args, Object returnObject) {
|
||||
ClassLoader classLoader = clazz.getClassLoader();
|
||||
|
||||
List<String> strs = splitMethodInfo(methodInfo);
|
||||
String methodName = strs.get(0);
|
||||
String methodDesc = strs.get(1);
|
||||
String[] info = splitMethodInfo(methodInfo);
|
||||
String methodName = info[0];
|
||||
String methodDesc = info[1];
|
||||
|
||||
List<AdviceListener> listeners = AdviceListenerManager.queryAdviceListeners(classLoader, clazz.getName(),
|
||||
methodName, methodDesc);
|
||||
if (listeners != null) {
|
||||
for (AdviceListener adviceListener : listeners) {
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
AdviceListener adviceListener = listeners.get(i);
|
||||
try {
|
||||
if (skipAdviceListener(adviceListener)) {
|
||||
continue;
|
||||
@@ -84,14 +85,15 @@ public class SpyImpl extends AbstractSpy {
|
||||
public void atExceptionExit(Class<?> clazz, String methodInfo, Object target, Object[] args, Throwable throwable) {
|
||||
ClassLoader classLoader = clazz.getClassLoader();
|
||||
|
||||
List<String> strs = splitMethodInfo(methodInfo);
|
||||
String methodName = strs.get(0);
|
||||
String methodDesc = strs.get(1);
|
||||
String[] info = splitMethodInfo(methodInfo);
|
||||
String methodName = info[0];
|
||||
String methodDesc = info[1];
|
||||
|
||||
List<AdviceListener> listeners = AdviceListenerManager.queryAdviceListeners(classLoader, clazz.getName(),
|
||||
methodName, methodDesc);
|
||||
if (listeners != null) {
|
||||
for (AdviceListener adviceListener : listeners) {
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
AdviceListener adviceListener = listeners.get(i);
|
||||
try {
|
||||
if (skipAdviceListener(adviceListener)) {
|
||||
continue;
|
||||
@@ -109,23 +111,23 @@ public class SpyImpl extends AbstractSpy {
|
||||
@Override
|
||||
public void atBeforeInvoke(Class<?> clazz, String invokeInfo, Object target) {
|
||||
ClassLoader classLoader = clazz.getClassLoader();
|
||||
List<String> strs = splitInvokeInfo(invokeInfo);
|
||||
String owner = strs.get(0);
|
||||
String methodName = strs.get(1);
|
||||
String methodDesc = strs.get(2);
|
||||
String[] info = splitInvokeInfo(invokeInfo);
|
||||
String owner = info[0];
|
||||
String methodName = info[1];
|
||||
String methodDesc = info[2];
|
||||
|
||||
List<AdviceListener> listeners = AdviceListenerManager.queryTraceAdviceListeners(classLoader, clazz.getName(),
|
||||
owner, methodName, methodDesc);
|
||||
|
||||
if (listeners != null) {
|
||||
int lineNumber = Integer.parseInt(strs.get(3));
|
||||
for (AdviceListener adviceListener : listeners) {
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
AdviceListener adviceListener = listeners.get(i);
|
||||
try {
|
||||
if (skipAdviceListener(adviceListener)) {
|
||||
continue;
|
||||
}
|
||||
final InvokeTraceable listener = (InvokeTraceable) adviceListener;
|
||||
listener.invokeBeforeTracing(owner, methodName, methodDesc, lineNumber);
|
||||
listener.invokeBeforeTracing(owner, methodName, methodDesc, Integer.parseInt(info[3]));
|
||||
} catch (Throwable e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.error("class: {}, invokeInfo: {}", clazz.getName(), invokeInfo, e);
|
||||
@@ -138,22 +140,22 @@ public class SpyImpl extends AbstractSpy {
|
||||
@Override
|
||||
public void atAfterInvoke(Class<?> clazz, String invokeInfo, Object target) {
|
||||
ClassLoader classLoader = clazz.getClassLoader();
|
||||
List<String> strs = splitInvokeInfo(invokeInfo);
|
||||
String owner = strs.get(0);
|
||||
String methodName = strs.get(1);
|
||||
String methodDesc = strs.get(2);
|
||||
String[] info = splitInvokeInfo(invokeInfo);
|
||||
String owner = info[0];
|
||||
String methodName = info[1];
|
||||
String methodDesc = info[2];
|
||||
List<AdviceListener> listeners = AdviceListenerManager.queryTraceAdviceListeners(classLoader, clazz.getName(),
|
||||
owner, methodName, methodDesc);
|
||||
|
||||
if (listeners != null) {
|
||||
int lineNumber = Integer.parseInt(strs.get(3));
|
||||
for (AdviceListener adviceListener : listeners) {
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
AdviceListener adviceListener = listeners.get(i);
|
||||
try {
|
||||
if (skipAdviceListener(adviceListener)) {
|
||||
continue;
|
||||
}
|
||||
final InvokeTraceable listener = (InvokeTraceable) adviceListener;
|
||||
listener.invokeAfterTracing(owner, methodName, methodDesc, lineNumber);
|
||||
listener.invokeAfterTracing(owner, methodName, methodDesc, Integer.parseInt(info[3]));
|
||||
} catch (Throwable e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.error("class: {}, invokeInfo: {}", clazz.getName(), invokeInfo, e);
|
||||
@@ -167,23 +169,23 @@ public class SpyImpl extends AbstractSpy {
|
||||
@Override
|
||||
public void atInvokeException(Class<?> clazz, String invokeInfo, Object target, Throwable throwable) {
|
||||
ClassLoader classLoader = clazz.getClassLoader();
|
||||
List<String> strs = splitInvokeInfo(invokeInfo);
|
||||
String owner = strs.get(0);
|
||||
String methodName = strs.get(1);
|
||||
String methodDesc = strs.get(2);
|
||||
String[] info = splitInvokeInfo(invokeInfo);
|
||||
String owner = info[0];
|
||||
String methodName = info[1];
|
||||
String methodDesc = info[2];
|
||||
|
||||
List<AdviceListener> listeners = AdviceListenerManager.queryTraceAdviceListeners(classLoader, clazz.getName(),
|
||||
owner, methodName, methodDesc);
|
||||
|
||||
if (listeners != null) {
|
||||
int lineNumber = Integer.parseInt(strs.get(3));
|
||||
for (AdviceListener adviceListener : listeners) {
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
AdviceListener adviceListener = listeners.get(i);
|
||||
try {
|
||||
if (skipAdviceListener(adviceListener)) {
|
||||
continue;
|
||||
}
|
||||
final InvokeTraceable listener = (InvokeTraceable) adviceListener;
|
||||
listener.invokeThrowTracing(owner, methodName, methodDesc, lineNumber);
|
||||
listener.invokeThrowTracing(owner, methodName, methodDesc, Integer.parseInt(info[3]));
|
||||
} catch (Throwable e) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.error("class: {}, invokeInfo: {}", clazz.getName(), invokeInfo, e);
|
||||
@@ -193,26 +195,24 @@ public class SpyImpl extends AbstractSpy {
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> splitMethodInfo(String methodInfo) {
|
||||
private String[] splitMethodInfo(String methodInfo) {
|
||||
return splitString(methodInfo);
|
||||
}
|
||||
|
||||
private List<String> splitInvokeInfo(String invokeInfo) {
|
||||
private String[] splitInvokeInfo(String invokeInfo) {
|
||||
return splitString(invokeInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 经过优化的字符串split方法,减少产生的内存碎片。
|
||||
* trace/watch 等字节码拦截回调每次都需要进行字符串split,调用很频繁,产生较多小对象。
|
||||
* 注意: 返回的List为重用的缓存对象,不能直接引用它,有需要请复制一份
|
||||
* 缓存字符串split结果,减少频繁调用产生的内存碎片。
|
||||
* trace/watch/monitor 等字节码拦截回调每次都需要进行字符串split,如果拦截的是高频方法,回调很频繁,产生较多小对象。
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
private List<String> splitString(String str) {
|
||||
List<String> strs = splitCache.get(str);
|
||||
private String[] splitString(String str) {
|
||||
String[] strs = splitCache.get(str);
|
||||
if (strs == null) {
|
||||
strs = new ArrayList<String>(8);
|
||||
StringUtils.splitToList(str, '|', strs);
|
||||
strs = StringUtils.split(str, '|');
|
||||
splitCache.put(str, strs);
|
||||
}
|
||||
return strs;
|
||||
|
||||
Reference in New Issue
Block a user