mirror of
https://github.com/rui314/mold.git
synced 2024-12-28 19:04:27 +03:00
temporary
This commit is contained in:
parent
6312ffb50c
commit
3880c4afd0
84
main.cc
84
main.cc
@ -1,8 +1,5 @@
|
|||||||
#include "mold.h"
|
#include "mold.h"
|
||||||
|
|
||||||
#include "llvm/Support/Timer.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
@ -13,30 +10,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
using llvm::Timer;
|
|
||||||
|
|
||||||
class MyTimer {
|
|
||||||
public:
|
|
||||||
MyTimer(std::string_view name) {
|
|
||||||
timer = new Timer(name, name);
|
|
||||||
timer->startTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
MyTimer(std::string_view name, llvm::TimerGroup &tg) {
|
|
||||||
timer = new Timer(name, name, tg);
|
|
||||||
timer->startTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
~MyTimer() { timer->stopTimer(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
llvm::Timer *timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
llvm::TimerGroup parse_timer("parse", "parse");
|
|
||||||
llvm::TimerGroup before_copy_timer("before_copy", "before_copy");
|
|
||||||
llvm::TimerGroup copy_timer("copy", "copy");
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Main
|
// Main
|
||||||
//
|
//
|
||||||
@ -117,7 +90,7 @@ static std::vector<std::span<T>> split(std::vector<T> &input, int unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void resolve_symbols() {
|
static void resolve_symbols() {
|
||||||
MyTimer t("resolve_symbols", before_copy_timer);
|
ScopedTimer t("resolve_symbols");
|
||||||
|
|
||||||
// Register defined symbols
|
// Register defined symbols
|
||||||
tbb::parallel_for_each(out::objs, [](ObjectFile *file) { file->resolve_symbols(); });
|
tbb::parallel_for_each(out::objs, [](ObjectFile *file) { file->resolve_symbols(); });
|
||||||
@ -145,7 +118,7 @@ static void resolve_symbols() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void eliminate_comdats() {
|
static void eliminate_comdats() {
|
||||||
MyTimer t("comdat", before_copy_timer);
|
ScopedTimer t("comdat");
|
||||||
|
|
||||||
tbb::parallel_for_each(out::objs, [](ObjectFile *file) {
|
tbb::parallel_for_each(out::objs, [](ObjectFile *file) {
|
||||||
file->resolve_comdat_groups();
|
file->resolve_comdat_groups();
|
||||||
@ -157,7 +130,7 @@ static void eliminate_comdats() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void handle_mergeable_strings() {
|
static void handle_mergeable_strings() {
|
||||||
MyTimer t("resolve_strings", before_copy_timer);
|
ScopedTimer t("resolve_strings");
|
||||||
|
|
||||||
// Resolve mergeable string pieces
|
// Resolve mergeable string pieces
|
||||||
tbb::parallel_for_each(out::objs, [](ObjectFile *file) {
|
tbb::parallel_for_each(out::objs, [](ObjectFile *file) {
|
||||||
@ -207,7 +180,7 @@ static void handle_mergeable_strings() {
|
|||||||
// An output section may contain millions of input sections.
|
// An output section may contain millions of input sections.
|
||||||
// So, we append input sections to output sections in parallel.
|
// So, we append input sections to output sections in parallel.
|
||||||
static void bin_sections() {
|
static void bin_sections() {
|
||||||
MyTimer t("bin_sections", before_copy_timer);
|
ScopedTimer t("bin_sections");
|
||||||
|
|
||||||
int unit = (out::objs.size() + 127) / 128;
|
int unit = (out::objs.size() + 127) / 128;
|
||||||
std::vector<std::span<ObjectFile *>> slices = split(out::objs, unit);
|
std::vector<std::span<ObjectFile *>> slices = split(out::objs, unit);
|
||||||
@ -246,7 +219,7 @@ static void bin_sections() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void check_duplicate_symbols() {
|
static void check_duplicate_symbols() {
|
||||||
MyTimer t("check_undef_syms", before_copy_timer);
|
ScopedTimer t("check_undef_syms");
|
||||||
|
|
||||||
auto is_error = [](ObjectFile *file, int i) {
|
auto is_error = [](ObjectFile *file, int i) {
|
||||||
const ElfSym &esym = file->elf_syms[i];
|
const ElfSym &esym = file->elf_syms[i];
|
||||||
@ -283,7 +256,7 @@ static void check_duplicate_symbols() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void set_isec_offsets() {
|
static void set_isec_offsets() {
|
||||||
MyTimer t("isec_offsets", before_copy_timer);
|
ScopedTimer t("isec_offsets");
|
||||||
|
|
||||||
tbb::parallel_for_each(OutputSection::instances, [&](OutputSection *osec) {
|
tbb::parallel_for_each(OutputSection::instances, [&](OutputSection *osec) {
|
||||||
if (osec->members.empty())
|
if (osec->members.empty())
|
||||||
@ -325,7 +298,7 @@ static void set_isec_offsets() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void scan_rels() {
|
static void scan_rels() {
|
||||||
MyTimer t("scan_rels", before_copy_timer);
|
ScopedTimer t("scan_rels");
|
||||||
|
|
||||||
// Scan relocations to find dynamic symbols.
|
// Scan relocations to find dynamic symbols.
|
||||||
tbb::parallel_for_each(out::objs, [&](ObjectFile *file) {
|
tbb::parallel_for_each(out::objs, [&](ObjectFile *file) {
|
||||||
@ -392,7 +365,7 @@ static void scan_rels() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void export_dynamic() {
|
static void export_dynamic() {
|
||||||
MyTimer t("export_dynamic", before_copy_timer);
|
ScopedTimer t("export_dynamic");
|
||||||
|
|
||||||
tbb::parallel_for(0, (int)out::objs.size(), [&](int i) {
|
tbb::parallel_for(0, (int)out::objs.size(), [&](int i) {
|
||||||
ObjectFile *file = out::objs[i];
|
ObjectFile *file = out::objs[i];
|
||||||
@ -418,7 +391,7 @@ static void export_dynamic() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void fill_symbol_versions() {
|
static void fill_symbol_versions() {
|
||||||
MyTimer t("fill_symbol_versions", before_copy_timer);
|
ScopedTimer t("fill_symbol_versions");
|
||||||
|
|
||||||
// Create a list of versioned symbols and sort by file and version.
|
// Create a list of versioned symbols and sort by file and version.
|
||||||
std::vector<Symbol *> syms = out::dynsym->symbols;
|
std::vector<Symbol *> syms = out::dynsym->symbols;
|
||||||
@ -501,7 +474,7 @@ static void fill_symbol_versions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void write_merged_strings() {
|
static void write_merged_strings() {
|
||||||
MyTimer t("write_merged_strings", copy_timer);
|
ScopedTimer t("write_merged_strings");
|
||||||
|
|
||||||
tbb::parallel_for_each(out::objs, [&](ObjectFile *file) {
|
tbb::parallel_for_each(out::objs, [&](ObjectFile *file) {
|
||||||
for (MergeableSection &isec : file->mergeable_sections) {
|
for (MergeableSection &isec : file->mergeable_sections) {
|
||||||
@ -517,7 +490,7 @@ static void write_merged_strings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void clear_padding(u64 filesize) {
|
static void clear_padding(u64 filesize) {
|
||||||
MyTimer t("clear_padding", copy_timer);
|
ScopedTimer t("clear_padding");
|
||||||
|
|
||||||
auto zero = [](OutputChunk *chunk, u64 next_start) {
|
auto zero = [](OutputChunk *chunk, u64 next_start) {
|
||||||
u64 pos = chunk->shdr.sh_offset;
|
u64 pos = chunk->shdr.sh_offset;
|
||||||
@ -550,7 +523,7 @@ static int get_section_rank(const ElfShdr &shdr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static u64 set_osec_offsets(std::span<OutputChunk *> chunks) {
|
static u64 set_osec_offsets(std::span<OutputChunk *> chunks) {
|
||||||
MyTimer t("osec_offset", before_copy_timer);
|
ScopedTimer t("osec_offset");
|
||||||
|
|
||||||
u64 fileoff = 0;
|
u64 fileoff = 0;
|
||||||
u64 vaddr = config.image_base;
|
u64 vaddr = config.image_base;
|
||||||
@ -671,7 +644,7 @@ static u32 get_umask() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static u8 *open_output_file(u64 filesize) {
|
static u8 *open_output_file(u64 filesize) {
|
||||||
MyTimer t("open_file", before_copy_timer);
|
ScopedTimer t("open_file");
|
||||||
|
|
||||||
int fd = open(std::string(config.output).c_str(), O_RDWR | O_CREAT, 0777);
|
int fd = open(std::string(config.output).c_str(), O_RDWR | O_CREAT, 0777);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
@ -778,6 +751,8 @@ static u64 parse_number(std::string opt, std::string_view value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
Timer t_all("all");
|
||||||
|
|
||||||
config.thread_count =
|
config.thread_count =
|
||||||
tbb::global_control::active_value(tbb::global_control::max_allowed_parallelism);
|
tbb::global_control::active_value(tbb::global_control::max_allowed_parallelism);
|
||||||
|
|
||||||
@ -835,7 +810,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
// Parse input files
|
// Parse input files
|
||||||
{
|
{
|
||||||
MyTimer t("parse", parse_timer);
|
ScopedTimer t("parse");
|
||||||
tbb::parallel_for_each(out::objs, [](ObjectFile *file) { file->parse(); });
|
tbb::parallel_for_each(out::objs, [](ObjectFile *file) { file->parse(); });
|
||||||
tbb::parallel_for_each(out::dsos, [](SharedFile *file) { file->parse(); });
|
tbb::parallel_for_each(out::dsos, [](SharedFile *file) { file->parse(); });
|
||||||
}
|
}
|
||||||
@ -852,14 +827,14 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
// Parse mergeable string sections
|
// Parse mergeable string sections
|
||||||
{
|
{
|
||||||
MyTimer t("merge", parse_timer);
|
ScopedTimer t("merge");
|
||||||
tbb::parallel_for_each(out::objs, [](ObjectFile *file) {
|
tbb::parallel_for_each(out::objs, [](ObjectFile *file) {
|
||||||
file->initialize_mergeable_sections();
|
file->initialize_mergeable_sections();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer total_timer("total", "total");
|
Timer t_total("total");
|
||||||
total_timer.startTimer();
|
Timer t_before_copy("before_copy");
|
||||||
|
|
||||||
out::ehdr = new OutputEhdr;
|
out::ehdr = new OutputEhdr;
|
||||||
out::shdr = new OutputShdr;
|
out::shdr = new OutputShdr;
|
||||||
@ -930,7 +905,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
// Create .bss sections for common symbols.
|
// Create .bss sections for common symbols.
|
||||||
{
|
{
|
||||||
MyTimer t("common", before_copy_timer);
|
ScopedTimer t("common");
|
||||||
tbb::parallel_for_each(out::objs,
|
tbb::parallel_for_each(out::objs,
|
||||||
[](ObjectFile *file) { file->convert_common_symbols(); });
|
[](ObjectFile *file) { file->convert_common_symbols(); });
|
||||||
}
|
}
|
||||||
@ -1054,12 +1029,16 @@ int main(int argc, char **argv) {
|
|||||||
if (phdr.p_type == PT_TLS)
|
if (phdr.p_type == PT_TLS)
|
||||||
out::tls_end = align_to(phdr.p_vaddr + phdr.p_memsz, phdr.p_align);
|
out::tls_end = align_to(phdr.p_vaddr + phdr.p_memsz, phdr.p_align);
|
||||||
|
|
||||||
|
t_before_copy.stop();
|
||||||
|
|
||||||
// Create an output file
|
// Create an output file
|
||||||
out::buf = open_output_file(filesize);
|
out::buf = open_output_file(filesize);
|
||||||
|
|
||||||
|
Timer t_copy("copy");
|
||||||
|
|
||||||
// Copy input sections to the output file
|
// Copy input sections to the output file
|
||||||
{
|
{
|
||||||
MyTimer t("copy", copy_timer);
|
ScopedTimer t("copy_buf");
|
||||||
tbb::parallel_for_each(out::chunks, [&](OutputChunk *chunk) {
|
tbb::parallel_for_each(out::chunks, [&](OutputChunk *chunk) {
|
||||||
chunk->copy_buf();
|
chunk->copy_buf();
|
||||||
});
|
});
|
||||||
@ -1073,16 +1052,15 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
// Commit
|
// Commit
|
||||||
{
|
{
|
||||||
MyTimer t("munmap", copy_timer);
|
ScopedTimer t("munmap");
|
||||||
munmap(out::buf, filesize);
|
munmap(out::buf, filesize);
|
||||||
}
|
}
|
||||||
|
|
||||||
total_timer.stopTimer();
|
t_copy.stop();
|
||||||
|
t_all.stop();
|
||||||
|
|
||||||
if (config.print_map) {
|
if (config.print_map)
|
||||||
MyTimer t("print_map");
|
|
||||||
print_map();
|
print_map();
|
||||||
}
|
|
||||||
|
|
||||||
// Show stat numbers
|
// Show stat numbers
|
||||||
Counter num_input_sections("input_sections");
|
Counter num_input_sections("input_sections");
|
||||||
@ -1095,8 +1073,6 @@ int main(int argc, char **argv) {
|
|||||||
Counter filesize_counter("filesize", filesize);
|
Counter filesize_counter("filesize", filesize);
|
||||||
|
|
||||||
Counter::print();
|
Counter::print();
|
||||||
llvm::TimerGroup::printAll(llvm::outs());
|
Timer::print();
|
||||||
|
|
||||||
llvm::outs().flush();
|
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
33
mold.h
33
mold.h
@ -13,8 +13,8 @@
|
|||||||
#include "tbb/task_group.h"
|
#include "tbb/task_group.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@ -1078,6 +1078,37 @@ private:
|
|||||||
static std::vector<Counter *> instances;
|
static std::vector<Counter *> instances;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Timer {
|
||||||
|
public:
|
||||||
|
Timer(std::string name);
|
||||||
|
void stop();
|
||||||
|
static void print();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::vector<Timer *> instances;
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
u64 start;
|
||||||
|
u64 end;
|
||||||
|
u64 user;
|
||||||
|
u64 sys;
|
||||||
|
bool stopped = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScopedTimer {
|
||||||
|
public:
|
||||||
|
ScopedTimer(std::string name) {
|
||||||
|
timer = new Timer(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ScopedTimer() {
|
||||||
|
timer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Timer *timer;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// mapfile.cc
|
// mapfile.cc
|
||||||
//
|
//
|
||||||
|
64
perf.cc
64
perf.cc
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
std::vector<Counter *> Counter::instances;
|
std::vector<Counter *> Counter::instances;
|
||||||
bool Counter::enabled = true;
|
bool Counter::enabled = true;
|
||||||
|
|
||||||
|
std::vector<Timer *> Timer::instances;
|
||||||
|
|
||||||
void Counter::print() {
|
void Counter::print() {
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
return;
|
return;
|
||||||
@ -18,3 +22,63 @@ void Counter::print() {
|
|||||||
for (Counter *c : vec)
|
for (Counter *c : vec)
|
||||||
std::cout << std::setw(20) << std::right << c->name << "=" << c->value << "\n";
|
std::cout << std::setw(20) << std::right << c->name << "=" << c->value << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u64 now_nsec() {
|
||||||
|
struct timespec t;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||||
|
return (u64)t.tv_sec * 1000000000 + t.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u64 to_usec(struct timeval t) {
|
||||||
|
return t.tv_sec * 1000000 + t.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer::Timer(std::string name) : name(name) {
|
||||||
|
instances.push_back(this);
|
||||||
|
|
||||||
|
struct rusage usage;
|
||||||
|
getrusage(RUSAGE_SELF, &usage);
|
||||||
|
|
||||||
|
start = now_nsec();
|
||||||
|
user = to_usec(usage.ru_utime);
|
||||||
|
sys = to_usec(usage.ru_stime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::stop() {
|
||||||
|
if (stopped)
|
||||||
|
return;
|
||||||
|
stopped = true;
|
||||||
|
|
||||||
|
struct rusage usage;
|
||||||
|
getrusage(RUSAGE_SELF, &usage);
|
||||||
|
|
||||||
|
end = now_nsec();
|
||||||
|
user = to_usec(usage.ru_utime) - user;
|
||||||
|
sys = to_usec(usage.ru_stime) - sys;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::print() {
|
||||||
|
for (Timer *t : instances)
|
||||||
|
t->stop();
|
||||||
|
|
||||||
|
std::vector<int> depth(instances.size());
|
||||||
|
|
||||||
|
for (int i = 0, j = 0; j < instances.size(); j++) {
|
||||||
|
while (instances[i]->end < instances[j]->start)
|
||||||
|
i++;
|
||||||
|
depth[j] = j - i;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << " User System Real Name\n";
|
||||||
|
|
||||||
|
for (int i = 0; i < instances.size(); i++) {
|
||||||
|
Timer &t = *instances[i];;
|
||||||
|
printf(" % 8.3f % 8.3f % 8.3f %s%s\n",
|
||||||
|
((double)t.user / 1000000),
|
||||||
|
((double)t.sys / 1000000),
|
||||||
|
(((double)t.end - t.start) / 1000000000),
|
||||||
|
std::string(" ", depth[i]).c_str(),
|
||||||
|
t.name.c_str());
|
||||||
|
}
|
||||||
|
std::cout << std::flush;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user