1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_MODULE_MODULE_LOGGER_H
17 #define ECMASCRIPT_MODULE_MODULE_LOGGER_H
18 
19 #include "ecmascript/module/js_module_source_text.h"
20 
21 #include <fstream>
22 namespace panda::ecmascript {
23 
24 struct ModuleLoadInfo {
25     bool isUsed {false};
26     CSet<CString> parentModules {};
27     CMap<CString, CSet<CString>> upLevel {}; // parent module and importName
28     double time {0};
29 };
30 
31 class ModuleLogger {
32 public:
33     explicit ModuleLogger(EcmaVM *vm);
~ModuleLogger()34     ~ModuleLogger()
35     {
36         for (auto &info : jsModuleLoadInfo_) {
37             delete info.second;
38         }
39         jsModuleLoadInfo_.clear();
40     }
41     void SetStartTime(const CString &recordName);
42     void SetEndTime(const CString &recordName);
43     void PostModuleLoggerTask(int32_t id, EcmaVM *vm);
44     void InsertModuleLoadInfo(JSHandle<SourceTextModule> currentModule,
45                               JSHandle<SourceTextModule> exportModule,
46                               int32_t index);
47     void InsertParentModule(JSHandle<SourceTextModule> currentModule, JSHandle<SourceTextModule> requiredModule);
48     void InsertEntryPointModule(JSHandle<SourceTextModule> currentModule);
49     void PrintModuleLoadInfo();
50     static std::string ToStringWithPrecision(const double num, const uint8_t n);
51 
52 private:
53     static constexpr const int MILLISECONDS_PER_SEC = 1000;
54     static constexpr const double DOUBLE_MILLISECONDS_PER_SEC = 1000.0;
55     static constexpr const int TWO = 2;
56     static constexpr const int THREE = 3;
57     static constexpr const double TWO_SECONDS = TWO * MILLISECONDS_PER_SEC * MILLISECONDS_PER_SEC;
58     static constexpr const char FILEDIR[] = "/data/storage/el2/base/files/";
59     static constexpr const char SUFFIX[] = "_redundant_file.txt";
60 
61     NO_COPY_SEMANTIC(ModuleLogger);
62     NO_MOVE_SEMANTIC(ModuleLogger);
63 
64     bool CreateResultFile(std::string &path) const; // first time
65     bool OpenResultFile(std::string &path) const;
66     ModuleLoadInfo *GetModuleLoadInfo(const CString &recordName);
67 
68     void PrintSummary() const;
69     void PrintUsedFileInfo() const;
70     void PrintUnusedFileInfo() const;
71     void ProcessModuleExecuteTime();
72     EcmaVM *vm_ {nullptr};
73     CUnorderedMap<CString, ModuleLoadInfo*> jsModuleLoadInfo_ {};
74     uint32_t totalFileNumber_ {0};
75     uint32_t unusedFileNumber_ {0};
76     uint32_t usedFileNumber_ {0};
77     int64_t totalTime_ {0};
78     int64_t usedFileTime_ {0};
79     int64_t unusedFileTime_ {0};
80     Mutex mutex_;
81 
82     class ModuleLoggerTask : public Task {
83     public:
ModuleLoggerTask(int32_t id, EcmaVM *vm)84         ModuleLoggerTask(int32_t id, EcmaVM *vm)
85             : Task(id), vm_(vm) {}
86         ~ModuleLoggerTask() override = default;
87         bool Run([[maybe_unused]]uint32_t threadIndex) override;
88 
89         NO_COPY_SEMANTIC(ModuleLoggerTask);
90         NO_MOVE_SEMANTIC(ModuleLoggerTask);
91     private:
92         EcmaVM *vm_ {nullptr};
93     };
94 };
95 } // namespace panda::ecmascript
96 #endif // ECMASCRIPT_MODULE_MODULE_LOGGER_H
97