001    /****************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one   *
003     * or more contributor license agreements.  See the NOTICE file *
004     * distributed with this work for additional information        *
005     * regarding copyright ownership.  The ASF licenses this file   *
006     * to you under the Apache License, Version 2.0 (the            *
007     * "License"); you may not use this file except in compliance   *
008     * with the License.  You may obtain a copy of the License at   *
009     *                                                              *
010     *   http://www.apache.org/licenses/LICENSE-2.0                 *
011     *                                                              *
012     * Unless required by applicable law or agreed to in writing,   *
013     * software distributed under the License is distributed on an  *
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015     * KIND, either express or implied.  See the License for the    *
016     * specific language governing permissions and limitations      *
017     * under the License.                                           *
018     ****************************************************************/
019    
020    package org.apache.james.mime4j;
021    
022    import java.io.ByteArrayInputStream;
023    import java.io.ByteArrayOutputStream;
024    import java.io.IOException;
025    import java.io.InputStream;
026    
027    import org.apache.james.mime4j.codec.CodecUtil;
028    import org.apache.james.mime4j.dom.Header;
029    import org.apache.james.mime4j.dom.MessageBuilder;
030    import org.apache.james.mime4j.message.DefaultMessageBuilder;
031    import org.apache.james.mime4j.message.SimpleContentHandler;
032    import org.apache.james.mime4j.parser.AbstractContentHandler;
033    import org.apache.james.mime4j.parser.ContentHandler;
034    import org.apache.james.mime4j.parser.MimeStreamParser;
035    import org.apache.james.mime4j.storage.DefaultStorageProvider;
036    import org.apache.james.mime4j.storage.MemoryStorageProvider;
037    import org.apache.james.mime4j.stream.BodyDescriptor;
038    import org.apache.james.mime4j.stream.EntityState;
039    import org.apache.james.mime4j.stream.MimeTokenStream;
040    
041    public class LongMultipartReadBench {
042    
043        public static void main(String[] args) throws Exception {
044    
045            byte[] content = loadMessage("long-multipart.msg");
046            if (content == null) {
047                System.err.println("Test message not found");
048                return;
049            }
050    
051            int testNumber = args.length > 0 ? Integer.parseInt(args[0]) : 0;
052    
053            Test test = createTest(testNumber);
054            if (test == null) {
055                System.err.println("No such test: " + testNumber);
056                return;
057            }
058    
059            int repetitions = args.length > 1 ? Integer.parseInt(args[1]) : 25000;
060    
061            System.out.println("Multipart message read.");
062            System.out.println("No of repetitions: " + repetitions);
063            System.out.println("Content length: " + content.length);
064            System.out.println("Test: " + test.getClass().getSimpleName());
065    
066            System.out.print("Warmup... ");
067            long t0 = System.currentTimeMillis();
068            while (System.currentTimeMillis() - t0 < 1500) {
069                test.run(content, 10);
070            }
071            System.out.println("done");
072    
073            System.out.println("--------------------------------");
074    
075            long start = System.currentTimeMillis();
076            test.run(content, repetitions);
077            long finish = System.currentTimeMillis();
078    
079            double seconds = (finish - start) / 1000.0;
080            double mb = content.length * repetitions / 1024.0 / 1024;
081            System.out.printf("Execution time: %f sec\n", seconds);
082            System.out.printf("%.2f messages/sec\n", repetitions / seconds);
083            System.out.printf("%.2f mb/sec\n", mb / seconds);
084        }
085    
086        private static Test createTest(int testNumber) {
087            switch (testNumber) {
088            case 0:
089                return new MimeTokenStreamTest();
090            case 1:
091                return new AbstractContentHandlerTest();
092            case 2:
093                return new SimpleContentHandlerTest();
094            case 3:
095                return new MessageTest();
096            default:
097                return null;
098            }
099        }
100    
101        private static byte[] loadMessage(String resourceName) throws IOException {
102            ClassLoader cl = LongMultipartReadBench.class.getClassLoader();
103    
104            ByteArrayOutputStream outstream = new ByteArrayOutputStream();
105            InputStream instream = cl.getResourceAsStream(resourceName);
106            if (instream == null) {
107                return null;
108            }
109            try {
110                CodecUtil.copy(instream, outstream);
111            } finally {
112                instream.close();
113            }
114    
115            return outstream.toByteArray();
116        }
117    
118        private interface Test {
119            void run(byte[] content, int repetitions) throws Exception;
120        }
121    
122        private static final class MimeTokenStreamTest implements Test {
123            public void run(byte[] content, int repetitions) throws Exception {
124                MimeTokenStream stream = new MimeTokenStream();
125                for (int i = 0; i < repetitions; i++) {
126                    stream.parse(new ByteArrayInputStream(content));
127                    for (EntityState state = stream.getState(); state != EntityState.T_END_OF_STREAM; state = stream
128                            .next()) {
129                    }
130                }
131            }
132        }
133    
134        private static final class AbstractContentHandlerTest implements Test {
135            public void run(byte[] content, int repetitions) throws Exception {
136                ContentHandler contentHandler = new AbstractContentHandler() {
137                };
138    
139                for (int i = 0; i < repetitions; i++) {
140                    MimeStreamParser parser = new MimeStreamParser();
141                    parser.setContentHandler(contentHandler);
142                    parser.parse(new ByteArrayInputStream(content));
143                }
144            }
145        }
146    
147        private static final class SimpleContentHandlerTest implements Test {
148            public void run(byte[] content, int repetitions) throws Exception {
149                ContentHandler contentHandler = new SimpleContentHandler() {
150                    @Override
151                    public void body(BodyDescriptor bd, InputStream is)
152                            throws IOException {
153                        byte[] b = new byte[4096];
154                        while (is.read(b) != -1);
155                    }
156    
157                    @Override
158                    public void headers(Header header) {
159                    }
160                };
161    
162                for (int i = 0; i < repetitions; i++) {
163                    MimeStreamParser parser = new MimeStreamParser();
164                    parser.setContentDecoding(true);
165                    parser.setContentHandler(contentHandler);
166                    parser.parse(new ByteArrayInputStream(content));
167                }
168            }
169        }
170    
171        private static final class MessageTest implements Test {
172            public void run(byte[] content, int repetitions) throws Exception {
173                DefaultStorageProvider.setInstance(new MemoryStorageProvider());
174                MessageBuilder builder = new DefaultMessageBuilder();
175    
176                for (int i = 0; i < repetitions; i++) {
177                    builder.parseMessage(new ByteArrayInputStream(content));
178                }
179            }
180        }
181    
182        /*
183        // requires mail.jar and activation.jar to be present
184        private static final class MimeMessageTest implements Test {
185            public void run(byte[] content, int repetitions) throws Exception {
186                for (int i = 0; i < repetitions; i++) {
187                    MimeMessage mm = new MimeMessage(null, new ByteArrayInputStream(content));
188                    Multipart multipart = (Multipart) mm.getContent();
189                    multipart.getCount(); // force parsing
190                }
191            }
192        }
193        */
194    
195    }