diff options
author | Charles.Lee <cheoljoo@gmail.com> | 2018-08-27 03:14:55 (GMT) |
---|---|---|
committer | Charles.Lee <cheoljoo@gmail.com> | 2018-08-27 03:14:55 (GMT) |
commit | 1a9bb0614362217143d8e01779d8ac9b336b96f4 (patch) | |
tree | 36ec658ef5ab1530ea8d4a18fb6f7b7c8cafe656 | |
parent | 94a52469b177703d3e0d94bed6c4a48bddba18cb (diff) | |
download | Doxygen-1a9bb0614362217143d8e01779d8ac9b336b96f4.zip Doxygen-1a9bb0614362217143d8e01779d8ac9b336b96f4.tar.gz Doxygen-1a9bb0614362217143d8e01779d8ac9b336b96f4.tar.bz2 |
Imporvement of performance : Reduce the Java running count
# What is it
- #6465 is the first reqeust. So I followed up the albert advice.
- in case of debug you use printf statements, I think that here there better options would be
- create an -d flag (e.g. -d plantuml) that gives the information, so no need for using the configuration option
- Follow up : create -d plantuml [debug.h, debug.cpp]
- usage of printf
- printf should not be used,all output is steered over calls to routines as defined in message.cpp,
- Follow up : use Debug::Print(Debug::Plantuml, ... and msg()
- usage of std::string / std::map
- in doxygen the string manipulation is. mostly, done by means of Qt classes (e.g. classes QCString, QString). For consistency these classes should be used.
- map manipulation is also done by means of Qt classes (dictionary and list classes)
- Follow up : use QDict QList QCString [plantuml.h, plantuml.cpp]
- dirent / opendir /readdir
- when browsing through directories the routines line readFileOrDirectory should probably be used or the techniques used in this routine
- Follow up : I will follow when I try to reduce redundancy of creating plantuml image.
- Run java minimally
- Test Case : 4 plantuml
- Original Run without PLANTUML_RUN_JAVA_ONCE
- 8.2 sec = 4 times * ( 1.6(java vm) + 0.1 * 1(load multiple file) + process each plantuml (0.35) *1 ) <- prediction
- New with PLANTUML_RUN_JAVA_ONCE
- 3.499 sec = 1.6(java vm) + 0.1 * 4(load multiple file) + process each plantuml (0.35) *4 <- prediction
- Creating Java Virtual Machine has a big portion.
- Result
- Improving Performance : 8.2 -> 3.499 (in case of 4 plantuml)
# Configuration
- add configuration value in Doxyfile
- PLANTUML_RUN_JAVA_ONCE = YES
# Debugging
- doxygen -d plantuml
- doxygen -d time -d plantuml
# Tested with following options
- source code of 3 plantuml
- PLANTUML_RUN_JAVA_ONCE = YES or NO
- DOT_IMAGE_FORMAT = png or svg
- DOT_CLEANUP = YES or NO
- -d plantuml
-rw-r--r-- | src/config.xml | 8 | ||||
-rw-r--r-- | src/debug.cpp | 1 | ||||
-rw-r--r-- | src/debug.h | 3 | ||||
-rw-r--r-- | src/doxygen.cpp | 8 | ||||
-rw-r--r-- | src/plantuml.cpp | 238 | ||||
-rw-r--r-- | src/plantuml.h | 22 |
6 files changed, 267 insertions, 13 deletions
diff --git a/src/config.xml b/src/config.xml index 2e0f430..4af0a65 100644 --- a/src/config.xml +++ b/src/config.xml @@ -3491,6 +3491,14 @@ to be found in the default search path. ]]> </docs> </option> + <option type='bool' id='PLANTUML_RUN_JAVA_ONCE' defval='0'> + <docs> +<![CDATA[ +If the \c PLANTUML_RUN_JAVA_ONCE tag is set to \c YES, doxygen will run java once for improving the performance. +This will run once at the end of process like dot graphics processing. +]]> + </docs> + </option> <option type='int' id='DOT_GRAPH_MAX_NODES' minval='0' maxval='10000' defval='50' depends='HAVE_DOT'> <docs> <![CDATA[ diff --git a/src/debug.cpp b/src/debug.cpp index c81a1af..2f343ac 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -48,6 +48,7 @@ static LabelMap s_labels[] = { "markdown", Debug::Markdown }, { "filteroutput", Debug::FilterOutput }, { "lex", Debug::Lex }, + { "plantuml", Debug::Plantuml }, { 0, (Debug::DebugMask)0 } }; diff --git a/src/debug.h b/src/debug.h index 8a28c7a..9a2070c 100644 --- a/src/debug.h +++ b/src/debug.h @@ -37,7 +37,8 @@ class Debug ExtCmd = 0x00000400, Markdown = 0x00000800, FilterOutput = 0x00001000, - Lex = 0x00002000 + Lex = 0x00002000, + Plantuml = 0x00004000 }; static void print(DebugMask mask,int prio,const char *fmt,...); static int setFlag(const char *label); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index bf93a9b..b33ae49 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -103,6 +103,7 @@ #include "settings.h" #include "context.h" #include "fileparser.h" +#include "plantuml.h" // provided by the generated file resources.cpp extern void initResources(); @@ -11707,6 +11708,13 @@ void generateOutput() g_s.end(); } + if (Config_getBool(PLANTUML_RUN_JAVA_ONCE)) + { + g_s.begin("Running plantuml with JAVA...\n"); + PlantumlManager::instance()->run(); + g_s.end(); + } + if (Config_getBool(HAVE_DOT)) { g_s.begin("Running dot...\n"); diff --git a/src/plantuml.cpp b/src/plantuml.cpp index ada035b..feac907 100644 --- a/src/plantuml.cpp +++ b/src/plantuml.cpp @@ -19,8 +19,11 @@ #include "doxygen.h" #include "index.h" #include "message.h" +#include "debug.h" #include <qdir.h> +#include <qdict.h> +#include <qlist.h> static const int maxCmdLine = 40960; @@ -29,6 +32,9 @@ QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,con QCString baseName(4096); static int umlindex=1; + Debug::print(Debug::Plantuml,0,"*** %s fileName: %s\n",__PRETTY_FUNCTION__,qPrint(fileName)); + Debug::print(Debug::Plantuml,0,"*** %s outDir: %s\n",__PRETTY_FUNCTION__,qPrint(outDir)); + if (fileName.isEmpty()) // generate name { baseName = outDir+"/inline_umlgraph_"+QCString().setNum(umlindex++); @@ -40,6 +46,8 @@ QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,con if (i!=-1) baseName = baseName.left(i); baseName.prepend(outDir+"/"); } + + Debug::print(Debug::Plantuml,0,"*** %s baseName: %s\n",__PRETTY_FUNCTION__,qPrint(baseName)); QFile file(baseName+".pu"); if (!file.open(IO_WriteOnly)) { @@ -55,9 +63,9 @@ QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,con void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format) { - static QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); - static QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE); - static QCString dotPath = Config_getString(DOT_PATH); + QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); + QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE); + QCString dotPath = Config_getString(DOT_PATH); QCString pumlExe = "java"; QCString pumlArgs = ""; @@ -123,17 +131,39 @@ void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutp pumlArgs+=".pu\" "; pumlArgs+="-charset UTF-8 "; int exitCode; - //printf("*** running: %s %s outDir:%s %s\n",pumlExe.data(),pumlArgs.data(),outDir,baseName); msg("Running PlantUML on generated file %s.pu\n",baseName); portable_sysTimerStart(); - if ((exitCode=portable_system(pumlExe,pumlArgs,TRUE))!=0) - { - err("Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n", - plantumlJarPath.data(),exitCode); - } - else if (Config_getBool(DOT_CLEANUP)) - { - QFile(QCString(baseName)+".pu").remove(); + if(Config_getBool(PLANTUML_RUN_JAVA_ONCE)){ + //Debug::print(Debug::Plantuml,0,"*** imgName %s\n",qPrint(imgName)); + //Debug::print(Debug::Plantuml,0,"*** running: %s %s outDir:%s %s\n",qPrint(pumlExe),qPrint(pumlArgs),outDir,baseName); + //Debug::print(Debug::Plantuml,0,"*** baseName: %s\n",baseName); + //Debug::print(Debug::Plantuml,0,"*** outDir: %s\n",outDir); + //Debug::print(Debug::Plantuml,0,"*** project name: %s\n",qPrint(Config_getString(PROJECT_NAME)) ); + //Debug::print(Debug::Plantuml,0,"*** output directory: %s\n",qPrint(Config_getString(OUTPUT_DIRECTORY)) ); + QCString qcOutDir(outDir); + uint pos = qcOutDir.findRev("/"); + //Debug::print(Debug::Plantuml,0,"*** right: %d\n",pos ); + //QCString baseDirectoryName(qcOutDir.left(pos)); + //Debug::print(Debug::Plantuml,0,"*** baseDirectoryName: %s\n",qPrint(baseDirectoryName)); + QCString generateType(qcOutDir.right(qcOutDir.length() - (pos + 1)) ); + Debug::print(Debug::Plantuml,0,"*** %s generateType: %s\n",__PRETTY_FUNCTION__,qPrint(generateType)); + QCString qcBaseName(baseName); + pos = qcBaseName.findRev("/"); + //Debug::print(Debug::Plantuml,0,"*** right: %d\n",pos ); + QCString baseFileName(qcBaseName.right(qcBaseName.length() - (pos + 1)) ); + Debug::print(Debug::Plantuml,0,"*** %s baseFileName: %s\n",__PRETTY_FUNCTION__,qPrint(baseFileName)); + PlantumlManager::instance()->insert(generateType,baseFileName,format); + } else { // ! Config_getBool(PLANTUML_RUN_JAVA_ONCE) + Debug::print(Debug::Plantuml,0,"*** running: %s %s outDir:%s %s\n",qPrint(pumlExe),qPrint(pumlArgs),outDir,baseName); + if ((exitCode=portable_system(pumlExe,pumlArgs,TRUE))!=0) + { + err("Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n", + plantumlJarPath.data(),exitCode); + } + else if (Config_getBool(DOT_CLEANUP)) + { + QFile(QCString(baseName)+".pu").remove(); + } } portable_sysTimerStop(); if ( (format==PUML_EPS) && (Config_getBool(USE_PDFLATEX)) ) @@ -150,3 +180,187 @@ void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutp Doxygen::indexList->addImageFile(imgName); } +//-------------------------------------------------------------------- + +PlantumlManager *PlantumlManager::m_theInstance = 0; + +PlantumlManager *PlantumlManager::instance() +{ + if (!m_theInstance) + { + m_theInstance = new PlantumlManager; + } + return m_theInstance; +} + +PlantumlManager::PlantumlManager() +{ +} + +PlantumlManager::~PlantumlManager() +{ + { + QDictIterator< QList<QCString> > it( m_pngPlantumlFiles); // See QDictIterator + QList<QCString> *list; + for (it.toFirst();(list=it.current());++it) + { + (*list).clear(); + } + m_pngPlantumlFiles.clear(); + } +} + +void PlantumlManager::runPlantumlFiles(QDict< QList <QCString> > &PlantumlFiles,const char *type) +{ + /* *** running: java -Djava.awt.headless=true -jar "/Users/cheoljoo/code/common_telltale/GP/Apps/Src/MgrTelltale/tools/plantuml.jar" -o "/Users/cheoljoo/Code/LG/test_doxygen/DOXYGEN_OUTPUT/html" -tpng "/Users/cheoljoo/Code/LG/test_doxygen/DOXYGEN_OUTPUT/html/A.pu" -charset UTF-8 outDir:/Users/cheoljoo/Code/LG/test_doxygen/DOXYGEN_OUTPUT/html /Users/cheoljoo/Code/LG/test_doxygen/DOXYGEN_OUTPUT/html/A + */ + int exitCode; + QCString plantumlJarPath = Config_getString(PLANTUML_JAR_PATH); + QCString plantumlConfigFile = Config_getString(PLANTUML_CFG_FILE); + QCString dotPath = Config_getString(DOT_PATH); + + QCString pumlExe = "java"; + QCString pumlArgs = ""; + + QStrList &pumlIncludePathList = Config_getList(PLANTUML_INCLUDE_PATH); + char *s=pumlIncludePathList.first(); + if (s) + { + pumlArgs += "-Dplantuml.include.path=\""; + pumlArgs += s; + s = pumlIncludePathList.next(); + } + while (s) + { + pumlArgs += portable_pathListSeparator(); + pumlArgs += s; + s = pumlIncludePathList.next(); + } + if (pumlIncludePathList.first()) pumlArgs += "\" "; + pumlArgs += "-Djava.awt.headless=true -jar \""+plantumlJarPath+"plantuml.jar\" "; + if (!plantumlConfigFile.isEmpty()) + { + pumlArgs += "-config \""; + pumlArgs += plantumlConfigFile; + pumlArgs += "\" "; + } + if (Config_getBool(HAVE_DOT) && !dotPath.isEmpty()) + { + pumlArgs += "-graphvizdot \""; + pumlArgs += dotPath; + pumlArgs += "dot"; + pumlArgs += portable_commandExtension(); + pumlArgs += "\" "; + } + + + QDictIterator< QList<QCString> > it( PlantumlFiles); // See QDictIterator + QList<QCString> *list; + for (it.toFirst();(list=it.current());++it) + { + QCString pumlArguments(pumlArgs); + msg("Running PlantUML on png PlantumlFiles in %s\n",qPrint(it.currentKey())); + pumlArguments+="-o \""; + pumlArguments+=Config_getString(OUTPUT_DIRECTORY); + pumlArguments+="/"; + pumlArguments+=it.currentKey(); + pumlArguments+="\" "; + pumlArguments+="-charset UTF-8 "; + pumlArguments+=type; + pumlArguments+=" "; + QListIterator<QCString> li(*list); + QCString *nb; + for (li.toFirst();(nb=li.current());++li) + { + pumlArguments+="\""; + pumlArguments+=Config_getString(OUTPUT_DIRECTORY); + pumlArguments+="/"; + pumlArguments+=it.currentKey(); + pumlArguments+="/"; + pumlArguments+=*nb; + pumlArguments+=".pu"; + pumlArguments+="\" "; + } + Debug::print(Debug::Plantuml,0,"*** %s Running Plantuml arguments:%s\n",__PRETTY_FUNCTION__,qPrint(pumlArguments)); + if ((exitCode=portable_system(pumlExe,pumlArguments,TRUE))!=0) + { + err("Problems running PlantUML. Verify that the command 'java -jar \"%splantuml.jar\" -h' works from the command line. Exit code: %d\n", + plantumlJarPath.data(),exitCode); + } + else if (Config_getBool(DOT_CLEANUP)) + { + for (li.toFirst();(nb=li.current());++li) + { + QCString pumlName = ""; + pumlName+=Config_getString(OUTPUT_DIRECTORY); + pumlName+="/"; + pumlName+=it.currentKey(); + pumlName+="/"; + pumlName+=*nb; + pumlName+=".pu"; + QFile(pumlName).remove(); + } + } + } + +} + +void PlantumlManager::run() +{ + Debug::print(Debug::Plantuml,0,"*** %s\n",__PRETTY_FUNCTION__); + runPlantumlFiles(m_pngPlantumlFiles, "-tpng"); + runPlantumlFiles(m_svgPlantumlFiles, "-tsvg"); + runPlantumlFiles(m_epsPlantumlFiles, "-teps"); +} + +void PlantumlManager::print(QDict< QList <QCString> > &PlantumlFiles) +{ + if (Debug::isFlagSet(Debug::Plantuml)){ + QDictIterator< QList<QCString> > it( PlantumlFiles); // See QDictIterator + QList<QCString> *list; + for (it.toFirst();(list=it.current());++it) + { + Debug::print(Debug::Plantuml,0,"*** %s PlantumlFiles key:%s\n",__PRETTY_FUNCTION__,qPrint(it.currentKey())); + QListIterator<QCString> li(*list); + QCString *nb; + for (li.toFirst();(nb=li.current());++li) + { + Debug::print(Debug::Plantuml,0,"*** %s PlantumlFiles list:%s\n",__PRETTY_FUNCTION__,qPrint(*nb)); + } + } + } +} + +void PlantumlManager::addPlantumlFiles(QDict< QList <QCString> > &PlantumlFiles,const QCString key , const QCString value) +{ + QList<QCString> *list = PlantumlFiles.find(key); + if (list==0) + { + list = new QList<QCString>; + PlantumlFiles.insert(key,list); + } + list->append(new QCString(value)); + Debug::print(Debug::Plantuml,0,"*** %s append : png key:%s ,value:%s\n",__PRETTY_FUNCTION__,qPrint(key),qPrint(value)); +} + +void PlantumlManager::insert(const QCString key , const QCString value, PlantUMLOutputFormat format) +{ + Debug::print(Debug::Plantuml,0,"*** %s key:%s ,value:%s\n",__PRETTY_FUNCTION__,qPrint(key),qPrint(value)); + switch (format) + { + case PUML_BITMAP: + addPlantumlFiles(m_pngPlantumlFiles,key,value); + print(m_pngPlantumlFiles); + break; + case PUML_EPS: + addPlantumlFiles(m_epsPlantumlFiles,key,value); + print(m_epsPlantumlFiles); + break; + case PUML_SVG: + addPlantumlFiles(m_svgPlantumlFiles,key,value); + print(m_svgPlantumlFiles); + break; + } +} + +//-------------------------------------------------------------------- diff --git a/src/plantuml.h b/src/plantuml.h index 54ab8a2..b931e70 100644 --- a/src/plantuml.h +++ b/src/plantuml.h @@ -16,6 +16,9 @@ #ifndef PLANTUML_H #define PLANTUML_H +#include <qdict.h> +#include <qlist.h> + class QCString; /** Plant UML output image formats */ @@ -36,5 +39,24 @@ QCString writePlantUMLSource(const QCString &outDir,const QCString &fileName,con */ void generatePlantUMLOutput(const char *baseName,const char *outDir,PlantUMLOutputFormat format); +/** Singleton that manages plantuml relation actions */ +class PlantumlManager +{ + public: + static PlantumlManager *instance(); + void run(); + void insert(const QCString key , const QCString value,PlantUMLOutputFormat format); + private: + PlantumlManager(); + virtual ~PlantumlManager(); + void addPlantumlFiles(QDict< QList <QCString> > &PlantumlFiles,const QCString key , const QCString value); + void print(QDict< QList <QCString> > &PlantumlFiles); + void runPlantumlFiles(QDict< QList <QCString> > &PlantumlFiles,const char *type); + static PlantumlManager *m_theInstance; + QDict< QList<QCString> > m_pngPlantumlFiles; + QDict< QList<QCString> > m_svgPlantumlFiles; + QDict< QList<QCString> > m_epsPlantumlFiles; +}; + #endif |