Add --stats option to print runtime and memory usage statistics.

This commit is contained in:
Ian Lance Taylor 2007-10-12 05:51:25 +00:00
parent 6ca8706da5
commit e44fcf3bcf
10 changed files with 205 additions and 3 deletions

View file

@ -13,6 +13,9 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `mallinfo' function. */
#undef HAVE_MALLINFO
/* Whether the C++ compiler can call a template member with no arguments */
#undef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS

102
gold/configure vendored
View file

@ -5443,6 +5443,108 @@ fi
done
for ac_func in mallinfo
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
if eval "test \"\${$as_ac_var+set}\" = set"; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
#define $ac_func innocuous_$ac_func
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func (); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
#undef $ac_func
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
{
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char $ac_func ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
char (*f) () = $ac_func;
#endif
#ifdef __cplusplus
}
#endif
int
main ()
{
return f != $ac_func;
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_cxx_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
eval "$as_ac_var=yes"
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_var=no"
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
if test `eval echo '${'$as_ac_var'}'` = yes; then
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
cat >conftest.$ac_ext <<_ACEOF
class c { public: template<int i> void fn(); };

View file

@ -171,6 +171,7 @@ AC_LANG_PUSH(C++)
AC_CHECK_HEADERS(tr1/unordered_set tr1/unordered_map)
AC_CHECK_HEADERS(ext/hash_map ext/hash_set)
AC_CHECK_FUNCS(mallinfo)
dnl Test whether the compiler can specify a member templates to call.
AC_COMPILE_IFELSE([

View file

@ -48,6 +48,8 @@ File_read::View::~View()
if (::munmap(const_cast<unsigned char*>(this->data_), this->size_) != 0)
fprintf(stderr, _("%s: munmap failed: %s\n"),
program_name, strerror(errno));
File_read::current_mapped_bytes -= this->size_;
}
}
@ -72,6 +74,11 @@ File_read::View::is_locked()
// Class File_read.
// The File_read static variables.
unsigned long long File_read::total_mapped_bytes;
unsigned long long File_read::current_mapped_bytes;
unsigned long long File_read::maximum_mapped_bytes;
// The File_read class is designed to support file descriptor caching,
// but this is not currently implemented.
@ -146,7 +153,15 @@ File_read::unlock()
gold_assert(this->lock_count_ > 0);
--this->lock_count_;
if (this->lock_count_ == 0)
this->clear_views(false);
{
File_read::total_mapped_bytes += this->mapped_bytes_;
File_read::current_mapped_bytes += this->mapped_bytes_;
this->mapped_bytes_ = 0;
if (File_read::current_mapped_bytes > File_read::maximum_mapped_bytes)
File_read::maximum_mapped_bytes = File_read::current_mapped_bytes;
this->clear_views(false);
}
}
bool
@ -289,6 +304,8 @@ File_read::find_or_make_view(off_t start, off_t size, bool cache)
gold_exit(false);
}
this->mapped_bytes_ += psize;
const unsigned char* pbytes = static_cast<const unsigned char*>(p);
v = new File_read::View(poff, psize, pbytes, cache, true);
}
@ -355,6 +372,17 @@ File_read::clear_views(bool destroying)
}
}
// Print statistical information to stderr. This is used for --stats.
void
File_read::print_stats()
{
fprintf(stderr, _("%s: total bytes mapped for read: %llu\n"),
program_name, File_read::total_mapped_bytes);
fprintf(stderr, _("%s: maximum bytes mapped for read at one time: %llu\n"),
program_name, File_read::maximum_mapped_bytes);
}
// Class File_view.
File_view::~File_view()

View file

@ -46,7 +46,7 @@ class File_read
public:
File_read()
: name_(), descriptor_(-1), size_(0), lock_count_(0), views_(),
saved_views_(), contents_(NULL)
saved_views_(), contents_(NULL), mapped_bytes_(0)
{ }
~File_read();
@ -109,11 +109,27 @@ class File_read
File_view*
get_lasting_view(off_t start, off_t size, bool cache);
// Dump statistical information to stderr.
static void
print_stats();
private:
// This class may not be copied.
File_read(const File_read&);
File_read& operator=(const File_read&);
// Total bytes mapped into memory during the link. This variable is
// only accessed from the main thread, when unlocking the object.
static unsigned long long total_mapped_bytes;
// Current number of bytes mapped into memory during the link. This
// variable is only accessed from the main thread.
static unsigned long long current_mapped_bytes;
// High water mark of bytes mapped into memory during the link.
// This variable is only accessed from the main thread.
static unsigned long long maximum_mapped_bytes;
// A view into the file.
class View
{
@ -167,6 +183,7 @@ class File_read
bool mapped_;
};
friend class View;
friend class File_view;
// Find a view into the file.
@ -219,6 +236,10 @@ class File_read
Saved_views saved_views_;
// Specified file contents. Used only for testing purposes.
const unsigned char* contents_;
// Total amount of space mapped into memory. This is only changed
// while the file is locked. When we unlock the file, we transfer
// the total to total_mapped_bytes, and reset this to zero.
size_t mapped_bytes_;
};
// A view of file data that persists even when the file is unlocked.

View file

@ -67,7 +67,7 @@ Layout::Layout(const General_options& options)
unattached_section_list_(), special_output_list_(),
tls_segment_(NULL), symtab_section_(NULL),
dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL),
eh_frame_section_(NULL)
eh_frame_section_(NULL), output_file_size_(-1)
{
// Make space for more than enough segments for a typical file.
// This is just for efficiency--it's OK if we wind up needing more.
@ -625,6 +625,8 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab)
// Now we know exactly where everything goes in the output file.
Output_data::layout_complete();
this->output_file_size_ = off;
return off;
}

View file

@ -137,6 +137,11 @@ class Layout
off_t
finalize(const Input_objects*, Symbol_table*);
// Return the size of the output file.
off_t
output_file_size() const
{ return this->output_file_size_; }
// Return the TLS segment. This will return NULL if there isn't
// one.
Output_segment*
@ -368,6 +373,8 @@ class Layout
Output_data_dynamic* dynamic_data_;
// The exception frame section.
Output_section* eh_frame_section_;
// The size of the output file.
off_t output_file_size_;
};
// This task handles writing out data which is not part of a section

View file

@ -22,6 +22,11 @@
#include "gold.h"
#ifdef HAVE_MALLINFO
#include <malloc.h>
#endif
#include "libiberty.h"
#include "options.h"
#include "parameters.h"
#include "dirsearch.h"
@ -49,6 +54,11 @@ main(int argc, char** argv)
// Handle the command line options.
Command_line command_line;
command_line.process(argc - 1, argv + 1);
long start_time = 0;
if (command_line.options().print_stats())
start_time = get_run_time();
initialize_parameters(&command_line.options());
// The work queue.
@ -75,5 +85,20 @@ main(int argc, char** argv)
// Run the main task processing loop.
workqueue.process();
if (command_line.options().print_stats())
{
long run_time = get_run_time() - start_time;
fprintf(stderr, _("%s: total run time: %ld.%06ld seconds\n"),
program_name, run_time / 1000000, run_time % 1000000);
#ifdef HAVE_MALLINFO
struct mallinfo m = mallinfo();
fprintf(stderr, _("%s: total space allocated by malloc: %d bytes\n"),
program_name, m.arena);
#endif
File_read::print_stats();
fprintf(stderr, _("%s: output file size: %lld bytes\n"),
program_name, static_cast<long long>(layout.output_file_size()));
}
gold_exit(true);
}

View file

@ -348,6 +348,8 @@ options::Command_line_options::options[] =
NULL, ONE_DASH, &General_options::set_shared),
GENERAL_NOARG('\0', "static", N_("Do not link against shared libraries"),
NULL, ONE_DASH, &General_options::set_static),
GENERAL_NOARG('\0', "stats", N_("Print resource usage statistics"),
NULL, TWO_DASHES, &General_options::set_stats),
GENERAL_ARG('\0', "sysroot", N_("Set target system root directory"),
N_("--sysroot DIR"), TWO_DASHES, &General_options::set_sysroot),
POSDEP_NOARG('\0', "as-needed",
@ -388,6 +390,7 @@ General_options::General_options()
rpath_link_(),
is_shared_(false),
is_static_(false),
print_stats_(false),
sysroot_()
{
}

View file

@ -169,6 +169,11 @@ class General_options
is_static() const
{ return this->is_static_; }
// --statis: Print resource usage statistics.
bool
print_stats() const
{ return this->print_stats_; }
// --sysroot: The system root of a cross-linker.
const std::string&
sysroot() const
@ -251,6 +256,10 @@ class General_options
set_static()
{ this->is_static_ = true; }
void
set_stats()
{ this->print_stats_ = true; }
void
set_sysroot(const char* arg)
{ this->sysroot_ = arg; }
@ -275,6 +284,7 @@ class General_options
Dir_list rpath_link_;
bool is_shared_;
bool is_static_;
bool print_stats_;
std::string sysroot_;
};