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