如果我在地图上进行空检,为什么整体性能降低? [英] Why the overall performance of application degrades if I do null checks on the maps?

查看:165
本文介绍了如果我在地图上进行空检,为什么整体性能降低?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是使用 CountDownLatch 的课程,以确保在这些地图上发生写入时,首次在主,辅助和三级地图上不会发生读取。

Below is my class which uses CountDownLatch to make sure reads are not happening on the primary, secondary and tertiary maps for the first time whenever writes are happening on those maps.

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分钟运行一次。

And below is my background thread class which is only responsible for setting all the three maps (look for parseResponse method below). It runs every 10 minutes.

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);
        }
    }
}

问题陈述:

如果我对我的映射对象和主,二级和三级地图进行了所有类型的空或理性检查,性能会降低很多(不知道为什么)。但是,如果我不做任何理智或空白的检查,表现会非常好。任何人都可以解释我的错误,为什么会发生什么?

If I am doing all sort of null or sanity checks on my mappings object and primary, secondary and tertiary maps, peformance degrades a lot (not sure why). But if I don't do any sanity or null checks, performance comes very good. Can anyone explain me what's wrong and why it happens?

以下是一个例子 -

Below is an example -

我正在使用 ClientData 类来获取我的主线程中的所有映射。如下所示,我正在做各种健康检查,以确保映射 mappings.primary mappings.secondary mappings.tertiary 不为空。如果它们是空的,那么记录错误并返回

I am using ClientData class to get all the mappings in my main thread. As you can see below, I am doing all sort of sanity checks to make sure mappings, mappings.primary, mappings.secondary and mappings.tertiary are not empty. If they are empty, then log an error and return

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 ms。

With the above sanity and null checks on primary, secondary and tertiary mappings, overall performance (95th percentile) of application comes as 4 ms.

但是,如果我这样做没有任何理智检查或对主,次和三级映射的空白检查,我得到总体维度(第95百分位数)为0.87 ms。

But if I do it like this without any sanity checks or null checks on primary, secondary and tertiary mappings, I get overall perforamnce (95th percentile) as 0.87 ms.

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方法 -

Below is my isEmpty and isNotEmpty method -

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");
}


推荐答案

到这一点这对于一些复杂的对象和他们很重的#toString()方法来说可能是昂贵的:

See how often your code gets to this point. This can be expensive with some complex objects and their heavy #toString() methods:

final String s = String.valueOf(obj).trim();

此外,它会在您的测试计数时创建可能导致垃圾收集的临时垃圾。

Also it creates temporary garbage that might cause Garbage Collection while your test is counting.

这篇关于如果我在地图上进行空检,为什么整体性能降低?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