mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
Add Countable interface for result model
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package com.taobao.arthas.core.command.model;
|
||||
|
||||
/**
|
||||
* Item countable for ResultModel
|
||||
* @author gongdewei 2020/6/8
|
||||
*/
|
||||
public interface Countable {
|
||||
|
||||
/**
|
||||
* Get item size of this result model, the value of size is greater than or equal to 1
|
||||
* @return item size of this result model
|
||||
*/
|
||||
int size();
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.taobao.arthas.core.distribution;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.taobao.arthas.core.command.model.Countable;
|
||||
import com.taobao.arthas.core.command.model.ResultModel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -14,49 +15,56 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 命令结果模型辅助类
|
||||
*
|
||||
* @author gongdewei 2020/5/18
|
||||
*/
|
||||
public class ResultConsumerHelper {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ResultConsumerHelper.class);
|
||||
|
||||
private static Map<String, List<Field>> modelFieldMap = new ConcurrentHashMap<String, List<Field>>();
|
||||
private static ConcurrentHashMap<String, List<Field>> modelFieldMap = new ConcurrentHashMap<String, List<Field>>();
|
||||
|
||||
/**
|
||||
* 估算命令执行结果的item数量
|
||||
* 注意:此方法调用频繁,不能产生内存碎片
|
||||
* 估算命令执行结果的item数量,目的是提供一个度量值,作为Consumer分发时进行切片的参考依据,避免单次发送大量数据。
|
||||
* 注意:此方法调用频繁,避免产生内存碎片
|
||||
*
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
public static int getItemCount(ResultModel model) {
|
||||
int count = processSpecialCommand(model);
|
||||
if (count > 0) {
|
||||
return count;
|
||||
//如果实现Countable接口,则认为model自己统计元素数量
|
||||
if (model instanceof Countable) {
|
||||
return ((Countable) model).size();
|
||||
}
|
||||
|
||||
//TODO 抽取ItemSet/ItemGroup接口,解决ClassSetVO/mbean等分组的情况
|
||||
|
||||
//对于普通的Model,通过类反射统计容器类字段统计元素数量
|
||||
//缓存Field对象,避免产生内存碎片
|
||||
Class modelClass = model.getClass();
|
||||
List<Field> fields = modelFieldMap.get(modelClass.getName());
|
||||
if (fields == null) {
|
||||
fields = new ArrayList<Field>();
|
||||
modelFieldMap.put(modelClass.getName(), fields);
|
||||
Field[] declaredFields = modelClass.getDeclaredFields();
|
||||
for (int i = 0; i < declaredFields.length; i++) {
|
||||
Field field = declaredFields[i];
|
||||
Class<?> fieldClass = field.getType();
|
||||
//如果是List/Map/Array/Countable类型的字段,则缓存起来后面统计数量
|
||||
if (Collection.class.isAssignableFrom(fieldClass)
|
||||
|| Map.class.isAssignableFrom(fieldClass)
|
||||
|| fieldClass.isArray()
|
||||
/* || fieldClass == ClassSetVO.class*/) {
|
||||
|| Countable.class.isAssignableFrom(fieldClass)
|
||||
|| fieldClass.isArray()) {
|
||||
field.setAccessible(true);
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
List<Field> old_fields = modelFieldMap.putIfAbsent(modelClass.getName(), fields);
|
||||
if (old_fields != null) {
|
||||
fields = old_fields;
|
||||
}
|
||||
}
|
||||
|
||||
//获取item数量
|
||||
//统计Model对象的item数量
|
||||
int count = 0;
|
||||
try {
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
Field field = fields.get(i);
|
||||
@@ -65,14 +73,14 @@ public class ResultConsumerHelper {
|
||||
}
|
||||
Object value = field.get(model);
|
||||
if (value != null) {
|
||||
if (value instanceof Collection) {
|
||||
return ((Collection) value).size();
|
||||
if (value instanceof Collection) {
|
||||
count += ((Collection) value).size();
|
||||
} else if (value.getClass().isArray()) {
|
||||
return Array.getLength(value);
|
||||
count += Array.getLength(value);
|
||||
} else if (value instanceof Map) {
|
||||
return ((Map) value).size();
|
||||
// } else if (value.getClass() == ClassSetVO.class) {
|
||||
// return ((ClassSetVO) value).getClasses().size();
|
||||
count += ((Map) value).size();
|
||||
} else if (value instanceof Countable) {
|
||||
count += ((Countable) value).size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,18 +88,7 @@ public class ResultConsumerHelper {
|
||||
logger.error("get item count of result model failed, model: {}", JSON.toJSONString(model), e);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int processSpecialCommand(ResultModel model) {
|
||||
// if (model instanceof CatModel) {
|
||||
// //特殊处理cat
|
||||
// return ((CatModel) model).getContent().length()/100 + 1 ;
|
||||
// } else if (model instanceof TraceModel) {
|
||||
// //特殊处理trace
|
||||
// return ((TraceModel) model).getNodeCount();
|
||||
// }
|
||||
return 0;
|
||||
return count > 0 ? count : 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user