001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.schematic.internal.document;
017
018import static org.junit.Assert.assertNotNull;
019import static org.junit.Assert.assertTrue;
020import java.io.ByteArrayInputStream;
021import java.io.ByteArrayOutputStream;
022import java.io.IOException;
023import java.io.InputStream;
024import java.io.InputStreamReader;
025import java.io.Reader;
026import java.io.StringReader;
027import java.util.concurrent.atomic.AtomicReference;
028import org.junit.After;
029import org.junit.Before;
030import org.junit.Ignore;
031import org.junit.Test;
032import org.modeshape.schematic.document.Document;
033
034@Ignore
035public class JsonPerformanceTest {
036
037    protected JsonReader reader;
038    protected boolean print;
039
040    @Before
041    public void beforeTest() {
042        reader = new JsonReader();
043    }
044
045    @After
046    public void afterTest() {
047        reader = null;
048        gc();
049    }
050
051    @Test
052    public void shouldReadLargeTestDocumentWithoutDateMatching() throws Exception {
053        testReadingJson(getLargeTestData(), 200, false, false);
054    }
055
056    @Test
057    public void shouldReadLargeTestDocumentWithDateMatching() throws Exception {
058        testReadingJson(getLargeTestData(), 200, false, true);
059    }
060
061    @Test
062    public void shouldReadLargeTestDocumentWithoutDataMatchingUsingJsonSimple() throws Exception {
063        testReadingJsonWithJsonSimple(getLargeTestData(), 200, false);
064    }
065
066    @Test
067    public void shouldReadSmallTestDocumentWithoutDateMatching() throws Exception {
068        testReadingJson(getSmallTestData(), 200, false, false);
069    }
070
071    @Test
072    public void shouldReadSmallTestDocumentWithDateMatching() throws Exception {
073        testReadingJson(getSmallTestData(), 200, false, true);
074    }
075
076    @Test
077    public void shouldReadSmallTestDocumentWithoutDataMatchingUsingJsonSimple() throws Exception {
078        testReadingJsonWithJsonSimple(getSmallTestData(), 200, false);
079    }
080
081    @Test
082    public void shouldReadSmallTestDocumentToAndFromBson() throws Exception {
083        testReadingJsonThenWritingBsonThenReadingBson(getSmallTestData(), 200, false, true);
084    }
085    
086    @Test
087    public static String getLargeTestData() throws Exception {
088        String result = read("sample-large-performance.json");
089        assertTrue(result.length() != 0);
090        return result;
091    }
092    
093    @Test
094    public static String getSmallTestData() throws Exception {
095        String result = read("sample-small-performance.json");
096        assertTrue(result.length() != 0);
097        return result;
098    }
099
100    private static String read( String resourcePath ) throws IOException {
101        return read(JsonPerformanceTest.class.getClassLoader().getResourceAsStream(resourcePath));
102    }
103
104    private static String read( InputStream stream ) throws IOException {
105        return read(new InputStreamReader(stream));
106    }
107
108    private static String read( Reader reader ) throws IOException {
109        if (reader == null) return "";
110        StringBuilder sb = new StringBuilder();
111        try {
112            int numRead = 0;
113            char[] buffer = new char[1024];
114            while ((numRead = reader.read(buffer)) > -1) {
115                sb.append(buffer, 0, numRead);
116            }
117        } finally {
118            reader.close();
119        }
120        return sb.toString();
121    }
122
123    private static void gc() {
124        try {
125            Thread.sleep(500L);
126        } catch (InterruptedException ie) {
127        }
128        System.gc();
129        try {
130            Thread.sleep(500L);
131        } catch (InterruptedException ie) {
132        }
133    }
134
135    private static void runTest( String message,
136                                 int loops,
137                                 int testDataLength,
138                                 boolean print,
139                                 Runnable function ) {
140        assert loops > 0;
141        // Run several times to warm up ...
142        for (int i = 0; i != 3; ++i) {
143            function.run();
144        }
145        long stop = 0L;
146        long start = System.nanoTime();
147        try {
148            for (int i = 0; i != loops; ++i) {
149                function.run();
150            }
151        } finally {
152            stop = System.nanoTime();
153        }
154        if (print) {
155            while (message.length() < 60)
156                message = message + " ";
157            System.out.print(message + " -- data length: " + testDataLength);
158            System.out.print(" -- average time: ");
159            double delta = (stop - start) / (loops + 0D);
160            String unit = "nanos";
161            if (delta > 1000.0) {
162                delta /= 1000000;
163                unit = "millis";
164            }
165            System.out.println(delta + " " + unit);
166        }
167    }
168
169    protected void testReadingJson( final String testData,
170                                    int numberOfRuns,
171                                    final boolean getValue,
172                                    final boolean introspectStringValues ) throws Exception {
173        assertNotNull(testData);
174        final JsonReader reader = new JsonReader();
175        final AtomicReference<Exception> error = new AtomicReference<Exception>();
176        final String key = "key";
177        runTest("JsonReader.read(String," + introspectStringValues + ")", numberOfRuns, testData.length(), print, new Runnable() {
178            @Override
179            public void run() {
180                try {
181                    Document doc = reader.read(testData, introspectStringValues);
182                    if (getValue) doc.get(key);
183                } catch (Exception t) {
184                    error.compareAndSet(null, t);
185                }
186            }
187        });
188        if (error.get() != null) throw error.get();
189    }
190
191    protected void testReadingJsonWithJsonSimple( final String testData,
192                                                  int numberOfRuns,
193                                                  final boolean getValue ) throws Exception {
194        final org.json.simple.parser.JSONParser parser = new org.json.simple.parser.JSONParser();
195        final AtomicReference<Exception> error = new AtomicReference<Exception>();
196        final String key = "key";
197        runTest("org.json.simple.parser.JSONParser().parse(Reader)", numberOfRuns, testData.length(), print, new Runnable() {
198            @Override
199            public void run() {
200                try {
201                    org.json.simple.JSONObject obj = (org.json.simple.JSONObject)parser.parse(new StringReader(testData));
202                    if (getValue) obj.get(key);
203                } catch (Exception t) {
204                    error.compareAndSet(null, t);
205                }
206            }
207        });
208        if (error.get() != null) throw error.get();
209    }
210
211    protected void testReadingJsonThenWritingBsonThenReadingBson( final String testData,
212                                                                  int numberOfRuns,
213                                                                  final boolean getValue,
214                                                                  final boolean introspectStringValues ) throws Exception {
215        assertNotNull(testData);
216        // Read the JSON into in-memory ...
217        Document doc = new JsonReader().read(testData, introspectStringValues);
218
219        // Write the in-memory out to BSON ...
220        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
221        new BsonWriter().write(doc, bytes);
222        final byte[] bsonBytes = bytes.toByteArray();
223
224        final BsonReader bsonReader = new BsonReader();
225        final AtomicReference<Exception> error = new AtomicReference<Exception>();
226        final String key = "key";
227        runTest("BsonReader.read(InputStream)", numberOfRuns, testData.length(), print, new Runnable() {
228            @Override
229            public void run() {
230                try {
231                    ByteArrayInputStream input = new ByteArrayInputStream(bsonBytes);
232                    Document doc = bsonReader.read(input);
233                    doc.get(key);
234                } catch (Exception t) {
235                    error.compareAndSet(null, t);
236                }
237            }
238        });
239        if (error.get() != null) throw error.get();
240    }
241}