~ubuntu-branches/ubuntu/vivid/mkgmap/vivid

« back to all changes in this revision

Viewing changes to test/main/SortTest.java

  • Committer: Package Import Robot
  • Author(s): Andreas Tille
  • Date: 2014-08-13 22:13:41 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20140813221341-i9dzzjuto2o7hfh6
Tags: 0.0.0+svn3333-1
* New upstream version
  Closes: #745097
* add debian/classpath (thanks for the patch to Manfred Stock
  <manfred.stock+debian@gmail.com>)
  Closes: #741596
* d/copyright: DEP5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2014.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 3 or
 
6
 * version 2 as published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
11
 * General Public License for more details.
 
12
 */
 
13
package main;
 
14
 
 
15
import java.nio.charset.Charset;
 
16
import java.text.CollationKey;
 
17
import java.text.Collator;
 
18
import java.text.ParseException;
 
19
import java.text.RuleBasedCollator;
 
20
import java.util.ArrayList;
 
21
import java.util.Collections;
 
22
import java.util.List;
 
23
import java.util.Random;
 
24
 
 
25
import uk.me.parabola.imgfmt.app.srt.Sort;
 
26
import uk.me.parabola.imgfmt.app.srt.SortKey;
 
27
import uk.me.parabola.mkgmap.srt.SrtTextReader;
 
28
 
 
29
/**
 
30
 * Test to compare sorting results and timings between sort keys and collator.
 
31
 *
 
32
 * Also have tested against java7 RuleBasedCollator and the ICU one.
 
33
 *
 
34
 * In general our implementation is fastest by a long way; key based sort 3 times faster, collation
 
35
 * based sort even more so.  The java collator does not result in the same sort as using sort keys.
 
36
 *
 
37
 * I also tried out the ICU collation with mixed results. Could not get the correct desired results with
 
38
 * it.  It was not faster than our implementation for a 1252 cp sort.
 
39
 */
 
