Hello, To reproduce this problem I think you will need my XSL and XML files. But I don't want to overload the mail list... (I already sent a massive message to the subscibe address - sorry about this but I don't use mailing lists much).
The main app I have is a fairly memory hungry GUI, so I tried running the Xalan transform in its own process, this helped a bit. The performance in RELEASE is about 2 minutes. The performance in DEBUG is about 30 mins. This is similar to the performance of the Xalan sample 'XalanCallbackTransformer' (RELEASE 2 minutes, DEBUG 11 minutes). > Are you by any chance using a ostrstream or ostringstream instance as to > hold the result of the transformation? I am using a callback handler, and it uses a vector of string objects on the heap. I don't think this is related to the problem - nearly all the time is spent processing BEFORE there is more than 1KB of output. > You cannot build Xalan-C without Xerces-C, and I'm not sure why you I got the idea from the Apache page: http://xml.apache.org/xalan-c/usagepatterns.html#xercesdomwrapperparsedsource "Performance is much better when Xalan-C++ uses native source tree handling rather than interacting with the Xerces DOMParser". What does this mean then, if Xalan cannot be built without Xerces ? > any performance issues, so why do you think Xerces-C is the problem in > your code? > > Please show us some code that shows us how you are invoking Xalan-C. In > particular, show us how you are handling the output of the transformation. > I believe the problem is with Xalan-C not Xerces-C, since even the sample 'XalanCallbackTransformer' takes 2 minutes in RELEASE build. Here is my code in any case: Thanks, Sean ============= ... //Initialise Xalan ... XALAN_USING_STD(cerr) XALAN_USING_STD(cout) XALAN_USING_STD(endl) //Initialise the Xalan transformer: XALAN_USING_XERCES(XMLPlatformUtils) XALAN_USING_XALAN(XalanTransformer) // Call the static initializer for Xerces. XMLPlatformUtils::Initialize(); // Initialize Xalan. XalanTransformer::initialize(); // Create a XalanTransformer. pXalanTransformer = new XalanTransformer; ... //invoke the transform: ... BOOL CMXmlTransformer::TransformParsedXMLWithXSLFile(CString _csXSLFilepath, CString _csXMLFilepathOut, BOOL* _pbErrors) { //Perform an XSL transform on a compiled XML file, using a compiled XSL. ... long lRetVal = pXalanTransformer->parseSource(X(_csXMLFilepath), pXalanParsedXML); ... if(pXalanParsedXML==NULL) { ASSERT(FALSE); ... return FALSE; //cannot continue } BOOL bSuccess = FALSE; (*_pbErrors) = FALSE; try { XalanCompiledStylesheet* pCompiledStylesheet = NULL; long lRetVal = pXalanTransformer->compileStylesheet(X(_csXSLFilepath), pCompiledStylesheet); if(lRetVal!=0) { ASSERT(FALSE); ... } // CallbackHandler writes incrementally, saving on memory allocation and so improving performance CMXalanCallbackHandler xalanHandler(pClient); // Do the transform. long lResult = pXalanTransformer->transform( *pXalanParsedXML, pCompiledStylesheet, &xalanHandler, XalanWriteCallback, XalanFlushCallback ); if(lResult!=0) { ASSERT(FALSE); ... } { //In any case, now write out the XML to a file (even if empty): vector< CString* >* pVecStrings = xalanHandler.GetXMLStrings(); CFile fileXML; //destructor of CFile will call Close() ... } } catch(...) { ASSERT(FALSE); ... } ... return bSuccess; } //Xalan callback handler: ////////////////////////////////////////////////////////////////////////////// //begin class CMXalanCallbackHandler //public: CMXalanCallbackHandler::CMXalanCallbackHandler(IXmlTransformerClient* _pClient) { pClient = _pClient; Reset(); } /*virtual*/ CMXalanCallbackHandler::~CMXalanCallbackHandler() { Clear(); } void CMXalanCallbackHandler::Clear() { for(vector< CString* >::iterator it = vecString.begin(); it != vecString.end(); it++) { delete *it; } vecString.clear(); } vector< CString* >* CMXalanCallbackHandler::GetXMLStrings() { return &vecString; } inline void CMXalanCallbackHandler::AllocateSpace() { if(vecString.size() == vecString.capacity()) { //allocate another block of vector entries: vecString.reserve( vecString.size() + XML_VECTOR_NUMBER_OF_CHUNKS ); } } void CMXalanCallbackHandler::Reset() { Clear(); //pre-allocate some space in the vector: vecString.reserve(XML_VECTOR_NUMBER_OF_CHUNKS); //i.e. reserve room for 500 chunks of XML data } CallbackSizeType CMXalanCallbackHandler::WriteChunk(const char* _pszData, CallbackSizeType _length) { TRACE1(_T("\nCMXalanCallbackHandler::WriteChunk(%ld)\n"), _length); AllocateSpace(); CString* pXMLChunk = new CString(_pszData, _length); vecString.push_back(pXMLChunk); //use new CString to prevent extra copying #ifdef _XMLMODEL_DIAGNOSTICS //for DEBUGing code only //need to NULL-terminate the string in order to output it: CString csTempOut(pszBuffer, _length); csTempOut += _T("\0"); TRACE( csTempOut.Left(500) ); //TRACE() can handle 512 chars max TRACE( csTempOut.Mid(500) ); //TRACE() can handle 512 chars max #endif //_XMLMODEL_DIAGNOSTICS if(pClient) { pClient->ChunkAdded(); } return _length; } void CMXalanCallbackHandler::Flush() { //not a stream, so do nothing } // 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 XalanWriteCallback( const char* theData, CallbackSizeType theLength, void* theHandle) { #if defined(XALAN_OLD_STYLE_CASTS) return ((CMXalanCallbackHandler*)theHandle)->WriteChunk(theData, theLength); #else return reinterpret_cast<CMXalanCallbackHandler*>(theHandle)->WriteChunk(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 XalanFlushCallback(void* theHandle) { #if defined(XALAN_OLD_STYLE_CASTS) ((CMXalanCallbackHandler*)theHandle)->Flush(); #else reinterpret_cast<CMXalanCallbackHandler*>(theHandle)->Flush(); #endif } } //extern //end of class CMXalanCallbackHandler ////////////////////////////////////////////////////////////////////////////// ============= ___________ Sean Ryan ___________ Sean Ryan
