Ticket #23468: 23468.2.patch

File 23468.2.patch, 6.4 KB (added by taylor.smock, 19 months ago)

Alternative to attachment:23468.patch where AlphanumComparator is optimized

  • src/org/openstreetmap/josm/tools/AlphanumComparator.java

    Subject: [PATCH] #23468: Performance issue with Validator tree window
    ---
    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/tools/AlphanumComparator.java b/src/org/openstreetmap/josm/tools/AlphanumComparator.java
    a b  
    7474     * @return alphanum chunk found at given position
    7575     */
    7676    private static String getChunk(String s, int slength, int marker) {
    77         StringBuilder chunk = new StringBuilder();
     77        final int startMarker = marker;
    7878        char c = s.charAt(marker);
    79         chunk.append(c);
    8079        marker++;
    8180        if (Character.isDigit(c)) {
    8281            while (marker < slength) {
     
    8483                if (!Character.isDigit(c)) {
    8584                    break;
    8685                }
    87                 chunk.append(c);
    8886                marker++;
    8987            }
    9088        } else {
     
    9391                if (Character.isDigit(c)) {
    9492                    break;
    9593                }
    96                 chunk.append(c);
    9794                marker++;
    9895            }
    9996        }
    100         return chunk.toString();
     97        return s.substring(startMarker, marker);
    10198    }
    10299
    103     @Override
    104     public int compare(String s1, String s2) {
    105         if (s1 == null && s2 == null) {
    106             return 0;
    107         } else if (s1 == null) {
    108             return -1;
    109         } else if (s2 == null) {
    110             return 1;
     100    /**
     101     * Check if a string is ASCII only
     102     * @param string The string to check
     103     * @param stringLength The length of the string (for performance reasons)
     104     * @return {@code true} if the string only contains ascii characters
     105     */
     106    private static boolean isAscii(String string, int stringLength) {
     107        for (int i = 0; i < stringLength; i++) {
     108            char c = string.charAt(i);
     109            if (c >= 128) {
     110                return false;
     111            }
    111112        }
     113        return true;
     114    }
    112115
    113         int thisMarker = 0;
    114         int thatMarker = 0;
    115         int s1Length = s1.length();
    116         int s2Length = s2.length();
    117 
    118         while (thisMarker < s1Length && thatMarker < s2Length) {
    119             String thisChunk = getChunk(s1, s1Length, thisMarker);
    120             thisMarker += thisChunk.length();
    121 
    122             String thatChunk = getChunk(s2, s2Length, thatMarker);
    123             thatMarker += thatChunk.length();
    124 
    125             // If both chunks contain numeric characters, sort them numerically
    126             int result;
    127             if (Character.isDigit(thisChunk.charAt(0)) && Character.isDigit(thatChunk.charAt(0))) {
    128                 // Simple chunk comparison by length.
    129                 int thisChunkLength = thisChunk.length();
    130                 result = thisChunkLength - thatChunk.length();
    131                 // If equal, the first different number counts
    132                 if (result == 0) {
    133                     for (int i = 0; i < thisChunkLength; i++) {
    134                         result = thisChunk.charAt(i) - thatChunk.charAt(i);
    135                         if (result != 0) {
    136                             return result;
    137                         }
    138                     }
    139                 }
    140             } else {
    141                 // Instantiate the collator
    142                 Collator compareOperator = Collator.getInstance();
    143                 // Compare regardless of accented letters
    144                 compareOperator.setStrength(Collator.SECONDARY);
    145                 result = compareOperator.compare(thisChunk, thatChunk);
    146             }
     116    /**
     117     * Compare two string chunks
     118     * @param thisChunk The first chunk to compare
     119     * @param thisChunkLength The length of the first chunk (for performance reasons)
     120     * @param thatChunk The second chunk to compare
     121     * @param thatChunkLength The length of the second chunk (for performance reasons)
     122     * @return The {@link Comparator} result
     123     */
     124    private static int compareChunk(String thisChunk, int thisChunkLength, String thatChunk, int thatChunkLength) {
     125        int result;
     126        if (Character.isDigit(thisChunk.charAt(0)) && Character.isDigit(thatChunk.charAt(0))) {
     127            // Simple chunk comparison by length.
     128            result = thisChunkLength - thatChunk.length();
     129            // If equal, the first different number counts
     130            if (result == 0) {
     131                for (int i = 0; i < thisChunkLength; i++) {
     132                    result = thisChunk.charAt(i) - thatChunk.charAt(i);
     133                    if (result != 0) {
     134                        return result;
     135                    }
     136                }
     137            }
     138        } else {
     139            // Check if both chunks are ascii only
     140            if (isAscii(thisChunk, thisChunkLength) && isAscii(thatChunk, thatChunkLength)) {
     141                return thisChunk.compareTo(thatChunk);
     142            }
     143            // Instantiate the collator
     144            Collator compareOperator = Collator.getInstance();
     145            // Compare regardless of accented letters
     146            compareOperator.setStrength(Collator.SECONDARY);
     147            result = compareOperator.compare(thisChunk, thatChunk);
     148        }
     149        return result;
     150    }
     151
     152    @Override
     153    public int compare(String s1, String s2) {
     154        if (s1 == null && s2 == null) {
     155            return 0;
     156        } else if (s1 == null) {
     157            return -1;
     158        } else if (s2 == null) {
     159            return 1;
     160        }
     161
     162        int thisMarker = 0;
     163        int thatMarker = 0;
     164        int s1Length = s1.length();
     165        int s2Length = s2.length();
     166
     167        while (thisMarker < s1Length && thatMarker < s2Length) {
     168            final String thisChunk = getChunk(s1, s1Length, thisMarker);
     169            final int thisChunkLength = thisChunk.length();
     170            thisMarker += thisChunkLength;
     171
     172            String thatChunk = getChunk(s2, s2Length, thatMarker);
     173            final int thatChunkLength = thatChunk.length();
     174            thatMarker += thatChunkLength;
     175
     176            // If both chunks contain numeric characters, sort them numerically
     177            int result = compareChunk(thisChunk, thisChunkLength, thatChunk, thatChunkLength);
    147178
    148179            if (result != 0) {
    149180                return result;