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>
22namespace panda::ecmascript {
23
24struct 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
31class ModuleLogger {
32public:
33    explicit ModuleLogger(EcmaVM *vm);
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
52private:
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:
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