1 // Created on: 1995-02-23
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <Draw_Appli.hxx>
20 #include <Draw_Chronometer.hxx>
21 #include <Draw_Drawable3D.hxx>
22 #include <Message.hxx>
23 #include <Message_Messenger.hxx>
24 #include <Message_PrinterOStream.hxx>
26 #include <OSD_Chronometer.hxx>
27 #include <OSD_Environment.hxx>
28 #include <OSD_Exception_CTRL_BREAK.hxx>
29 #include <OSD_MAllocHook.hxx>
30 #include <OSD_MemInfo.hxx>
31 #include <OSD_Parallel.hxx>
32 #include <OSD_ThreadPool.hxx>
33 #include <Standard_Macro.hxx>
34 #include <Standard_SStream.hxx>
35 #include <Standard_Stream.hxx>
36 #include <Standard_Version.hxx>
37 #include <TCollection_AsciiString.hxx>
39 #include <OSD_PerfMeter.h>
50 #define RLIM_INFINITY 0x7fffffff
52 static clock_t CPU_CURRENT; // cpu time already used at last
53 // cpulimit call. (sec.)
56 #include <sys/resource.h>
60 #if defined (__hpux) || defined ( HPUX )
61 #define RLIM_INFINITY 0x7fffffff
67 extern Standard_Boolean Draw_Batch;
69 static clock_t CPU_LIMIT; // Cpu_limit in Sec.
70 static OSD_Timer aTimer;
72 //=======================================================================
74 //=======================================================================
76 extern Standard_Boolean Draw_Chrono;
78 static Standard_Integer dchronom (Draw_Interpretor& theDI,
79 Standard_Integer theNbArgs,
80 const char** theArgVec)
84 && (*theArgVec[1] == '0'
85 || *theArgVec[1] == '1')))
89 Draw_Chrono = !Draw_Chrono;
93 Draw_Chrono = (*theArgVec[1] == '1');
97 ? "Chronometers activated.\n"
98 : "Chronometers deactivated.\n");
102 const char* aTimerName = theArgVec[1];
103 Handle(Draw_Chronometer) aChronom;
104 if (Handle(Draw_Drawable3D) aDrawable = Draw::Get (aTimerName))
106 aChronom = Handle(Draw_Chronometer)::DownCast (aDrawable);
108 if (aChronom.IsNull())
110 aChronom = new Draw_Chronometer();
111 Draw::Set (aTimerName, aChronom, false);
116 aChronom->Timer().Reset();
120 const bool toShowCout = (TCollection_AsciiString (theArgVec[0]) == "chrono");
122 for (Standard_Integer anIter = 2; anIter < theNbArgs; ++anIter)
124 TCollection_AsciiString anArg (theArgVec[anIter]);
126 if (anArg == "-reset"
129 aChronom->Timer().Reset();
131 else if (anArg == "-restart"
132 || anArg == "restart")
134 aChronom->Timer().Restart();
136 else if (anArg == "-start"
137 || anArg == "-resume"
140 aChronom->Timer().Start();
142 else if (anArg == "-stop"
146 aChronom->Timer().Stop();
148 else if (anArg == "-show"
153 aChronom->Timer().Show (std::cout);
157 Standard_SStream aStream;
158 aChronom->Timer().Show (aStream);
162 else if (anIter + 1 < theNbArgs
163 && (anArg == "-counter"
164 || anArg == "counter"))
166 Standard_Real aSeconds = 0.0, aCPUtime = 0.0;
167 Standard_Integer aMinutes = 0, aHours = 0;
168 aChronom->Timer().Show (aSeconds, aMinutes, aHours, aCPUtime);
171 std::cout << "COUNTER " << theArgVec[++anIter] << ": " << aCPUtime << "\n";
175 theDI << "COUNTER " << theArgVec[++anIter] << ": " << aCPUtime << "\n";
178 else if (anArg == "-elapsed")
180 if (++aNbPuts > 1) { theDI << " "; }
181 theDI << aChronom->Timer().ElapsedTime();
183 else if (anArg == "-cpu"
184 || anArg == "-usercpu"
185 || anArg == "-cpuuser")
187 if (++aNbPuts > 1) { theDI << " "; }
188 theDI << aChronom->Timer().UserTimeCPU();
190 else if (anArg == "-systemcpu"
191 || anArg == "-syscpu"
192 || anArg == "-cpusystem"
193 || anArg == "-cpusys")
195 if (++aNbPuts > 1) { theDI << " "; }
196 theDI << aChronom->Timer().SystemTimeCPU();
198 else if (anArg == "-thread"
199 || anArg == "-threadonly")
201 bool isThreadOnly = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anIter);
202 aChronom->Timer().Stop();
203 aChronom->Timer().Reset();
204 aChronom->Timer().SetThisThreadOnly (isThreadOnly);
206 else if (anArg == "-process")
208 bool isProcessTime = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anIter);
209 aChronom->Timer().Stop();
210 aChronom->Timer().Reset();
211 aChronom->Timer().SetThisThreadOnly (!isProcessTime);
215 theDI << "Syntax error at '" << theArgVec[anIter] << "'\n";
222 //=======================================================================
225 //=======================================================================
227 static Standard_Integer ifbatch(Draw_Interpretor& DI, Standard_Integer , const char** )
237 //=======================================================================
240 //=======================================================================
242 extern Standard_Boolean Draw_Spying;
243 extern std::filebuf Draw_Spyfile;
245 static Standard_Integer spy(Draw_Interpretor& di, Standard_Integer n, const char** a)
248 Draw_Spyfile.close();
249 Draw_Spying = Standard_False;
251 if (!Draw_Spyfile.open(a[1],std::ios::out)) {
252 di << "Cannot open "<<a[1]<<" for writing\n";
255 Draw_Spying = Standard_True;
260 static Standard_Integer dlog(Draw_Interpretor& di, Standard_Integer n, const char** a)
262 if (n != 2 && n != 3)
264 Message::SendFail() << "Enable or disable logging: " << a[0] << " {on|off}\n"
265 << "Reset log: " << a[0] << " reset\n"
266 << "Get log content: " << a[0] << " get";
270 if (! strcmp (a[1], "on") && n == 2)
272 di.SetDoLog (Standard_True);
273 // di.Log() << "dlog on" << std::endl; // for symmetry
275 else if (! strcmp (a[1], "off") && n == 2)
277 di.SetDoLog (Standard_False);
279 else if (! strcmp (a[1], "reset") && n == 2)
283 else if (! strcmp (a[1], "get") && n == 2)
287 else if (! strcmp (a[1], "add") && n == 3)
292 else if (! strcmp (a[1], "status") && n == 2)
294 di << (di.GetDoLog() ? "on" : "off");
297 Message::SendFail() << "Unrecognized option(s): " << a[1];
303 static Standard_Integer decho(Draw_Interpretor& di, Standard_Integer n, const char** a)
307 Message::SendFail() << "Enable or disable echoing: " << a[0] << " {on|off}";
311 if (! strcmp (a[1], "on"))
313 di.SetDoEcho (Standard_True);
315 else if (! strcmp (a[1], "off"))
317 di.SetDoEcho (Standard_False);
320 Message::SendFail() << "Unrecognized option: " << a[1];
326 static Standard_Integer dbreak(Draw_Interpretor& di, Standard_Integer, const char**)
331 catch (OSD_Exception_CTRL_BREAK const&) {
332 di << "User pressed Control-Break";
333 return 1; // Tcl exception
339 static Standard_Integer dversion(Draw_Interpretor& di, Standard_Integer, const char**)
341 // print OCCT version and OCCTY-specific macros used
342 di << "Open CASCADE Technology " << OCC_VERSION_STRING_EXT << "\n";
344 di << "Extended debug mode\n";
345 #elif defined(_DEBUG)
346 di << "Debug mode\n";
349 di << "Tk enabled (HAVE_TK)\n";
351 di << "Tk disabled\n";
354 di << "Xlib enabled (HAVE_XLIB)\n";
355 #elif !defined(_WIN32)
356 di << "Xlib disabled\n";
359 di << "TBB enabled (HAVE_TBB)\n";
361 di << "TBB disabled\n";
364 di << "FreeType enabled (HAVE_FREETYPE)\n";
366 di << "FreeType disabled\n";
368 #ifdef HAVE_FREEIMAGE
369 di << "FreeImage enabled (HAVE_FREEIMAGE)\n";
371 di << "FreeImage disabled\n";
374 di << "FFmpeg enabled (HAVE_FFMPEG)\n";
376 di << "FFmpeg disabled\n";
378 #ifdef HAVE_OPENGL_EXT
379 di << "OpenGL: enabled (HAVE_OPENGL_EXT)\n";
381 #ifdef HAVE_GLES2_EXT
382 di << "OpenGL ES: enabled (HAVE_GLES2_EXT)\n";
385 di << "OpenVR enabled (HAVE_OPENVR)\n";
387 di << "OpenVR disabled\n";
389 #ifdef HAVE_RAPIDJSON
390 di << "RapidJSON enabled (HAVE_RAPIDJSON)\n";
392 di << "RapidJSON disabled\n";
395 di << "Draco enabled (HAVE_DRACO)\n";
397 di << "Draco disabled\n";
400 di << "VTK enabled (HAVE_VTK)\n";
402 di << "VTK disabled\n";
405 di << "Exceptions disabled (No_Exception)\n";
407 di << "Exceptions enabled\n";
410 // check compiler, OS, etc. using pre-processor macros provided by compiler
411 // see "Pre-defined C/C++ Compiler Macros" http://sourceforge.net/p/predef/wiki/
412 // note that only modern compilers that are known to be used for OCCT are recognized
414 // compiler; note that GCC and MSVC are last as other compilers (e.g. Intel) can also define __GNUC__ and _MSC_VER
415 #if defined(__INTEL_COMPILER)
416 di << "Compiler: Intel " << __INTEL_COMPILER << "\n";
417 #elif defined(__BORLANDC__)
418 di << "Compiler: Borland C++ (__BORLANDC__ = " << __BORLANDC__ << ")\n";
419 #elif defined(__clang__)
420 di << "Compiler: Clang " << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__ << "\n";
421 #elif defined(__SUNPRO_C)
422 di << "Compiler: Sun Studio (__SUNPRO_C = " << __SUNPROC_C << ")\n";
423 #elif defined(_MSC_VER)
425 di << "Compiler: MS Visual C++ " << (int)(_MSC_VER/100-6) << "." << (int)((_MSC_VER/10)-60-10*(int)(_MSC_VER/100-6)) << " (_MSC_FULL_VER = " << _MSC_FULL_VER << ")\n";
427 di << "Compiler: MS Visual C++ " << (int)(_MSC_VER/100-5) << "." << (int)((_MSC_VER/10)-50-10*(int)(_MSC_VER/100-5)) << " (_MSC_FULL_VER = " << _MSC_FULL_VER << ")\n";
429 #elif defined(__GNUC__)
430 di << "Compiler: GCC " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__ << "\n";
432 di << "Compiler: unrecognized\n";
435 // Cygwin and MinGW specifics
436 #if defined(__CYGWIN__)
439 #if defined(__MINGW64__)
440 di << "MinGW 64 " << __MINGW64_VERSION_MAJOR << "." << __MINGW64_VERSION_MINOR << "\n";
441 #elif defined(__MINGW32__)
442 di << "MinGW 32 " << __MINGW32_MAJOR_VERSION << "." << __MINGW32_MINOR_VERSION << "\n";
446 #if defined(__amd64) || defined(__x86_64) || defined(_M_AMD64)
447 di << "Architecture: AMD64\n";
448 #elif defined(__i386) || defined(_M_IX86) || defined(__X86__)|| defined(_X86_)
449 di << "Architecture: Intel x86\n";
450 #elif defined(_M_IA64) || defined(__ia64__)
451 di << "Architecture: Intel Itanium (IA 64)\n";
452 #elif defined(__sparc__) || defined(__sparc)
453 di << "Architecture: SPARC\n";
454 #elif defined(__aarch64__) && defined(__LP64__)
455 di << "Architecture: ARM 64-bit\n";
456 #elif defined(__arm__) || defined(__arm64__)
457 #if defined(__LP64__)
458 di << "Architecture: ARM 64-bit\n";
460 di << "Architecture: ARM 32-bit\n";
462 #elif defined(__EMSCRIPTEN__)
463 di << "Architecture: WASM "
464 #if defined(__LP64__)
469 #if defined(__wasm_simd128__)
474 di << "Architecture: unrecognized\n";
478 #if defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__)
479 di << "OS: Windows\n";
480 #elif defined(__APPLE__) || defined(__MACH__)
481 di << "OS: Mac OS X\n";
483 di << "OS: SUN Solaris\n";
484 #elif defined(__ANDROID__) /* must be before Linux */
485 #include <android/api-level.h>
486 di << "OS: Android (__ANDROID_API__ = " << __ANDROID_API__ << ")\n";
487 #elif defined(__QNXNTO__)
488 di << "OS: QNX Neutrino\n";
489 #elif defined(__QNX__)
491 #elif defined(__linux__)
493 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
494 #include <sys/param.h>
495 di << "OS: BSD (BSD = " << BSD << ")\n";
496 #elif defined(__EMSCRIPTEN__)
497 di << "OS: WebAssembly (Emscripten SDK " << __EMSCRIPTEN_major__ << "." << __EMSCRIPTEN_minor__ << "." << __EMSCRIPTEN_tiny__
498 #ifdef __EMSCRIPTEN_PTHREADS__
505 di << "OS: unrecognized\n";
511 //=======================================================================
514 //=======================================================================
516 static Standard_Integer Draw_wait(Draw_Interpretor& , Standard_Integer n, const char** a)
518 Standard_Integer w = 10;
520 w = Draw::Atoi(a[1]);
521 time_t ct = time(NULL) + w;
522 while (time(NULL) < ct) {};
526 //=======================================================================
527 //function : cpulimit
529 //=======================================================================
531 static unsigned int __stdcall CpuFunc (void * /*param*/)
533 clock_t anElapCurrent;
539 Standard_Real anUserSeconds, aSystemSeconds;
540 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
541 aCurrent = clock_t(anUserSeconds + aSystemSeconds);
542 anElapCurrent = clock_t(aTimer.ElapsedTime());
544 if (CPU_LIMIT > 0 && (aCurrent - CPU_CURRENT) >= CPU_LIMIT)
547 if (IsDebuggerPresent())
549 std::cout << "Info: CPU limit (" << CPU_LIMIT << " sec) has been reached but ignored because of attached Debugger" << std::endl;
554 std::cout << "ERROR: Process killed by CPU limit (" << CPU_LIMIT << " sec)" << std::endl;
558 if (CPU_LIMIT > 0 && anElapCurrent >= CPU_LIMIT)
561 if (IsDebuggerPresent())
563 std::cout << "Info: Elapsed limit (" << CPU_LIMIT << " sec) has been reached but ignored because of attached Debugger" << std::endl;
568 std::cout << "ERROR: Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << std::endl;
575 static void cpulimitSignalHandler (int)
577 std::cout << "Process killed by CPU limit (" << CPU_LIMIT << " sec)" << std::endl;
580 static void *CpuFunc(void* /*threadarg*/)
582 clock_t anElapCurrent;
586 anElapCurrent = clock_t(aTimer.ElapsedTime());
587 if (CPU_LIMIT >0 && (anElapCurrent) >= CPU_LIMIT) {
588 std::cout << "Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << std::endl;
596 // Returns time in seconds defined by the argument string,
597 // multiplied by factor defined in environment variable
598 // CSF_CPULIMIT_FACTOR (if it exists, 1 otherwise)
599 static clock_t GetCpuLimit (const Standard_CString theParam)
601 clock_t aValue = Draw::Atoi (theParam);
603 OSD_Environment aEnv("CSF_CPULIMIT_FACTOR");
604 TCollection_AsciiString aEnvStr = aEnv.Value();
605 if (!aEnvStr.IsEmpty())
607 aValue *= Draw::Atoi (aEnvStr.ToCString());
612 static Standard_Integer cpulimit(Draw_Interpretor& di, Standard_Integer n, const char** a)
614 static int aFirst = 1;
616 // Windows specific code
617 unsigned int __stdcall CpuFunc (void *);
621 CPU_LIMIT = RLIM_INFINITY;
623 CPU_LIMIT = GetCpuLimit (a[1]);
624 Standard_Real anUserSeconds, aSystemSeconds;
625 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
626 CPU_CURRENT = clock_t(anUserSeconds + aSystemSeconds);
629 if (aFirst) // Launch the thread only at the 1st call.
632 _beginthreadex (NULL, 0, CpuFunc, NULL, 0, &aThreadID);
639 rlp.rlim_max = RLIM_INFINITY;
642 rlp.rlim_cur = RLIM_INFINITY;
646 rlp.rlim_cur = GetCpuLimit (a[1]);
649 CPU_LIMIT = (clock_t )rlp.rlim_cur;
651 int aStatus = setrlimit (RLIMIT_CPU, &rlp);
654 di << "status cpulimit setrlimit : " << aStatus << "\n";
657 // set signal handler to print a message before death
658 struct sigaction act, oact;
659 memset (&act, 0, sizeof(act));
660 act.sa_handler = cpulimitSignalHandler;
661 sigaction (SIGXCPU, &act, &oact);
663 // cpulimit for elapsed time
666 pthread_t cpulimitThread;
667 if (aFirst) // Launch the thread only at the 1st call.
670 pthread_create(&cpulimitThread, NULL, CpuFunc, NULL);
673 di << "CPU and elapsed time limit set to " << (double)CPU_LIMIT << " seconds";
677 //=======================================================================
678 //function : mallochook
680 //=======================================================================
682 static Standard_Integer mallochook(Draw_Interpretor& di, Standard_Integer n,
688 usage: mallochook cmd\n\
689 where cmd is one of:\n\
690 set [<op>] - set callback to malloc/free; op is one of the following:\n\
691 0 - set callback to NULL,\n\
692 1 - set callback OSD_MAllocHook::CollectBySize (default)\n\
693 2 - set callback OSD_MAllocHook::LogFileHandler\n\
694 reset - reset the CollectBySize handler\n\
695 report1 [<outfile>]\n\
696 - write report from CollectBySize handler in <outfile>\n\
698 - open file for writing the log with LogFileHandler\n\
699 close - close the log file with LogFileHandler\n\
700 report2 [<flag>] [<logfile>] [<outfile>]\n\
701 - scan <logfile> written with LogFileHandler\n\
702 and make synthesized report in <outfile>; <flag> can be:\n\
703 0 - simple stats by sizes (default),\n\
704 1 - with alive allocation numbers\n\
705 By default <logfile> is \"mem-log.txt\", <outfile> is \"mem-stat.txt\""
709 if (strcmp(a[1], "set") == 0)
711 int aType = (n > 2 ? Draw::Atoi(a[2]) : 1);
712 if (aType < 0 || aType > 2)
714 di << "unknown op of the command set\n";
719 OSD_MAllocHook::SetCallback(NULL);
720 di << "callback is unset\n";
724 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetCollectBySize());
725 di << "callback is set to CollectBySize\n";
727 else //if (aType == 2)
729 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetLogFileHandler());
730 di << "callback is set to LogFileHandler\n";
733 else if (strcmp(a[1], "reset") == 0)
735 OSD_MAllocHook::GetCollectBySize()->Reset();
736 di << "CollectBySize handler is reset\n";
738 else if (strcmp(a[1], "open") == 0)
740 const char* aFileName = (n > 2 ? a[2] : "mem-log.txt");
741 if (!OSD_MAllocHook::GetLogFileHandler()->Open(aFileName))
743 di << "cannot create file " << aFileName << " for writing\n";
746 di << "log file " << aFileName << " is opened for writing\n";
748 else if (strcmp(a[1], "close") == 0)
750 OSD_MAllocHook::GetLogFileHandler()->Close();
751 di << "log file is closed\n";
753 else if (strcmp(a[1], "report1") == 0)
755 const char* aOutFile = "mem-stat.txt";
758 if (OSD_MAllocHook::GetCollectBySize()->MakeReport(aOutFile))
760 di << "report " << aOutFile << " has been created\n";
764 di << "cannot create report " << aOutFile << "\n";
768 else if (strcmp(a[1], "report2") == 0)
770 Standard_Boolean includeAlive = Standard_False;
771 const char* aLogFile = "mem-log.txt";
772 const char* aOutFile = "mem-stat.txt";
775 includeAlive = (Draw::Atoi(a[2]) != 0);
783 if (OSD_MAllocHook::LogFileHandler::MakeReport(aLogFile, aOutFile, includeAlive))
785 di << "report " << aOutFile << " has been created\n";
789 di << "cannot create report " << aOutFile << " from the log file "
796 di << "unrecognized command " << a[1] << "\n";
802 //==============================================================================
805 //==============================================================================
807 static int dlocale (Draw_Interpretor& di, Standard_Integer n, const char** argv)
809 int category = LC_ALL;
812 const char *cat = argv[1];
813 if ( ! strcmp (cat, "LC_ALL") ) category = LC_ALL;
814 else if ( ! strcmp (cat, "LC_COLLATE") ) category = LC_COLLATE;
815 else if ( ! strcmp (cat, "LC_CTYPE") ) category = LC_CTYPE;
816 else if ( ! strcmp (cat, "LC_MONETARY") ) category = LC_MONETARY;
817 else if ( ! strcmp (cat, "LC_NUMERIC") ) category = LC_NUMERIC;
818 else if ( ! strcmp (cat, "LC_TIME") ) category = LC_TIME;
821 Message::SendFail() << "Error: cannot recognize argument " << cat << " as one of LC_ macros";
825 const char* locale = (n > 2 ? argv[2] : NULL);
826 const char* result = setlocale (category, locale);
830 std::cout << "Error: unsupported locale specification: " << locale << std::endl;
834 //==============================================================================
835 //function : dmeminfo
837 //==============================================================================
839 static int dmeminfo (Draw_Interpretor& theDI,
840 Standard_Integer theArgNb,
841 const char** theArgVec)
845 OSD_MemInfo aMemInfo;
846 theDI << aMemInfo.ToString();
850 NCollection_Map<OSD_MemInfo::Counter> aCounters;
851 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
853 TCollection_AsciiString anArg (theArgVec[anIter]);
855 if (anArg == "virt" || anArg == "v")
857 aCounters.Add (OSD_MemInfo::MemVirtual);
859 else if (anArg == "heap" || anArg == "h")
861 aCounters.Add (OSD_MemInfo::MemHeapUsage);
863 else if (anArg == "wset" || anArg == "w")
865 aCounters.Add (OSD_MemInfo::MemWorkingSet);
867 else if (anArg == "wsetpeak")
869 aCounters.Add (OSD_MemInfo::MemWorkingSetPeak);
871 else if (anArg == "swap")
873 aCounters.Add (OSD_MemInfo::MemSwapUsage);
875 else if (anArg == "swappeak")
877 aCounters.Add (OSD_MemInfo::MemSwapUsagePeak);
879 else if (anArg == "private")
881 aCounters.Add (OSD_MemInfo::MemPrivate);
885 theDI << "Syntax error at '" << theArgVec[anIter] << "'!\n";
890 OSD_MemInfo aMemInfo (Standard_False);
891 aMemInfo.SetActive (Standard_False);
892 for (NCollection_Map<OSD_MemInfo::Counter>::Iterator aCountersIt (aCounters); aCountersIt.More(); aCountersIt.Next())
894 aMemInfo.SetActive (aCountersIt.Value(), Standard_True);
898 for (NCollection_Map<OSD_MemInfo::Counter>::Iterator aCountersIt (aCounters); aCountersIt.More(); aCountersIt.Next())
900 theDI << Standard_Real (aMemInfo.Value (aCountersIt.Value())) << " ";
906 //==============================================================================
907 //function : dparallel
909 //==============================================================================
910 static int dparallel (Draw_Interpretor& theDI,
911 Standard_Integer theArgNb,
912 const char** theArgVec)
914 const Handle(OSD_ThreadPool)& aDefPool = OSD_ThreadPool::DefaultPool();
917 theDI << "NbLogicalProcessors: " << OSD_Parallel::NbLogicalProcessors() << "\n"
918 << "NbThreads: " << aDefPool->NbThreads() << "\n"
919 << "NbDefThreads: " << aDefPool->NbDefaultThreadsToLaunch() << "\n"
920 << "UseOcct: " << (OSD_Parallel::ToUseOcctThreads() ? 1 : 0);
924 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
926 TCollection_AsciiString anArg (theArgVec[anIter]);
928 if (anIter + 1 < theArgNb
929 && (anArg == "-nbthreads"
930 || anArg == "-threads"))
932 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
933 aDefPool->Init (aVal);
935 else if (anIter + 1 < theArgNb
936 && (anArg == "-nbdefthreads"
937 || anArg == "-defthreads"
938 || anArg == "-nbmaxdefthreads"
939 || anArg == "-maxdefthreads"))
941 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
942 if (aVal <= 0 || aVal > aDefPool->NbThreads())
944 Message::SendFail() << "Syntax error: maximum number of threads to use should be <= of threads in the pool";
947 aDefPool->SetNbDefaultThreadsToLaunch (aVal);
949 else if (anIter + 1 < theArgNb
950 && (anArg == "-useocct"
951 || anArg == "-touseocct"
952 || anArg == "-occt"))
954 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
955 OSD_Parallel::SetUseOcctThreads (aVal == 1);
956 if (OSD_Parallel::ToUseOcctThreads() != (aVal == 1))
958 std::cout << "Warning: unable to switch threads library - no options available\n";
961 else if (anIter + 1 < theArgNb
962 && (anArg == "-usetbb"
963 || anArg == "-tousetbb"
966 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
967 OSD_Parallel::SetUseOcctThreads (aVal == 0);
968 if (OSD_Parallel::ToUseOcctThreads() != (aVal == 0))
970 std::cout << "Warning: unable to switch threads library - no options available\n";
975 Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
982 //==============================================================================
985 //==============================================================================
987 static int dperf (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
989 // reset if argument is provided and it is not '0'
990 int reset = (theArgNb > 1 ? theArgVec[1][0] != '0' && theArgVec[1][0] != '\0' : 0);
992 perf_sprint_all_meters (buffer, 25600 - 1, reset);
997 //==============================================================================
998 //function : dsetsignal
1000 //==============================================================================
1002 static int dsetsignal (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
1004 OSD_SignalMode aMode = OSD_SignalMode_Set;
1005 Standard_Boolean aSetFPE = OSD::ToCatchFloatingSignals();
1006 Standard_Integer aStackLen = OSD::SignalStackTraceLength();
1008 // default for FPE signal is defined by CSF_FPE variable, if set
1009 OSD_Environment aEnv("CSF_FPE");
1010 TCollection_AsciiString aEnvStr = aEnv.Value();
1011 if (!aEnvStr.IsEmpty())
1013 aSetFPE = (aEnvStr.Value(1) != '0');
1017 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1019 TCollection_AsciiString anArg(theArgVec[anArgIter]);
1021 if (anArg == "asis")
1023 aMode = OSD_SignalMode_AsIs;
1025 else if (anArg == "set")
1027 aMode = OSD_SignalMode_Set;
1029 else if (anArg == "unhandled")
1031 aMode = OSD_SignalMode_SetUnhandled;
1033 else if (anArg == "unset")
1035 aMode = OSD_SignalMode_Unset;
1037 else if (anArg == "1" || anArg == "on")
1039 aSetFPE = Standard_True;
1041 else if (anArg == "0" || anArg == "off")
1043 aSetFPE = Standard_False;
1045 else if (anArg == "default")
1048 else if (anArgIter + 1 < theArgNb
1049 && (anArg == "-stracktracelength"
1050 || anArg == "-stracktracelen"
1051 || anArg == "-stracklength"
1052 || anArg == "-stracklen"))
1054 aStackLen = Draw::Atoi (theArgVec[++anArgIter]);
1058 Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
1063 OSD::SetSignal(aMode, aSetFPE);
1064 OSD::SetSignalStackTraceLength (aStackLen);
1066 // report actual status in the end
1067 const char* aModeStr = 0;
1068 switch (OSD::SignalMode())
1071 case OSD_SignalMode_AsIs: aModeStr = "asis"; break;
1072 case OSD_SignalMode_Set: aModeStr = "set"; break;
1073 case OSD_SignalMode_SetUnhandled: aModeStr = "unhandled"; break;
1074 case OSD_SignalMode_Unset: aModeStr = "unset"; break;
1076 theDI << "Signal mode: " << aModeStr << "\n"
1077 << "Catch FPE: " << (OSD::ToCatchFloatingSignals() ? "1" : "0") << "\n"
1078 << "Stack Trace Length: " << aStackLen << "\n";
1082 //==============================================================================
1083 //function : dtracelevel
1085 //==============================================================================
1087 static int dtracelevel (Draw_Interpretor& theDI,
1088 Standard_Integer theArgNb,
1089 const char** theArgVec)
1091 Message_Gravity aLevel = Message_Info;
1092 if (theArgNb < 1 || theArgNb > 2)
1094 Message::SendFail() << "Error: wrong number of arguments! See usage:";
1095 theDI.PrintHelp (theArgVec[0]);
1098 else if (theArgNb == 2)
1100 TCollection_AsciiString aVal (theArgVec[1]);
1102 if (aVal == "trace")
1104 aLevel = Message_Trace;
1106 else if (aVal == "info")
1108 aLevel = Message_Info;
1110 else if (aVal == "warn"
1111 || aVal == "warning")
1113 aLevel = Message_Warning;
1115 else if (aVal == "alarm")
1117 aLevel = Message_Alarm;
1119 else if (aVal == "fail")
1121 aLevel = Message_Fail;
1125 Message::SendFail() << "Error: unknown gravity '" << theArgVec[1] << "'";
1130 Handle(Message_Messenger) aMessenger = Message::DefaultMessenger();
1131 if (aMessenger.IsNull())
1133 Message::SendFail() << "Error: default messenger is unavailable";
1137 Message_SequenceOfPrinters& aPrinters = aMessenger->ChangePrinters();
1138 if (aPrinters.Length() < 1)
1140 Message::SendFail() << "Error: no printers registered in default Messenger";
1144 for (Standard_Integer aPrinterIter = 1; aPrinterIter <= aPrinters.Length(); ++aPrinterIter)
1146 Handle(Message_Printer)& aPrinter = aPrinters.ChangeValue (aPrinterIter);
1149 if (aPrinterIter == 1)
1151 aLevel = aPrinter->GetTraceLevel();
1153 else if (aLevel == aPrinter->GetTraceLevel())
1158 switch (aPrinter->GetTraceLevel())
1160 case Message_Trace: theDI << "trace"; break;
1161 case Message_Info: theDI << "info"; break;
1162 case Message_Warning: theDI << "warn"; break;
1163 case Message_Alarm: theDI << "alarm"; break;
1164 case Message_Fail: theDI << "fail"; break;
1169 aPrinter->SetTraceLevel (aLevel);
1175 //==============================================================================
1176 //function : ddebugtraces
1178 //==============================================================================
1179 static int ddebugtraces (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
1183 theDI << Standard_Failure::DefaultStackTraceLength();
1186 else if (theArgNb != 2)
1188 theDI << "Syntax error: wrong number of arguments";
1192 Standard_Failure::SetDefaultStackTraceLength (Draw::Atoi (theArgVec[1]));
1196 //==============================================================================
1199 //==============================================================================
1200 static int dputs (Draw_Interpretor& theDI,
1201 Standard_Integer theArgNb,
1202 const char** theArgVec)
1204 Standard_OStream* aStream = &std::cout;
1205 bool isNoNewline = false, toIntense = false;
1206 Message_ConsoleColor aColor = Message_ConsoleColor_Default;
1207 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
1209 TCollection_AsciiString anArg (theArgVec[anArgIter]);
1211 if (anArg == "-nonewline")
1215 else if (anArg == "stdcout")
1217 aStream = &std::cout;
1219 else if (anArg == "stdcerr")
1221 aStream = &std::cerr;
1223 else if (anArg == "-intense")
1227 else if (anArg == "-black")
1229 aColor = Message_ConsoleColor_Black;
1231 else if (anArg == "-white")
1233 aColor = Message_ConsoleColor_White;
1235 else if (anArg == "-red")
1237 aColor = Message_ConsoleColor_Red;
1239 else if (anArg == "-blue")
1241 aColor = Message_ConsoleColor_Blue;
1243 else if (anArg == "-green")
1245 aColor = Message_ConsoleColor_Green;
1247 else if (anArg == "-yellow")
1249 aColor = Message_ConsoleColor_Yellow;
1251 else if (anArg == "-cyan")
1253 aColor = Message_ConsoleColor_Cyan;
1255 else if (anArg == "-magenta")
1257 aColor = Message_ConsoleColor_Magenta;
1259 else if (anArgIter + 1 == theArgNb)
1261 if (!theDI.ToColorize())
1264 aColor = Message_ConsoleColor_Default;
1266 if (toIntense || aColor != Message_ConsoleColor_Default)
1268 Message_PrinterOStream::SetConsoleTextColor (aStream, aColor, toIntense);
1271 *aStream << theArgVec[anArgIter];
1274 *aStream << std::endl;
1277 if (toIntense || aColor != Message_ConsoleColor_Default)
1279 Message_PrinterOStream::SetConsoleTextColor (aStream, Message_ConsoleColor_Default, false);
1285 Message::SendFail() << "Syntax error at '" << anArg << "'";
1290 Message::SendFail() << "Syntax error: wrong number of arguments";
1294 void Draw::BasicCommands(Draw_Interpretor& theCommands)
1296 static Standard_Boolean Done = Standard_False;
1298 Done = Standard_True;
1300 std::ios::sync_with_stdio();
1302 const char* g = "DRAW General Commands";
1304 theCommands.Add("batch", "returns 1 in batch mode",
1305 __FILE__,ifbatch,g);
1306 theCommands.Add("spy","spy [file], Save commands in file. no file close",
1308 theCommands.Add("wait","wait [time(10)], wait time seconds",
1309 __FILE__,Draw_wait,g);
1310 theCommands.Add("cpulimit","cpulimit [nbseconds], no args remove limits",
1311 __FILE__,cpulimit,g);
1313 const char* aChronoHelp =
1314 "chrono Name [-start] [-stop] [-reset] [-restart] [-counter Text]"
1315 "\n\t\t: [-show] [-elapsed] [-userCPU] [-sysCPU]"
1316 "\n\t\t: [-thread|-process {0|1}]"
1317 "\n\t\t: Operates named timer:"
1318 "\n\t\t: -start starts (resumes) timer"
1319 "\n\t\t: -stop stops (pauses) timer"
1320 "\n\t\t: -reset resets timer progress"
1321 "\n\t\t: -restart resets and starts timer"
1322 "\n\t\t: -show prints timer progress"
1323 "\n\t\t: ('dchrono' puts into Tcl, 'chrono' puts into std::cout)"
1324 "\n\t\t: -elapsed prints elapsed time in seconds"
1325 "\n\t\t: -userCPU prints user CPU time in seconds"
1326 "\n\t\t: -sysCPU prints system CPU time in seconds"
1327 "\n\t\t: -counter prints 'COUNTER <Text>'"
1328 "\n\t\t: -thread stops timer and sets measuring of CPU time for this thread only (FALSE by default)"
1329 "\n\t\t: -process stops timer and sets measuring of CPU time for all threads (TRUE by default)"
1330 "\n\t\t: Without arguments enables / disables global timer for all DRAW commands."
1331 "\n\t\t: chrono {0|1}"
1332 "\n\t\t: Typical usage:"
1333 "\n\t\t: chrono t -restart"
1334 "\n\t\t: <algorithm>"
1335 "\n\t\t: chrono t -stop -show";
1336 theCommands.Add("chrono", aChronoHelp,
1337 __FILE__,dchronom,g);
1338 theCommands.Add("dchrono", aChronoHelp,
1339 __FILE__,dchronom,g);
1340 theCommands.Add("mallochook",
1341 "debug memory allocation/deallocation, w/o args for help",
1342 __FILE__, mallochook, g);
1343 theCommands.Add ("meminfo",
1344 "meminfo [virt|v] [heap|h] [wset|w] [wsetpeak] [swap] [swappeak] [private]"
1345 " : memory counters for this process",
1346 __FILE__, dmeminfo, g);
1347 theCommands.Add("dperf","dperf [reset] -- show performance counters, reset if argument is provided",
1349 theCommands.Add("dsetsignal",
1350 "dsetsignal [{asIs|set|unhandled|unset}=set] [{0|1|default=$CSF_FPE}]"
1351 "\n\t\t: [-strackTraceLength Length]"
1352 "\n\t\t: Sets OSD signal handler, with FPE option if argument is given."
1353 "\n\t\t: -strackTraceLength specifies length of stack trace to put into exceptions redirected from signals.",
1354 __FILE__,dsetsignal,g);
1356 theCommands.Add("dparallel",
1357 "dparallel [-occt {0|1}] [-nbThreads Count] [-nbDefThreads Count]"
1358 "\n\t\t: Manages global parallelization parameters:"
1359 "\n\t\t: -occt use OCCT implementation or external library (if available)"
1360 "\n\t\t: -nbThreads specify the number of threads in default thread pool"
1361 "\n\t\t: -nbDefThreads specify the upper limit of threads to be used for default thread pool"
1362 "\n\t\t: within single parallelization call (should be <= of overall number of threads),"
1363 "\n\t\t: so that nested algorithm can also use this pool",
1364 __FILE__,dparallel,g);
1366 // Logging commands; note that their names are hard-coded in the code
1367 // of Draw_Interpretor, thus should not be changed without update of that code!
1368 theCommands.Add("dlog", "manage logging of commands and output; run without args to get help",
1370 theCommands.Add("decho", "switch on / off echo of commands to cout; run without args to get help",
1372 theCommands.Add("dtracelevel", "dtracelevel [trace|info|warn|alarm|fail]",
1373 __FILE__, dtracelevel, g);
1374 theCommands.Add("ddebugtraces",
1375 "ddebugtraces nbTraces"
1376 "\n\t\t: Sets the number of lines for the stack trace within Standard_Failure constructor."
1377 "\n\t\t: Intended for debug purposes.",
1378 __FILE__, ddebugtraces, g);
1380 theCommands.Add("dbreak", "raises Tcl exception if user has pressed Control-Break key",
1382 theCommands.Add("dversion", "provides information on OCCT build configuration (version, compiler, OS, C library, etc.)",
1383 __FILE__,dversion,g);
1384 theCommands.Add("dlocale", "set and / or query locate of C subsystem (function setlocale())",
1385 __FILE__,dlocale,g);
1387 theCommands.Add("dputs",
1388 "dputs [-intense] [-black|-white|-red|-green|-blue|-yellow|-cyan|-magenta]"
1389 "\n\t\t: [-nonewline] [stdcout|stdcerr] text"
1390 "\n\t\t: Puts text into console output",