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
020package org.apache.james.mime4j;
021
022import java.io.ByteArrayInputStream;
023import java.io.ByteArrayOutputStream;
024import java.io.IOException;
025import java.io.InputStream;
026
027import org.apache.james.mime4j.codec.CodecUtil;
028import org.apache.james.mime4j.dom.Header;
029import org.apache.james.mime4j.dom.MessageBuilder;
030import org.apache.james.mime4j.message.DefaultMessageBuilder;
031import org.apache.james.mime4j.message.SimpleContentHandler;
032import org.apache.james.mime4j.parser.AbstractContentHandler;
033import org.apache.james.mime4j.parser.ContentHandler;
034import org.apache.james.mime4j.parser.MimeStreamParser;
035import org.apache.james.mime4j.storage.DefaultStorageProvider;
036import org.apache.james.mime4j.storage.MemoryStorageProvider;
037import org.apache.james.mime4j.stream.BodyDescriptor;
038import org.apache.james.mime4j.stream.EntityState;
039import org.apache.james.mime4j.stream.MimeTokenStream;
040
041public 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}