简体   繁体   中英

Efficiency of StringBuilder when Modifying String if using toString in Java

I've been tasked with optimizing an application developed with the Cognos SDK that queries the Content Store for all packages and then writes them to a SQL database. The application was written by my predecessor in the role and does some interesting things... it had several manual system.GC calls that I disabled, along with a System.wait(2000) that was in one of the loops. It currently will run on a server architecture much faster, but if one tries to run it on a normal client it will crash due to a heap error. So digging in, I found that there are tons upon tons of strings in it. The obvious answer was to change to StringBuilder, but if I'm having to use a lot of "toString" in it am I really saving any memory? In theory there should be a method for each of these string operators, but I'm somewhat reluctant to mess with some logic on the application and I'm having to look up how to do each specifically. Apologies if this has been asked before, but after looking around for an hour I wasn't able to find one.

(Small aside : The whole method has a cognitive complexity of 174, but a fair amount of that is cognos specific and I have no idea where to start with reducing that.)

Here's an example of what I've changed (This loop is run several times on ~450000 lines of input). Also, I changed "express" to a StringBuilder with an initial value of "" shortly before the for loop this is part of:

                        if (element.hasAttribute("expression") && element.getAttribute("expression") != "") {
                        formula = element.getAttribute("expression");
                        for (int k = 0; k < formula.length(); k++) {
                            if (formula.charAt(k) == '<')
                                exSearch++;
                            if (exSearch == 0)
                                express.append(formula.charAt(k));
                            if (formula.charAt(k) == '>')
                                exSearch--;
                        }

                        express.replace(0, express.length(),express.toString().replaceAll("\\s", ""));
                        express.replace(0, express.length(),express.toString().replaceAll("&gt;", "<"));
                        express.replace(0, express.length(),express.toString().replaceAll("&lt;", ">"));
                        express.replace(0, express.length(),express.toString().replaceAll("&apos;", "'"));
                        express.replace(0, express.length(),express.toString().replaceAll("&amp;", "&"));
                    }
                        if (express.length() > 1000) {
                        express.replace(0, express.length(),express.toString().substring(0, 995) + "..." );
                    }
                    table = "CALCULATION";
                    tableLoc = "CALCULATION";
                    inBrackets = false;

                    if (express.indexOf("[")== 0) {
                        String[] temp = express.toString().split("].");
                        if (temp.length > 1 && temp[temp.length - 1].length() > 1) {
                            table = temp[temp.length - 2].substring(1);
                            tableLoc = temp[temp.length - 1].substring(1, temp[temp.length - 1].length() - 1);
                        }
                    }

Original :

    if (element.hasAttribute("expression") && element.getAttribute("expression") != "") {
                        formula = element.getAttribute("expression");
                        for (int k = 0; k < formula.length(); k++) {
                            if (formula.charAt(k) == '<')
                                exSearch++;
                            if (exSearch == 0)
                                express += formula.charAt(k);
                            if (formula.charAt(k) == '>')
                                exSearch--;
                        }
                        express = express.replaceAll("\\s", "");
                        express = express.replaceAll("&gt;", "<");
                        express = express.replaceAll("&lt;", ">");
                        express = express.replaceAll("&apos;", "'");
                        express = express.replaceAll("&amp;", "&");
                    }
                    if (express.length() > 1000) {
                        express = express.substring(0, 995) + "...";
                    }

                    table = "CALCULATION";
                    tableLoc = "CALCULATION";
                    inBrackets = false;

                    if (express.startsWith("[")) {
                        String[] temp = express.split("].");
                        if (temp.length > 1 && temp[temp.length - 1].length() > 1) {
                            table = temp[temp.length - 2].substring(1);
                            tableLoc = temp[temp.length - 1].substring(1, temp[temp.length - 1].length() - 1);
                        }
                    }

Yes, replacing string arithmetic with StringBuilder will have an impact on memory and performance. But your new code is still doing a lot of string arithmetic with all the toString().replaceAll and toString().split and toString().substring() calls. Get rid of all of them. They are all costly and totally unnecessary.

Do not do any operations on strings, do them all on a single StringBuilder instance.

As for running out of memory, most of those strings are garbage collected so it's not clear this will solve the memory problem. But it will definitely improve things.

please for the love of god transform

  express = express.replaceAll("\\s", "");
  express = express.replaceAll("&gt;", "<");
  express = express.replaceAll("&lt;", ">");
  express = express.replaceAll("&apos;", "'");
  express = express.replaceAll("&amp;", "&");

into

express = express.replace("\\s", "").replace("&gt;", "<").replace("&lt;", ">").replace("&apos;", "'").replace("&amp;", "&")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM