clayborg added inline comments.
================ Comment at: lldb/include/lldb/Target/TraceHTR.h:41 + size_t m_num_instructions; + std::unordered_map<std::string, size_t> m_func_calls; + friend llvm::json::Value toJSON(const HTRBlockMetadata &metadata); ---------------- wallace wrote: > jj10306 wrote: > > clayborg wrote: > > > Use ConstString here instead of std::string. std::string will make a copy > > > of the string. ConstString objects should always be used for storing > > > function and type names as a constant string pool will unique any strings > > > that are placed into a ConstString. This will avoid consuming more memory > > > for these traces and ConstString also is much more efficient for > > > comparing strings for equality if that is needed anywhere. > > I tried using `ConstString` here, but I was running into issues because I > > don't believe there's a hash implementation for `ConstString` so it's > > unable to be the key type for an `unordered_map`. I'm considering using a > > `map` instead which should allow the use of `ConstString`, but at the cost > > of performance because lookups in these map are done quite often (every > > time two blocks are merged). What are your thoughts? > See my comment above, this is too memory expensive The constant string pool uses llvm::StringMap which ends up using "uint32_t llvm::djbHash(StringRef)". That being said, I would try and use the llvm::DenseMap instead of std::unordered_map since we already wrote the needed hashing accessors for it (search for "template <> struct DenseMapInfo<lldb_private::ConstString>" in the ConstString.h file for details). ================ Comment at: lldb/include/lldb/Target/TraceHTR.h:68 + template <class M> friend llvm::json::Value toJSON(const TraceHTR<M> &layer); + template <class B> friend llvm::json::Value toJSON(const HTRBlock<B> &block); +}; ---------------- ah yes. Makes sense. ================ Comment at: lldb/include/lldb/Target/TraceHTR.h:73 +/// Maps the unique Block IDs to their respective Blocks +template <class TMetadata> class HTRBlockDefs { +public: ---------------- jj10306 wrote: > wallace wrote: > > clayborg wrote: > > > Does this need to be templatized? Are we using this same class with > > > multiple different TMetadata classes or are we always using it with > > > HTRBlockMetadata? > > +1 > > I don't think you should go with templates unless you had more TMetadata > > objects > Currently, the templates are not needed because we have a single metadata > type, but I added the templates to make this design extensible to different > use cases that may require different metadata. > > Since we currently have just a single metadata type, I'll go ahead and remove > the templates and if we ever need to add a new metadata type we can discuss > how to extend the design. That sounds good to me ================ Comment at: lldb/source/Commands/CommandObjectThread.cpp:2172 + + CommandObjectTraceDumpChromeTraceFormat(CommandInterpreter &interpreter) + : CommandObjectIterateOverThreads( ---------------- jj10306 wrote: > clayborg wrote: > > Instead of making a new custom command, I would say we should just add a > > "--export" option to the "thread trace dump" command that can take a export > > enumeration as its value. Possible values would be "chrome-trace-format" or > > "ctf". If we architect it correctly, we would create a Trace export plug-in > > within LLDB to allow other people to create new trace export plug-ins in > > the future. > I agree that the allowing exporting to different formats is useful, so I > think the trace export plug-in is a great idea. > > Discussed with @wallace offline and we decided for this diff we are going to > add a `thread trace export` command that has a `--format` option and in a > future diff we could add implement the plug-in logic. Sounds good! ================ Comment at: lldb/source/Target/TraceHTR.cpp:56 + int block_id = 0; + std::unordered_map<lldb::addr_t, size_t> load_address_to_block_id; + // This flag becomes true when cursor->Next() returns false ---------------- jj10306 wrote: > clayborg wrote: > > So each unique address gets added to this map? if we have many instructions > > that are in the same block like 0x1000, 0x1004 and 0x1008, we will have all > > three addresses in the map pointing to the same block ID? If we used an > > ordered_map, we could use lower_bound to find the lowest address that > > points to the block, and the block could have an address range inside of it > > that could be updated as we went along. It might end up saving memory if we > > can do it this way. > > > > So if we have: > > ``` > > 0x1000: nop > > 0x1004: nop > > 0x1008: nop > > 0x100c: call 0x2000 > > 0x2000: nop > > 0x2004: nop > > 0x2008: nop > > ``` > > This would end up with two blocks, one whose range is [0x1000-0x1010) (4 > > bytes after 0x100c), and one from [0x2000-0x200c). If we used a map the map > > could simply end up containing: > > ``` > > 0x1000 -> 1 (Block [0x1000-0x1010) > > 0x2000 -> 2 (Block [0x2000-0x200c) > > ``` > > Using an ordered_map would take a bit more logic to always update a Block's > > address range on the fly and as load addresses come in, like 0x1004, > > 0x1008, 0x100c, we would need to locate the 0x1000 entry using > > "load_address_to_block_id.lower_bound(addr)" and seeing if the block's > > address range has been finalized, and if not, update it, and if it was, > > just make sure the address is in the block. > > > > Where as right now the load_address_to_block_id would end up containing: > > ``` > > 0x1000 -> 1 > > 0x1004 -> 1 > > 0x1008 -> 1 > > 0x100c -> 1 > > 0x2000 -> 2 > > 0x2004 -> 2 > > 0x2008 -> 2 > > ``` > > I worry about the size of the load_address_to_block_id data structure if it > > isn't minimized. > Correct, each unique address gets an entry in this map. > > For the example you gave `load_address_to_block_id` would end up containing: > ``` > 0x1000 -> 0 > 0x1004 -> 1 > 0x1008 -> 2 > 0x100c -> 3 > 0x2000 -> 4 > 0x2004 -> 5 > 0x2008 -> 6 > ``` > The goal of this map is to assign each load address a new, unique id. The > idea with assigning a new unique id is that this id could be smaller in size > compared to a load address (ie 4 bytes versus 8 bytes) since the number of > unique instructions in a trace is typically significantly smaller than the > total number of instructions in a trace (<1% based on some testing I did) - > this obviously would depend on the specific trace but the high level idea is > there is potentially an opportunity to save space since it is very unlikely > that any useful trace would have more than `2^32 - 1` unique instructions. > > `size_t` is currently used as the type for the ids so this memory saving idea > isn't implemented here, but wanted to get feedback on this idea. > > For this diff, I'll go ahead and remove this map as a whole and just use the > load addresses themselves as the unique id for a block, but I'd like to keep > the idea I described above in mind for future work. Sounds good, thanks for the explanation. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D105741/new/ https://reviews.llvm.org/D105741 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits