""",
file=self.stream,
)
class IndexRenderer:
def __init__(
self, output_dir, should_display_hotness, max_hottest_remarks_on_index
):
self.stream = io.open(
os.path.join(output_dir, "index.html"), "w", encoding="utf-8"
)
self.should_display_hotness = should_display_hotness
self.max_hottest_remarks_on_index = max_hottest_remarks_on_index
def render_entry(self, r, odd):
escaped_name = html.escape(r.DemangledFunctionName)
print(
"""
""".format(
**locals()
),
file=self.stream,
)
def render(self, all_remarks):
print(
"""
Source Location |
Hotness |
Function |
Pass |
""",
file=self.stream,
)
max_entries = None
if self.should_display_hotness:
max_entries = self.max_hottest_remarks_on_index
for i, remark in enumerate(all_remarks[:max_entries]):
if not suppress(remark):
self.render_entry(remark, i % 2)
print(
"""
""",
file=self.stream,
)
def _render_file(source_dir, output_dir, ctx, no_highlight, entry, filter_):
global context
context = ctx
filename, remarks = entry
SourceFileRenderer(source_dir, output_dir, filename, no_highlight).render(remarks)
def map_remarks(all_remarks):
# Set up a map between function names and their source location for
# function where inlining happened
for remark in optrecord.itervalues(all_remarks):
if (
isinstance(remark, optrecord.Passed)
and remark.Pass == "inline"
and remark.Name == "Inlined"
):
for arg in remark.Args:
arg_dict = dict(list(arg))
caller = arg_dict.get("Caller")
if caller:
try:
context.caller_loc[caller] = arg_dict["DebugLoc"]
except KeyError:
pass
def generate_report(
all_remarks,
file_remarks,
source_dir,
output_dir,
no_highlight,
should_display_hotness,
max_hottest_remarks_on_index,
num_jobs,
should_print_progress,
):
try:
os.makedirs(output_dir)
except OSError as e:
if e.errno == errno.EEXIST and os.path.isdir(output_dir):
pass
else:
raise
if should_print_progress:
print("Rendering index page...")
if should_display_hotness:
sorted_remarks = sorted(
optrecord.itervalues(all_remarks),
key=lambda r: (
r.Hotness,
r.File,
r.Line,
r.Column,
r.PassWithDiffPrefix,
r.yaml_tag,
r.Function,
),
reverse=True,
)
else:
sorted_remarks = sorted(
optrecord.itervalues(all_remarks),
key=lambda r: (
r.File,
r.Line,
r.Column,
r.PassWithDiffPrefix,
r.yaml_tag,
r.Function,
),
)
IndexRenderer(
output_dir, should_display_hotness, max_hottest_remarks_on_index
).render(sorted_remarks)
shutil.copy("/usr/share/opt-viewer/style.css", output_dir)
_render_file_bound = functools.partial(
_render_file, source_dir, output_dir, context, no_highlight
)
if should_print_progress:
print("Rendering HTML files...")
optpmap.pmap(
_render_file_bound, file_remarks.items(), num_jobs, should_print_progress
)
def main():
parser = argparse.ArgumentParser(description=desc)
parser.add_argument(
"yaml_dirs_or_files",
nargs="+",
help="List of optimization record files or directories searched "
"for optimization record files.",
)
parser.add_argument(
"--output-dir",
"-o",
default="html",
help="Path to a directory where generated HTML files will be output. "
"If the directory does not already exist, it will be created. "
'"%(default)s" by default.',
)
parser.add_argument(
"--jobs",
"-j",
default=None,
type=int,
help="Max job count (defaults to %(default)s, the current CPU count)",
)
parser.add_argument("--source-dir", "-s", default="", help="set source directory")
parser.add_argument(
"--no-progress-indicator",
"-n",
action="store_true",
default=False,
help="Do not display any indicator of how many YAML files were read "
"or rendered into HTML.",
)
parser.add_argument(
"--max-hottest-remarks-on-index",
default=1000,
type=int,
help="Maximum number of the hottest remarks to appear on the index page",
)
parser.add_argument(
"--no-highlight",
action="store_true",
default=False,
help="Do not use a syntax highlighter when rendering the source code",
)
parser.add_argument(
"--demangler",
help="Set the demangler to be used (defaults to %s)"
% optrecord.Remark.default_demangler,
)
parser.add_argument(
"--filter",
default="",
help="Only display remarks from passes matching filter expression",
)
# Do not make this a global variable. Values needed to be propagated through
# to individual classes and functions to be portable with multiprocessing across
# Windows and non-Windows.
args = parser.parse_args()
print_progress = not args.no_progress_indicator
if args.demangler:
optrecord.Remark.set_demangler(args.demangler)
files = optrecord.find_opt_files(*args.yaml_dirs_or_files)
if not files:
parser.error("No *.opt.yaml files found")
sys.exit(1)
all_remarks, file_remarks, should_display_hotness = optrecord.gather_results(
files, args.jobs, print_progress, args.filter
)
map_remarks(all_remarks)
generate_report(
all_remarks,
file_remarks,
args.source_dir,
args.output_dir,
args.no_highlight,
should_display_hotness,
args.max_hottest_remarks_on_index,
args.jobs,
print_progress,
)
if __name__ == "__main__":
main()