Add basic output of where memory is stored after a compile. (#4136)

The output is really basic, I'm just adding this to help track how
memory is allocated.

```
---
filename:        'check/testdata/expr_category/in_place_tuple_init.carbon'
source_:
  used_bytes:      8057
  reserved_bytes:  8057
tokens_.allocator_:
  used_bytes:      0
  reserved_bytes:  0
tokens_.token_infos_:
  used_bytes:      1040
  reserved_bytes:  2032

(eliding)

value_stores_.string_literals_.set_:
  used_bytes:      320
  reserved_bytes:  320
Total:
  used_bytes:      20609
  reserved_bytes:  29437
...
```

---------

Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
This commit is contained in:
Jon Ross-Perkins
2024-07-16 23:11:01 +00:00
committed by GitHub
co-authored by josh11b
parent cd7c10b8e2
commit f1190a4792
20 changed files with 354 additions and 2 deletions
+36 -2
View File
@@ -308,6 +308,14 @@ Dump the generated assembly to stdout after codegen.
)""",
},
[&](auto& arg_b) { arg_b.Set(&dump_asm); });
b.AddFlag(
{
.name = "dump-mem-usage",
.help = R"""(
Dumps the amount of memory used.
)""",
},
[&](auto& arg_b) { arg_b.Set(&dump_mem_usage); });
b.AddFlag(
{
.name = "prelude-import",
@@ -344,6 +352,7 @@ Excludes files with the given prefix from dumps.
bool dump_sem_ir = false;
bool dump_llvm_ir = false;
bool dump_asm = false;
bool dump_mem_usage = false;
bool stream_errors = false;
bool preorder_parse_tree = false;
bool builtin_sem_ir = false;
@@ -540,6 +549,9 @@ class Driver::CompilationUnit {
sorting_consumer_ = SortingDiagnosticConsumer(*consumer);
consumer_ = &*sorting_consumer_;
}
if (options_.dump_mem_usage && IncludeInDumps()) {
mem_usage_ = MemUsage();
}
}
// Loads source and lexes it. Returns true on success.
@@ -552,6 +564,10 @@ class Driver::CompilationUnit {
*consumer_);
}
});
if (mem_usage_) {
mem_usage_->Add("source_", source_->text().size(),
source_->text().size());
}
if (!source_) {
success_ = false;
return;
@@ -565,6 +581,9 @@ class Driver::CompilationUnit {
consumer_->Flush();
driver_->output_stream_ << tokens_;
}
if (mem_usage_) {
mem_usage_->Collect("tokens_", *tokens_);
}
CARBON_VLOG() << "*** Lex::TokenizedBuffer ***\n" << tokens_;
if (tokens_->has_errors()) {
success_ = false;
@@ -582,6 +601,9 @@ class Driver::CompilationUnit {
consumer_->Flush();
parse_tree_->Print(driver_->output_stream_, options_.preorder_parse_tree);
}
if (mem_usage_) {
mem_usage_->Collect("parse_tree_", *parse_tree_);
}
CARBON_VLOG() << "*** Parse::Tree ***\n" << parse_tree_;
if (parse_tree_->has_errors()) {
success_ = false;
@@ -607,8 +629,12 @@ class Driver::CompilationUnit {
// to wait for code generation.
consumer_->Flush();
CARBON_VLOG() << "*** Raw SemIR::File ***\n" << *sem_ir_ << "\n";
if (mem_usage_) {
mem_usage_->Collect("sem_ir_", *sem_ir_);
}
if (options_.dump_raw_sem_ir && IncludeInDumps()) {
CARBON_VLOG() << "*** Raw SemIR::File ***\n" << *sem_ir_ << "\n";
sem_ir_->Print(driver_->output_stream_, options_.builtin_sem_ir);
if (options_.dump_sem_ir) {
driver_->output_stream_ << "\n";
@@ -659,11 +685,16 @@ class Driver::CompilationUnit {
// Runs post-compile logic. This is always called, and called after all other
// actions on the CompilationUnit.
auto PostCompile() const -> void {
auto PostCompile() -> void {
if (options_.dump_shared_values && IncludeInDumps()) {
Yaml::Print(driver_->output_stream_,
value_stores_.OutputYaml(input_filename_));
}
if (mem_usage_) {
mem_usage_->Collect("value_stores_", value_stores_);
Yaml::Print(driver_->output_stream_,
mem_usage_->OutputYaml(input_filename_));
}
// The diagnostics consumer must be flushed before compilation artifacts are
// destructed, because diagnostics can refer to their state.
@@ -773,6 +804,9 @@ class Driver::CompilationUnit {
bool success_ = true;
// Tracks memory usage of the compile.
std::optional<MemUsage> mem_usage_;
// These are initialized as steps are run.
std::optional<SourceBuffer> source_;
std::optional<Lex::TokenizedBuffer> tokens_;