1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <sal/config.h>
11 
12 #include <atomic>
13 
14 #include <comphelper/sequence.hxx>
15 #include <comphelper/profilezone.hxx>
16 #include <osl/time.h>
17 #include <osl/thread.h>
18 
19 namespace comphelper
20 {
21 
22 std::atomic<bool> ProfileZone::g_bRecording(false);
23 
24 namespace ProfileRecording
25 {
26 
27 static std::vector<OUString> g_aRecording;    // recorded data
28 static long long g_aSumTime(0);  // overall zone time in microsec
29 static int g_aNesting;           // level of overlapped zones
30 static long long g_aStartTime;                // start time of recording
31 static ::osl::Mutex g_aMutex;
32 
startRecording(bool bStartRecording)33 void startRecording(bool bStartRecording)
34 {
35     if (bStartRecording)
36     {
37         TimeValue systemTime;
38         osl_getSystemTime( &systemTime );
39         ::osl::MutexGuard aGuard( g_aMutex );
40         g_aStartTime = static_cast<long long>(systemTime.Seconds) * 1000000 + systemTime.Nanosec/1000;
41         g_aNesting = 0;
42     }
43     ProfileZone::g_bRecording = bStartRecording;
44 }
45 
addRecording(const char * aProfileId,long long aCreateTime)46 long long addRecording(const char * aProfileId, long long aCreateTime)
47 {
48     assert( ProfileZone::g_bRecording );
49 
50     TimeValue systemTime;
51     osl_getSystemTime( &systemTime );
52     long long aTime = static_cast<long long>(systemTime.Seconds) * 1000000 + systemTime.Nanosec/1000;
53 
54     if (!aProfileId)
55         aProfileId = "(null)";
56     OUString aString(aProfileId, strlen(aProfileId), RTL_TEXTENCODING_UTF8);
57 
58     OUString sRecordingData(OUString::number(osl_getThreadIdentifier(nullptr)) + " " +
59         OUString::number(aTime/1000000.0) + " " + aString + ": " +
60         (aCreateTime == 0 ? OUStringLiteral("start") : OUStringLiteral("stop")) +
61         (aCreateTime != 0 ? (" " + OUString::number((aTime - aCreateTime)/1000.0) + " ms") : OUString("")));
62 
63     ::osl::MutexGuard aGuard( g_aMutex );
64 
65     g_aRecording.emplace_back(sRecordingData);
66     if (aCreateTime == 0)
67     {
68         g_aNesting++;
69         return aTime;
70     }
71     // neglect ProfileZones created before startRecording
72     else if (aCreateTime >= g_aStartTime)
73     {
74         if (g_aNesting > 0)
75             g_aNesting--;
76         if (g_aNesting == 0)
77             g_aSumTime += aTime - aCreateTime;
78     }
79     return 0;
80 }
81 
getRecordingAndClear()82 css::uno::Sequence<OUString> getRecordingAndClear()
83 {
84     bool bRecording;
85     std::vector<OUString> aRecording;
86     {
87         ::osl::MutexGuard aGuard( g_aMutex );
88         bRecording = ProfileZone::g_bRecording;
89         startRecording(false);
90         aRecording.swap(g_aRecording);
91         long long aSumTime = g_aSumTime;
92         aRecording.insert(aRecording.begin(), OUString::number(aSumTime/1000000.0));
93     }
94     // reset start time and nesting level
95     startRecording(bRecording);
96     return ::comphelper::containerToSequence(aRecording);
97 }
98 
99 } // namespace ProfileRecording
100 
101 
102 } // namespace comphelper
103 
104 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
105