On Nov 5, 2007 11:21 AM, Stefano Bagnara <[EMAIL PROTECTED]> wrote:
> Robert Burrell Donkin ha scritto:
> > On Nov 4, 2007 10:57 PM, Stefano Bagnara <[EMAIL PROTECTED]> wrote:
> >> Robert Burrell Donkin ha scritto:
> >>> MimeMessages are expensive to create.
> >> I see you wrote this twice in 2 messages: have you measured it? I never
> >> ran a real benchmark but I know MimeMessage sources and the way we
> >> subclassed/wrapped it and I don't see what is expensive there.
> >>
> >> I just want to go deeper in this because you used it as the "cause" for
> >> "action needed" in 2 recent proposals. While I agree that javamail is
> >> far from being a good server side api I don't think that MimeMessages
> >> are expensive: I can see problems in the way they expose their content,
> >> but not in their "cost" (either in term of memory or cpu).
> >
> > TorqueMimeMessage is created by loading all the header rows from the
> > database plus the byte content from the data and then using a
> > MimeMessage to parse the bytes. this is a slow operation and consumes
> > a lot of memory especially for big messages.
> >
> > the MimeMessage API is unsuitable for independent implementations. if
> > it were a lighter interface then it might have been possible to expose
> > only those quantities of data which were requested. the design of the
> > API means that this isn't realistic.
>
> I don't agree. It is more difficult than simply implementing interfaces,
> but it is not so unrealistic.

it's unrealistic to specify a MailboxAPI that's so difficult that no
one else will attempt a performant implementation. IMAP is a difficult
protocol. insisting that data is accessed through MimeMessage just
increases the work required. JAMES IMAP has seen many developers
start, try and then fail. we need to keep things as simple as
possible.

the other problem is that the IMAP protocol cannot be performantly
implemented by use of MimeMessage alone - additional requirements
beyond the standard javamail specification would be necessary. in
particular, a number of the poorly defined optional methods *must*
return accurate data.

> If you look at our MimeMessageWrapper you can see we can override almost
> anything from the original MimeMessage by simply extending it. In fact
> in MimeMessageWrapper we can lazily load both headers and the body and
> we could even cache the structure of the message or use mime4j to do the
> real parsing.

of course it is possible to create an implementation that just
overrides every method. the problem is creating an implementation that
complies with all the designed contracts yet at the same time
satisfies all the IMAP requirements.

> Maybe there is some limitation in the objects we can store to
> MimeMessage that I can't think about right now, but they are not (IMHO)
> the above. Just look at MimeMessage source code and you will find that
> it is not an heavyweight object as you describe it.

i describe it as heavyweight since:

1. it's not an interface and uses inheritance rather than delegation
2. it does too many jobs bad
3. it has too many methods

> Can we take a concrete case where MimeMessage is bloated and we can't
> live with it? I don't like javamail too much, but I also don't like FUD
> based on a common criticism made to javamail.
>
> Here is a list of methods from MimeMessage.
>
> // header helpers
> Address[] getFrom()
> void setFrom(Address address)
> void setFrom()
> void addFrom(Address[] addresses)
> Address getSender()
> void setSender(Address address)
> Address[] getRecipients(Message.RecipientType type)
> Address[] getAllRecipients()
> void setRecipients(Message.RecipientType type, Address[] addresses)
> void setRecipients(Message.RecipientType type, String addresses)
> void addRecipients(Message.RecipientType type, Address[] addresses)
> void addRecipients(Message.RecipientType type, String addresses)
> Address[] getReplyTo()
> void setReplyTo(Address[] addresses)
> String getSubject()
> void setSubject(String subject)
> void setSubject(String subject, String charset)
> Date getSentDate()
> void setSentDate(Date d)
> Date getReceivedDate()
> int getSize()
> int getLineCount()
> String getContentType()
> boolean isMimeType(String mimeType)
> String getDisposition()
> void setDisposition(String disposition)
> String getEncoding()
> String getContentID()
> void setContentID(String cid)
> String getContentMD5()
> void setContentMD5(String md5)
> String getDescription()
> void setDescription(String description)
> void setDescription(String description, String charset)
> String[] getContentLanguage()
> void setContentLanguage(String[] languages)
> String getMessageID()
> String getFileName()
> void setFileName(String filename)
>
> // content handling
> InputStream getInputStream() throws IOException
> InputStream getRawInputStream()
> DataHandler getDataHandler()
> Object getContent() throws IOException
> synchronized void setDataHandler(DataHandler dh)
> void setContent(Object o, String type)
> void setText(String text)
> void setText(String text, String charset)
> void setText(String text, String charset, String subtype)
> void setContent(Multipart mp)
> Message reply(boolean replyToAll)
> void writeTo(OutputStream os)
> void writeTo(OutputStream os, String[] ignoreList)
>
> // delegation from InternetHeaders:
> String[] getHeader(String name)
> String getHeader(String name, String delimiter)
> void setHeader(String name, String value)
> void addHeader(String name, String value)
> void removeHeader(String name)
> Enumeration getAllHeaders()
> Enumeration getMatchingHeaders(String[] names)
> Enumeration getNonMatchingHeaders(String[] names)
> void addHeaderLine(String line)
> Enumeration getAllHeaderLines()
> Enumeration getMatchingHeaderLines(String[] names)
> Enumeration getNonMatchingHeaderLines(String[] names)
>
> // flags
> synchronized Flags getFlags()
> synchronized boolean isSet(Flags.Flag flag)
> synchronized void setFlags(Flags flag, boolean set)
> void saveChanges()

thanks for demonstrating my point!

an implementor is forced to override a lot of methods

> In the end they make sense to me, most of them are helpers to simplify
> some header access. In MimeMessageWrapper you can already see that I
> added some check to lazy load headers/body depending on the called
> methods. I also remember I disabled lazy loading of the headers because
> of a bug, but if this is the only performance issue we can try to fix i

there are *many* performance issues

> I guess the key part you refer to is the content handling part.
>
> I don't see "weird" methods but the DataHandler stuff from the
> activation framework (JAF).
>
> The DataHandler (as always in javamail) is not an interface but a class
> and unlike MimeMessage it expose much less to subclasses (it contains
> many private fields).
>
> If you think the DataHandler is the key weakness of MimeMessage I can
> investigate further to understand how we can optimize things, but before
> working on this I'd like to know if this is the case or if the simple
> use of Enumeration and primitive arrays is already something that make
> you discard this technology (or if it is something else).

i agree that use of JAF is a key mistake but it's not the only one

the API is (in places) poorly defined or optional. some of these
poorly defined, optional APIs are crucial for IMAP

- robert

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to