• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 package ohos.devtools.services.hiperf;
17 
18 import ohos.devtools.datasources.transport.grpc.service.HiperfReport;
19 import ohos.devtools.datasources.utils.profilerlog.ProfilerLogManager;
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 
23 import java.io.File;
24 import java.io.IOException;
25 import java.nio.ByteBuffer;
26 import java.sql.Connection;
27 import java.sql.PreparedStatement;
28 import java.sql.SQLException;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.List;
33 
34 /**
35  * Trace File Parse
36  *
37  * @since 2021/8/20 18:00
38  */
39 public class HiperfParse extends ParsePerf {
40     /**
41      * Log
42      */
43     private static final Logger LOGGER = LogManager.getLogger(HiperfParse.class);
44 
45     /**
46      * File Head Sign
47      */
48     private static final String HEAD = "HIPERF_PB_";
49 
50     /**
51      * File Struct List
52      */
53     private final Map<Integer, HiperfReport.SymbolTableFile> mFiles = new HashMap<>();
54 
55     /**
56      * Thread Struct List
57      */
58     private final Map<Integer, HiperfReport.VirtualThreadInfo> mThreads = new HashMap<>();
59 
60     /**
61      * Sample Struct List
62      */
63     private final List<HiperfReport.CallStackSample> mSamples = new ArrayList<>();
64 
65     /**
66      * Parse trace File
67      *
68      * @param trace trace file
69      * @throws IOException io
70      */
parseFile(File trace)71     public void parseFile(File trace) throws IOException {
72         if (ProfilerLogManager.isInfoEnabled()) {
73             LOGGER.info("parseFile");
74         }
75         if (trace == null || !trace.isFile()) {
76             return;
77         }
78         ByteBuffer buffer = byteBufferFromFile(trace);
79         verifyHead(buffer, HEAD);
80         // myTraceVersion
81         buffer.getShort();
82         int recordSize = buffer.getInt();
83         long sampleCount = 0L;
84         while (recordSize != 0) {
85             byte[] recordBytes = new byte[recordSize];
86             buffer.get(recordBytes);
87             HiperfReport.HiperfRecord record = HiperfReport.HiperfRecord.parseFrom(recordBytes);
88 
89             switch (record.getRecordTypeCase()) {
90                 case FILE:
91                     HiperfReport.SymbolTableFile file = record.getFile();
92                     mFiles.put(file.getId(), file);
93                     break;
94                 case STATISTIC:
95                     HiperfReport.SampleStatistic situation = record.getStatistic();
96                     sampleCount = situation.getCount();
97                     break;
98                 case SAMPLE:
99                     HiperfReport.CallStackSample sample = record.getSample();
100                     mSamples.add(sample);
101                     break;
102                 case THREAD:
103                     HiperfReport.VirtualThreadInfo thread = record.getThread();
104                     mThreads.put(thread.getTid(), thread);
105                     break;
106                 default:
107                     LOGGER.info("Lost Case");
108             }
109             recordSize = buffer.getInt();
110         }
111 
112         if (mSamples.size() != sampleCount) {
113             throw new IllegalStateException("Samples count doesn't match the number of samples read.");
114         }
115     }
116 
117     /**
118      * insertPerfSample
119      */
insertSample()120     public void insertSample() {
121         Connection conn = PerfDAO.getInstance().getConn();
122         try {
123             PreparedStatement callChainPst = conn.prepareStatement(
124                     "insert into "
125                             + "perf_callchain("
126                             + "sample_id, "
127                             + "callchain_id, "
128                             + "vaddr_in_file, "
129                             + "file_id, "
130                             + "symbol_id) "
131                             + "values(?,?,?,?,?)");
132             conn.setAutoCommit(false);
133 
134             PreparedStatement samplePst = conn.prepareStatement(
135                     "insert into "
136                             + "perf_sample("
137                             + "sample_id, "
138                             + "timestamp, "
139                             + "thread_id, "
140                             + "event_count, "
141                             + "event_type_id) "
142                             + "values(?,?,?,?,?)");
143             conn.setAutoCommit(false);
144 
145             // sample
146             getSamplePst(samplePst, callChainPst);
147 
148             // files
149             PreparedStatement filePst = getFilePst(conn);
150             // thread
151             PreparedStatement threadPst = getThreadPst(conn);
152             try {
153                 samplePst.executeBatch();
154                 callChainPst.executeBatch();
155                 filePst.executeBatch();
156                 threadPst.executeBatch();
157                 conn.commit();
158             } catch (SQLException exception) {
159                 if (ProfilerLogManager.isErrorEnabled()) {
160                     LOGGER.error(exception.getMessage());
161                 }
162             } finally {
163                 if (samplePst != null) {
164                     samplePst.close();
165                 }
166                 conn.close();
167             }
168         } catch (SQLException exception) {
169             if (ProfilerLogManager.isErrorEnabled()) {
170                 LOGGER.error(exception.getMessage());
171             }
172         }
173     }
174 
175 
getThreadPst(Connection conn)176     private PreparedStatement getThreadPst(Connection conn) throws SQLException {
177         PreparedStatement threadPst = conn.prepareStatement(
178                 "insert into "
179                         + "perf_thread("
180                         + "thread_id, "
181                         + "process_id, "
182                         + "thread_name) "
183                         + "values(?,?,?)");
184         conn.setAutoCommit(false);
185         mThreads.values().forEach(thread -> {
186             try {
187                 threadPst.setInt(1, thread.getTid());
188                 threadPst.setInt(2, thread.getPid());
189                 threadPst.setString(3, thread.getName());
190                 threadPst.addBatch();
191             } catch (SQLException exception) {
192                 if (ProfilerLogManager.isErrorEnabled()) {
193                     LOGGER.error(exception.getMessage());
194                 }
195             }
196         });
197         return threadPst;
198     }
199 
getFilePst(Connection conn)200     private PreparedStatement getFilePst(Connection conn) throws SQLException {
201         PreparedStatement filePst = conn.prepareStatement(
202                 "insert into "
203                         + "perf_files("
204                         + "file_id, "
205                         + "symbol, "
206                         + "path) "
207                         + "values(?,?,?)");
208         conn.setAutoCommit(false);
209         mFiles.values().forEach(perffile -> {
210             perffile.getFunctionNameList().forEach(function -> {
211                 try {
212                     filePst.setInt(1, perffile.getId());
213                     filePst.setString(2, function);
214                     filePst.setString(3, perffile.getPath());
215                     filePst.addBatch();
216                 } catch (SQLException exception) {
217                     if (ProfilerLogManager.isErrorEnabled()) {
218                         LOGGER.error(exception.getMessage());
219                     }
220                 }
221             });
222         });
223         return filePst;
224     }
225 
getSamplePst(PreparedStatement samplePst, PreparedStatement callChainPst)226     private void getSamplePst(PreparedStatement samplePst, PreparedStatement callChainPst) {
227         for (int sampleId = 0; sampleId < mSamples.size(); sampleId++) {
228             HiperfReport.CallStackSample sample = mSamples.get(sampleId);
229             try {
230                 samplePst.setLong(1, sampleId);
231                 samplePst.setLong(2, sample.getTime());
232                 samplePst.setInt(3, sample.getTid());
233                 samplePst.setLong(4, sample.getEventCount());
234                 samplePst.setInt(5, sample.getConfigNameId());
235                 samplePst.addBatch();
236                 for (int callChainId = 0; callChainId < sample.getCallStackFrameList().size(); callChainId++) {
237                     HiperfReport.CallStackSample.CallStackFrame callChain =
238                             sample.getCallStackFrameList().get(callChainId);
239                     callChainPst.setLong(1, sampleId);
240                     callChainPst.setLong(2, callChainId);
241                     callChainPst.setLong(3, callChain.getSymbolsVaddr());
242                     callChainPst.setLong(4, callChain.getSymbolsFileId());
243                     callChainPst.setInt(5, callChain.getFunctionNameId());
244                     callChainPst.addBatch();
245                 }
246             } catch (SQLException exception) {
247                 if (ProfilerLogManager.isErrorEnabled()) {
248                     LOGGER.error(exception.getMessage());
249                 }
250             }
251         }
252     }
253 }
254