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 }