40
public class SortTest {
 
41
 
 
42
        private static final int LIST_SIZE = 500000;
 
43
        private Sort sort;
 
44
        private boolean time;
 
45
        private boolean fullOutput;
 
46
        private boolean quiet;
 
47
        private boolean unicode;
 
48
 
 
49
        private void test() throws Exception {
 
50
                sort = SrtTextReader.sortForCodepage(unicode? 65001: 1252);
 
51
 
 
52
                //testPairs();
 
53
 
 
54
                Charset charset = sort.getCharset();
 
55
 
 
56
                Random rand = new Random(21909278L);
 
57
 
 
58
                List<String> list = createList(rand, charset);
 
59
 
 
60
                if (time) {
 
61
                        // Run a few times without output, to warm up
 
62
                        compareLists(sortWithKeys(list), sortWithKeys(list));
 
63
                        compareLists(sortWithCollator(list), sortWithCollator(list));
 
64
                        compareLists(sortWithJavaKeys(list), sortWithJavaKeys(list));
 
65
                        compareLists(sortWithJavaCollator(list), sortWithJavaCollator(list));
 
66
                        // re-create the list to make sure it wasn't too optimised to the data
 
67
                        list = createList(rand, charset);
 
68
                }
 
69
 
 
70
                System.out.println("Compare key sort and collator sort");
 
71
                int n = compareLists(sortWithKeys(list), sortWithCollator(list));
 
72
                System.out.println("N errors " + n);
 
73
 
 
74
                if (!unicode) {
 
75
                        System.out.println("Compare our sort with java sort");
 
76
                        n = compareLists(sortWithKeys(list), sortWithJavaKeys(list));
 
77
                        System.out.println("N errors " + n);
 
78
                }
 
79
 
 
80
                if (time) {
 
81
                        System.out.println("Compare java keys with java collator");
 
82
                        n = compareLists(sortWithJavaKeys(list), sortWithJavaCollator(list));
 
83
                        System.out.println("N errors " + n);
 
84
                }
 
85
        }
 
86
 
 
87
        private List<String> createList(Random rand, Charset charset) {
 
88
                List<String> list = new ArrayList<>();
 
89
 
 
90
                for (int n = 0; n < LIST_SIZE; n++) {
 
91
                        int len = rand.nextInt(6)+1;
 
92
                        if (len < 2)
 
93
                                len = rand.nextInt(5) + 2;
 
94
 
 
95
                        if (unicode) {
 
96
                                char[] c = new char[len];
 
97
                                for (int i = 0; i < len; i++) {
 
98
                                        int ch;
 
99
                                        do {
 
100
                                                if (rand.nextInt(10) > 6)
 
101
                                                        ch = rand.nextInt(6 * 256);
 
102
                                                else
 
103
                                                        ch = rand.nextInt(256);
 
104
                                        } while (reject(rand, ch));
 
105
 
 
106
                                        c[i] = (char) ch;
 
107
                                }
 
108
                                list.add(new String(c));
 
109
                        } else {
 
110
                                byte[] b = new byte[len];
 
111
                                for (int i = 0; i < len; i++) {
 
112
 
 
113
                                        int ch;
 
114
                                        do {
 
115
                                                ch = rand.nextInt(256);
 
116
                                                // reject unassigned. Also low chars most of the time
 
117
                                        } while (reject(rand, ch));
 
118
 
 
119
                                        b[i] = (byte) ch;
 
120
                                }
 
121
                                list.add(new String(b, charset));
 
122
                        }
 
123
                }
 
124
 
 
125
                list = Collections.unmodifiableList(list);
 
126
                return list;
 
127
        }
 
128
 
 
129
        private int compareLists(List<String> r1, List<String> r2) {
 
130
                int count = 0;
 
131
                for (int i = 0; i < LIST_SIZE; i++) {
 
132
                        String s1 = r1.get(i);
 
133
                        String s2 = r2.get(i);
 
134
                        String mark = "";
 
135
                        if (!s1.equals(s2)) {
 
136
                                mark = "*";
 
137
                                count++;
 
138
                        }
 
139
 
 
140
                        if (fullOutput || (!mark.isEmpty() && !quiet))
 
141
                                System.out.printf("%6d |%-10s |%-10s %s\n", i, s1, s2, mark);
 
142
                }
 
143
                return count;
 
144
        }
 
145
 
 
146
        private boolean reject(Random rand, int ch) {
 
147
                switch (ch) {
 
148
                case 0:
 
149
                case ' ':
 
150
                case '\n':case '\r':
 
151
                case 0x81:case 0x8d:case 0x8f:
 
152
                case 0x90:case 0x9d:
 
153
                        return true;
 
154
                }
 
155
                switch (Character.getType(ch)) {
 
156
                case Character.UNASSIGNED:
 
157
                        return true;
 
158
                case Character.CONTROL:
 
159
                        return true;
 
160
                }
 
161
 
 
162
                // Reject low characters most of the time
 
163
                if (ch < 0x20 && rand.nextInt(100) < 95)
 
164
                        return true;
 
165
                if (ch > 255 && rand.nextInt(100) > 99)
 
166
                        return true;
 
167
                return false;
 
168
        }
 
169
 
 
170
        private List<String> sortWithKeys(List<String> list) {
 
171
                long start = System.currentTimeMillis();
 
172
                List<SortKey<String>> keys = new ArrayList<>();
 
173
                for (String s : list) {
 
174
                        SortKey<String> key = sort.createSortKey(s, s);
 
175
                        keys.add(key);
 
176
                }
 
177
                Collections.sort(keys);
 
178
 
 
179
                long end = System.currentTimeMillis();
 
180
 
 
181
                List<String> ret = new ArrayList<>();
 
182
 
 
183
                for (SortKey<String> key : keys) {
 
184
                        ret.add(key.getObject());
 
185
                }
 
186
                System.out.println("time keys: " + (end-start) + "ms");
 
187
                return ret;
 
188
        }
 
189
 
 
190
        private List<String> sortWithCollator(List<String> list) {
 
191
                long start = System.currentTimeMillis();
 
192
                List<String> ret = new ArrayList<>(list);
 
193
                Collections.sort(ret, sort.getCollator());
 
194
                System.out.println("time coll: " + (System.currentTimeMillis() - start) + "ms");
 
195
                return ret;
 
196
        }
 
197
 
 
198
        private List<String> sortWithJavaKeys(List<String> list) {
 
199
 
 
200
                long start = System.currentTimeMillis();
 
201
                List<CollationKey> keys = new ArrayList<>();
 
202
                Collator jcol;
 
203
                try {
 
204
                        jcol = new RuleBasedCollator(getRules(false));
 
205
                } catch (ParseException e) {
 
206
                        e.printStackTrace();
 
207
                        return null;
 
208
                }
 
209
                for (String s : list) {
 
210
                        CollationKey key = jcol.getCollationKey(s);
 
211
                        keys.add(key);
 
212
                }
 
213
                Collections.sort(keys);
 
214
 
 
215
                long end = System.currentTimeMillis();
 
216
 
 
217
                List<String> ret = new ArrayList<>();
 
218
                for (CollationKey key : keys) {
 
219
                        ret.add(key.getSourceString());
 
220
                }
 
221
                System.out.println("time J keys: " + (end - start) + "ms");
 
222
                return ret;
 
223
        }
 
224
 
 
225
        private List<String> sortWithJavaCollator(List<String> list) {
 
226
 
 
227
                long start = System.currentTimeMillis();
 
228
 
 
229
                List<String> out = new ArrayList<>(list);
 
230
                Collator jcol;
 
231
                try {
 
232
                        jcol = new RuleBasedCollator(getRules(false));
 
233
                        jcol.setStrength(Collator.TERTIARY);
 
234
                } catch (ParseException e) {
 
235
                        e.printStackTrace();
 
236
                        return null;
 
237
                }
 
238
 
 
239
                Collections.sort(out, jcol);
 
240
 
 
241
                System.out.println("time J collator: " + (System.currentTimeMillis() - start) + "ms");
 
242
                return out;
 
243
        }
 
244
 
 
245
        private String getRules(boolean forICU) {
 
246
                return "='\u0008'='\u000e'='\u000f'='\u0010'='\u0011'='\u0012'='\u0013'='\u0014'='\u0015'='\u0016'"
 
247
                                + "='\u0017' ='\u0018' = '\u0019' ='\u001a' ='\u001b'= '\u001c' ='\u001d'= '\u001e'= '\u001f' "
 
248
                                + "='\u007f' ='\u00ad'"
 
249
                                + ", '\u0001', '\u0002', '\u0003', '\u0004' ,'\u0005' ,'\u0006', '\u0007'"
 
250
                                + "< '\u0009' < '\n' < '\u000b' < '\u000c' < '\r' < '\u0020','\u00a0'"
 
251
                                + "< '_' < '-' < '–' < '—' < '\u002c' < '\u003b' < ':' < '!' < '¡' < '?' < '¿'"
 
252
                                + "< '.' < '·' "
 
253
                                + ((forICU)? "< \\' ": "< ''' ")
 
254
                                + "< '‘' < '’' < '‚' < '‹' < '›' < '“' < '”' < '„' < '«' < '»' "
 
255
                                + " < '\"' "
 
256
                                + "< '“' < '”' < '„' < '«'< '»' < '(' < ')' "
 
257
                                + "< '[' < ']' < '{' < '}' < '§' < '¶' < '@' < '*' < '/' < '\\' < '&' < '#' < '%'"
 
258
                                + "< '‰' < '†' < '‡' < '•' < '`' < '´' < '^' < '¯' < '¨' < '¸' < 'ˆ' < '°' < '©' < '®'"
 
259
                                + "< '+' < '±' < '÷' < '×' < '\u003c' < '\u003d' < '>' < '¬' < '|' < '¦' < '~' ; '˜' <  '¤'"
 
260
                                + "< '¢' < '$' < '£' < '¥' < '€' < 0 < 1,¹ < 2,² < 3,³ < 4 < 5 < 6 < 7 < 8 < 9"
 
261
                                + "< a,ª,A ; á,Á ; à,À ; â, ; å,Å ; ä,Ä ; ã,Ã"
 
262
                                + "< b,B"
 
263
                                + "< c,C ; ç,Ç"
 
264
                                + "< d,D ; ð,Ð"
 
265
                                + "< e,E ; é,É ; è,È ; ê,Ê ; ë,Ë"
 
266
                                + "< f,F"
 
267
                                + "< ƒ"
 
268
                                + "< g,G"
 
269
                                + "< h,H"
 
270
                                + "< i,I ; í,Í ; ì,Ì ; î,Π; ï,Ï"
 
271
                                + "< j,J"
 
272
                                + "< k,K"
 
273
                                + "< l,L"
 
274
                                + "< m,M"
 
275
                                + "< n,N ; ñ,Ñ"
 
276
                                + "< o,º,O ; ó,Ó ; ò,Ò ; ô,Ô ; ö,Ö ; õ,Õ ; ø,Ø"
 
277
                                + "< p,P"
 
278
                                + "< q,Q"
 
279
                                + "< r,R"
 
280
                                + "< s,S ; š,Š"
 
281
                                + "< t,T"
 
282
                                + "< u,U ; ú,Ú ; ù,Ù ; û,Û ; ü,Ü"
 
283
                                + "< v,V"
 
284
                                + "< w,W"
 
285
                                + "< x,X"
 
286
                                + "< y,Y ; ý,Ý ; ÿ,Ÿ"
 
287
                                + "< z,Z ; ž,Ž"
 
288
                                + "< þ,Þ"
 
289
                                + "< µ"
 
290
                                + "&'1/4'=¼  &'1/2'=½  &'3/4'=¾"
 
291
                                + "&ae = æ &AE = Æ &ss = ß &OE= Œ  &oe= œ  &TM = ™  &'...' = … "
 
292
                                ;
 
293
        }
 
294
 
 
295
        public static void main(String[] args) throws Exception {
 
296
                SortTest sortTest = new SortTest();
 
297
                for (String arg : args) {
 
298
                        switch (arg) {
 
299
                        case "--time":
 
300
                                sortTest.time = true;
 
301
                                break;
 
302
                        case "--full":
 
303
                                sortTest.fullOutput = true;
 
304
                                break;
 
305
                        case "--quiet":
 
306
                                sortTest.quiet = true;
 
307
                                break;
 
308
                        case "--unicode":
 
309
                                sortTest.unicode = true;
 
310
                                break;
 
311
                        }
 
312
                }
 
313
                sortTest.test();
 
314
        }
 
315
}