Write the benchmarking part

This commit is contained in:
Théophile Bastian 2018-08-04 14:07:34 +02:00
parent 86012c7d5e
commit 88ae6dbb0e
3 changed files with 85 additions and 3 deletions

View file

@ -1 +1,2 @@
- Make consistant -ise / -ize (eg. optimize) - Make consistant -ise / -ize (eg. optimize)
- Add references to all my repositories

View file

@ -757,7 +757,7 @@ protocol, and afterwards, a good deal of code reading and coding to get the
solution working. solution working.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Requirements} \subsection{Requirements}\label{ssec:bench_req}
To provide relevant benchmarks of the \ehelfs{} performance, one must sample at To provide relevant benchmarks of the \ehelfs{} performance, one must sample at
least a few hundreds or thousands of stack unwinding, since a single frame least a few hundreds or thousands of stack unwinding, since a single frame
@ -797,11 +797,66 @@ integrate the sampled data in the end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Benchmarking with \prog{perf}} \subsection{Benchmarking with \prog{perf}}
\todo{}
In the context of this internship, the main advantage of \prog{perf} is that it
does a lot of stack unwinding. It also meets all the requirements from
Section~\ref{ssec:bench_req} above: since it stops at regular intervals and
unwinds, the unwindings are evenly distributed \wrt{} the frequency of
execution of the code, which is a natural enough setup for the benchmarks to be
meaningful, while still unwinding from diversified locations, preventing
caching from being be overwhelming. It also has the ability to unwind from
within any function, included functions of linked shared libraries. It can also
be applied to virtually any program, which allows unwinding ``interesting''
code.
The program that was chosen for \prog{perf}-benchmarking is
\prog{hackbench}~\cite{hackbenchsrc}. This small program is designed to
stress-test and benchmark the Linux scheduler by spawning processes or threads
that communicate with each other. It has the interest of generating stack
activity, be linked against \prog{libc} and \prog{pthread}, and be very light.
\medskip
Interfacing \ehelfs{} with \prog{perf} required, in a first place, to fork
\prog{libunwind} and implement \ehelfs{} support for it. In the process, it
turned out necessary to slightly modify \prog{libunwind}'s interface to add a
parameter to a function, since \prog{libunwind} is made to be agnostic of the
system and process as much as possible, to be able to unwind in any context.
This very restricted information lacked a memory map (a table indicating which
shared object is mapped at which address in memory) in order to use \ehelfs.
Apart from this, the modified version of \prog{libunwind} produced is entirely
compatible with the vanilla version.
Once this was done, plugging it in \prog{perf} was the matter of a few lines of
code only. The major problem encountered was to understand how \prog{perf}
works. In order to avoid perturbing the traced program, \prog{perf} does not
unwind at runtime, but rather records at regular interval the program's stack,
and all the auxiliary information that is needed to unwind later. This is done
when running \lstbash{perf record}. Then, \lstbash{perf report} unwinds the
stack to analyze it; but at this point of time, the traced process is long
dead, thus any PID-based approach, or any approach using \texttt{/proc}
information will fail. However, as this was the easiest method, this approach
was chosen when implementing the first version of \ehelfs; thus requiring some
code rewriting.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Other explored methods} \subsection{Other explored methods}
\todo{}
The first approach tried to benchmark was trying to create some specific C code
that would meet the requirements from Section~\ref{ssec:bench_req}, while
calling itself a benchmarking procedure from time to time. This was abandoned
quite fast, because generating C code interesting enough to be unwound turned
out hard, and the generated FDEs invariably ended out uninteresting. It would
also never have met the requirement of unwinding from fairly distributed
locations anyway.
Another attempt was made using CSmith~\cite{csmith}, a random C code generator
initially made for C compilers random testing. The idea was still to craft an
interesting C program that would unwind on its own frequently, but to integrate
randomly generated C code with CSmith to integrate interesting C snippets that
would generate large enough FDEs and nested calls. This was abandoned as well
as the call graph of a CSmith-generated code is often far too small, and the
CSmith code is notoriously hard to understand and edit.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View file

@ -50,3 +50,29 @@
urldate={2018-08-04} urldate={2018-08-04}
} }
@online{hackbenchsrc,
title={Hackbench},
author={Zhang, Yanmin},
url={https://people.redhat.com/mingo/cfs-scheduler/tools/hackbench.c},
year={2008}
}
@inproceedings{csmith,
author = {Xuejun Yang and
Yang Chen and
Eric Eide and
John Regehr},
title = {Finding and understanding bugs in {C} compilers},
booktitle = {Proceedings of the 32nd {ACM} {SIGPLAN} Conference on Programming
Language Design and Implementation, {PLDI} 2011, San Jose, CA, USA,
June 4-8, 2011},
pages = {283--294},
year = {2011},
crossref = {DBLP:conf/pldi/2011},
url = {http://doi.acm.org/10.1145/1993498.1993532},
doi = {10.1145/1993498.1993532},
timestamp = {Mon, 05 Jun 2017 12:39:37 +0200},
biburl = {https://dblp.org/rec/bib/conf/pldi/YangCER11},
bibsource = {dblp computer science bibliography, https://dblp.org}
}