Thanks for the help.  I have done the following as per your 3 suggestions, but 
have noticed no increase in speed.  Any other ideas, or can you point out 
something I am doing wrong?

1) I already had my compiler set to build for release and optimize for speed.

2) I have now implemented a callback class, but still need the output as a 
string to pass back to java, so I am still wrapping a stringstream in the 
callback class - is this still bad for memory allocation?  If so, what stream 
do I use as I don't want IO to file (unless I have to), and I don't know how to 
get a string from the other streams.  I have changed my transform method to use 
a compiled stylesheet and a XalanDefaultParsedSource.  Here is the code for my 
callback handler:

#if defined(XALAN_CLASSIC_IOSTREAMS)
#include <sstream.h>
#else
#include <sstream>
#endif

class StringCallbackHandler
{
public:

        StringCallbackHandler(std::stringstream* thestream) :
                xmlStream(thestream)
        {
                assert(xmlStream != 0);
        }

        CallbackSizeType write(const char* theData, CallbackSizeType theLength) 
{
                xmlStream->write(theData, theLength);
                return theLength;
        }

        void flush() {
                xmlStream->flush();
        }

private:

        std::stringstream* xmlStream;
};



// These functions need to have C linkage, so surround them with an extern C 
block...
extern "C"
{

// This is the write callback function, which casts the handle
// to the appropriate type, then calls the write() member function
// on the CallbackHandler class.
CallbackSizeType
writeCallback(
                        const char*                     theData,
                        CallbackSizeType        theLength,
                        void*                           theHandle)
{
#if defined(XALAN_OLD_STYLE_CASTS)
        return ((StringCallbackHandler*)theHandle)->write(theData, theLength);
#else
        return 
reinterpret_cast<StringCallbackHandler*>(theHandle)->write(theData, theLength);
#endif
}

// This is the flush callback function, which casts the handle
// to the appropriate type, then calls the flush() member function
// on the CallbackHandler class.
void
flushCallback(void*     theHandle)
{
#if defined(XALAN_OLD_STYLE_CASTS)
        ((StringCallbackHandler*)theHandle)->flush();
#else
        reinterpret_cast<StringCallbackHandler*>(theHandle)->flush();
#endif
}

}

and some code from my transform method:

                stringstream theOutXMLStream;
                // CallbackHandler writes incrementally, saving on memory 
allocation
                StringCallbackHandler theHandler(&theOutXMLStream);
                // XalanParsedSource required to use callback on compiled 
stylesheet
                XSLTInputSource * theInputSource;

                // Do the transform.
                time_t currenttime = time(NULL);    
                printf( "Prepping Input %ld\n", currenttime ); 
                ifstream testfile(input);
                if ( testfile.is_open() ) {
                        // input is filepath
                        testfile.close();
                        theInputSource = new XSLTInputSource(input);
                        currenttime = time(NULL);  
                        printf( "Start Transforming File %ld\n", currenttime ); 
                } else {
                        // input was actual xml string
                        istrstream theInXMLStream(input, strlen(input));
                        theInputSource = new XSLTInputSource(theInXMLStream);
                        currenttime = time(NULL);  
                        printf( "Start Transforming String %ld\n", currenttime 
); 
                }
                XalanDefaultParsedSource theParsedSource(*theInputSource);
                //result = theXalanTransformer.transform(theInputSource, 
stylesheetSource, theOutXMLStream);
                //result = theXalanTransformer->transform(theInputSource, 
theCompiledStylesheet, theOutXMLStream);
                result = theXalanTransformer->transform(
                                        theParsedSource,
                                        theCompiledStylesheet,
                                        &theHandler,
                                        writeCallback,
                                        flushCallback);
                currenttime = time(NULL);  
                printf( "End Transforming %ld\n", currenttime ); 

3) How does one test a DLL independently?  Are you suggesting I compile as an 
executable with a main method and test, and just assume the DLL will perform 
similarly?  My transform method prints out the system time very very often, so 
I know the JNI interface isn't the slow part, just the 
XalanTransformer::transform method call.

Thanks again.

Brian

-----Original Message-----
From: David Bertoni [mailto:[EMAIL PROTECTED]
Sent: Friday, October 07, 2005 12:29 PM
To: [email protected]
Subject: Re: Slow performance of XalanTransformer.transform in DLL


Brian Frutchey wrote:
> I am writing a JNI bridge which uses Xalan-C++ to speed up the XSLT 
> processing in a Java application.  Everything is functional, but the 
> XalanTransformer.transform method is perform exceptionally slow (slower 
> than a native Java implementation using Xalan-J).  Strangely, I am 
> copying the code from the XalanTransformer sample project, but when I 
> use the packaged executable from the command line on the same file and 
> stylesheet the performance is lightning fast.

Do you mean the XalanTransformer sample application, or the Xalan 
executable?

> The only major difference between my code and the sample project is
> that instead of compiling as an executable I am compiling as a DLL.
> Could this be the source of my performance hit? My DLL will convert a
> 1MB file in 44secs, the executable takes about .2secs. What else
> might it be?
> 

Are you testing this outside of the Java environment, to make sure 
nothing in Java is taking up the time?  Building into a DLL should not 
have any effect on performance.

> Code:
>
...
>         XALAN_USING_STD(istrstream)
>         XALAN_USING_STD(ostringstream)

Using std::ostringstream or std::ostrstream is never a good idea if you 
want the best performance.  Take a look at the XalanTransformerCallback 
sample to see how you can use the callback mechanism to avoid multiple 
memory allocations and extra copies of the serialized result.

If you're having performance problems, I suggest you do the following:

1. Make sure you are building a release DLL and the compiler is set to 
optimize.

2. Use a callback to avoid extraneous memory allocations and extra 
copies of the data.

3. Test your code without any JNI artifacts, to verify the performance 
problem is actually related to Xalan and your code that works with 
Xalan, and not JNI.

> 
> This email message and any attachments are confidential to Endeca. If 
> you are not the intended recipient, please notify Endeca immediately -- 
> by replying to this message or by sending an email to: [EMAIL PROTECTED] 
> -- and destroy all copies of this message and any attachments. Thank you.
>

You should remove this tag from your postings to public mailing lists, 
since your message is _not_ confidential in the least.

Dave


Reply via email to