下面是我的课程,用于CountDownLatch
确保在这些地图上发生写入时第一次不会在主要、次要和三级地图上发生读取。
public class ClientData {
public static class Mappings {
public final Map<String, Map<Integer, String>> primary;
public final Map<String, Map<Integer, String>> secondary;
public final Map<String, Map<Integer, String>> tertiary;
public Mappings(
Map<String, Map<Integer, String>> primary,
Map<String, Map<Integer, String>> secondary,
Map<String, Map<Integer, String>> tertiary
) {
this.primary = primary;
this.secondary = secondary;
this.tertiary = tertiary;
}
}
private static final AtomicReference<Mappings> mappings = new AtomicReference<>();
private static final CountDownLatch hasBeenInitialized = new CountDownLatch(1);
public static Mappings getMappings() {
try {
hasBeenInitialized.await();
return mappings.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
}
public static void setMappings(
Map<String, Map<Integer, String>> primary,
Map<String, Map<Integer, String>> secondary,
Map<String, Map<Integer, String>> tertiary
) {
setMappings(new Mappings(primary, secondary, tertiary));
}
public static void setMappings(Mappings newMappings) {
mappings.set(newMappings);
hasBeenInitialized.countDown();
}
}
下面是我的后台线程类,它只负责设置所有三个映射(在下面查找 parseResponse 方法)。它每 10 分钟运行一次。
public class TempBackgroundThread {
// parse the response and store it in a variable
private void parseResponse(String response) {
//...
Map<String, Map<Integer, String>> primaryTables = null;
Map<String, Map<Integer, String>> secondaryTables = null;
Map<String, Map<Integer, String>> tertiaryTables = null;
//...
// store the three map data in ClientData class variables if anything has changed
// which can be used by other threads, this will be updated once every four or five months
if(changed) {
ClientData.setMappings(primaryTables, secondaryTables, tertiaryTables);
}
}
}
问题陈述:
如果我对我的映射对象以及主要、次要和三次映射进行各种空值或完整性检查,性能会大大降低(不知道为什么)。但是,如果我不做任何健全性或空值检查,性能就会非常好。谁能解释我出了什么问题以及为什么会发生?
下面是一个例子 -
我正在使用ClientData
类来获取主线程中的所有映射。正如您在下面看到的,我正在做各种健全性检查以确保、 和mappings
不mappings.primary
为空。如果它们为空,则记录错误并返回mappings.secondary
mappings.tertiary
class Task implements Callable<String> {
public Task() {
}
public String call() throws Exception {
int compId = 100;
String localPath = "hello";
String remotePath = "world";
Mappings mappings = ClientData.getMappings();
if (MyUtilityClass.isEmpty(mappings)
|| (MyUtilityClass.isEmpty(mappings.primary) && MyUtilityClass
.isEmpty(mappings.secondary))
|| MyUtilityClass.isEmpty(mappings.tertiary)) {
// log error and return
}
// otherwise extract values from them
String localPAddress = null;
String remotePAddress = null;
if (MyUtilityClass.isNotEmpty(mappings.primary)) {
String localPId = mappings.primary.get(localPath).get(compId);
localPAddress = mappings.tertiary.get(localPath).get(
Integer.parseInt(localPId));
String remotePId = mappings.primary.get(remotePath).get(compId);
remotePAddress = mappings.tertiary.get(remotePath).get(
Integer.parseInt(remotePId));
}
String localSAddress = null;
String remoteSAddress = null;
if (MyUtilityClass.isNotEmpty(mappings.secondary)) {
String localSId = mappings.secondary.get(localPath).get(compId);
localSAddress = mappings.tertiary.get(localPath).get(
Integer.parseInt(localSId));
String remoteSId = mappings.secondary.get(remotePath).get(compId);
remoteSAddress = mappings.tertiary.get(remotePath).get(
Integer.parseInt(remoteSId));
}
// now use - localPAddress, remotePAddress, localSAddress and remoteSAddress
}
}
通过对一级、二级和三级映射的上述健全性和空值检查,应用程序的整体性能(第 95 个百分位)为 4 毫秒。
但是,如果我在没有对主要、次要和三次映射进行任何健全性检查或空值检查的情况下这样做,我会得到 0.87 毫秒的整体性能(第 95 个百分位)。
class Task implements Callable<String> {
public Task() {
}
public String call() throws Exception {
int compId = 100;
String localPath = "hello";
String remotePath = "world";
Mappings mappings = ClientData.getMappings();
String localPId = mappings.primary.get(localPath).get(compId);
String localPAddress = mappings.tertiary.get(localPath).get(Integer.parseInt(localPId));
String remotePId = mappings.primary.get(remotePath).get(compId);
String remotePAddress = mappings.tertiary.get(remotePath).get(Integer.parseInt(remotePId));
String localSId = mappings.secondary.get(localPath).get(compId);
String localSAddress = mappings.tertiary.get(localPath).get(Integer.parseInt(localSId));
String remoteSId = mappings.secondary.get(remotePath).get(compId);
String remoteSAddress = mappings.tertiary.get(remotePath).get(Integer.parseInt(remoteSId));
// now use - localPAddress, remotePAddress, localSAddress and remoteSAddress
}
}
下面是我的 isEmpty 和 isNotEmpty 方法 -
public static boolean isNotEmpty(Object obj) {
return !isEmpty(obj);
}
public static boolean isEmpty(Object obj) {
if (obj == null)
return true;
if (obj instanceof Collection)
return ((Collection<?>) obj).size() == 0;
final String s = String.valueOf(obj).trim();
return s.length() == 0 || s.equalsIgnoreCase("null");
}