• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_
18 #define INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_
19 
20 #include <cstdint>
21 #include <memory>
22 #include <vector>
23 
24 #include <limits.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 
28 namespace perfetto {
29 
30 namespace protos::pbzero {
31 class QueryResult;
32 }  // namespace protos::pbzero
33 
34 namespace trace_processor {
35 
36 class Iterator;
37 class IteratorImpl;
38 
39 // This class serializes a TraceProcessor query result (i.e. an Iterator)
40 // into batches of QueryResult (trace_processor.proto). This class
41 // returns results in batches, allowing to deal with O(M) results without
42 // full memory buffering. It works as follows:
43 // - The iterator is passed in the constructor.
44 // - The client is expected to call Serialize(out_buf) until EOF is reached.
45 // - For each Serialize() call, this class will serialize a batch of cells,
46 //   stopping when either when a number of cells (|cells_per_batch_|) is reached
47 //   or when the batch size exceeds (batch_split_threshold_).
48 //   A batch is guaranteed to contain a number of cells that is an integer
49 //   multiple of the column count (i.e. a batch is not truncated in the middle
50 //   of a row).
51 // The intended use case is streaaming these batches onto through a
52 // chunked-encoded HTTP response, or through a repetition of Wasm calls.
53 class QueryResultSerializer {
54  public:
55   static constexpr uint32_t kDefaultBatchSplitThreshold = 128 * 1024;
56   explicit QueryResultSerializer(Iterator);
57   ~QueryResultSerializer();
58 
59   // No copy or move.
60   QueryResultSerializer(const QueryResultSerializer&) = delete;
61   QueryResultSerializer& operator=(const QueryResultSerializer&) = delete;
62 
63   // Appends the data to the passed protozero message. It returns true if more
64   // chunks are available (i.e. it returns NOT(|eof_reached_||)). The caller is
65   // supposed to keep calling this function until it returns false.
66   bool Serialize(protos::pbzero::QueryResult*);
67 
68   // Like the above but stitches everything together in a vector. Incurs in
69   // extra copies.
70   bool Serialize(std::vector<uint8_t>*);
71 
set_batch_size_for_testing(uint32_t cells_per_batch,uint32_t thres)72   void set_batch_size_for_testing(uint32_t cells_per_batch, uint32_t thres) {
73     cells_per_batch_ = cells_per_batch;
74     batch_split_threshold_ = thres;
75   }
76 
77  private:
78   void SerializeMetadata(protos::pbzero::QueryResult*);
79   void SerializeBatch(protos::pbzero::QueryResult*);
80   void MaybeSerializeError(protos::pbzero::QueryResult*);
81 
82   std::unique_ptr<IteratorImpl> iter_;
83   const uint32_t num_cols_;
84   bool did_write_metadata_ = false;
85   bool eof_reached_ = false;
86   uint32_t col_ = UINT32_MAX;
87 
88   // These params specify the thresholds for splitting the results in batches,
89   // in terms of: (1) max cells (row x cols); (2) serialized batch size in
90   // bytes, whichever is reached first. Note also that the byte limit is not
91   // 100% accurate and can occasionally yield to batches slighly larger than
92   // the limit (it splits on the next row *after* the limit is hit).
93   // Overridable for testing only.
94   uint32_t cells_per_batch_ = 50000;
95   uint32_t batch_split_threshold_ = kDefaultBatchSplitThreshold;
96 };
97 
98 }  // namespace trace_processor
99 }  // namespace perfetto
100 
101 #endif  // INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_RPC_QUERY_RESULT_SERIALIZER_H_
102