From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40770C2D0DB for ; Mon, 20 Jan 2020 16:31:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E8E0722464 for ; Mon, 20 Jan 2020 16:31:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="rselF6Eu" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729740AbgATQbh (ORCPT ); Mon, 20 Jan 2020 11:31:37 -0500 Received: from smtp-fw-9101.amazon.com ([207.171.184.25]:1899 "EHLO smtp-fw-9101.amazon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729393AbgATQbQ (ORCPT ); Mon, 20 Jan 2020 11:31:16 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1579537875; x=1611073875; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=ajprkLA0Z2CJ05kKrF2mzXctYnFtL8SxS5YWM3SPIlk=; b=rselF6EuS/Uvcl4juHlb+TNoK3kF0KMSg7JcJBz62O8Htep0206cogqa Jpc2g5wp8yeAYducnYIyhSqTfUdcCUUP6tX5WfShe4/8oYxyWxrFq6qCu mtj6nG2jbQf+t2+Gj7CzZMV3rsKFqq0Sf0ex4rHS5ls0xnyJfLMWmasv+ I=; IronPort-SDR: RyzlBS7b8Hjtk2gm5BluMQXz766yqt06KcQxi/wrNyrrd2gSSOSF2LJ43cPAXHYOR7ykFuftMX ULLrMTnO9e9w== X-IronPort-AV: E=Sophos;i="5.70,342,1574121600"; d="scan'208";a="11398552" Received: from sea32-co-svc-lb4-vlan3.sea.corp.amazon.com (HELO email-inbound-relay-2a-f14f4a47.us-west-2.amazon.com) ([10.47.23.38]) by smtp-border-fw-out-9101.sea19.amazon.com with ESMTP; 20 Jan 2020 16:31:13 +0000 Received: from EX13MTAUEA002.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan2.pdx.amazon.com [10.170.41.162]) by email-inbound-relay-2a-f14f4a47.us-west-2.amazon.com (Postfix) with ESMTPS id D03B8A2B6A; Mon, 20 Jan 2020 16:31:11 +0000 (UTC) Received: from EX13D31EUA001.ant.amazon.com (10.43.165.15) by EX13MTAUEA002.ant.amazon.com (10.43.61.77) with Microsoft SMTP Server (TLS) id 15.0.1236.3; Mon, 20 Jan 2020 16:31:11 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.253) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Mon, 20 Jan 2020 16:31:04 +0000 From: SeongJae Park To: CC: SeongJae Park , , , , , , , , , , , Subject: [PATCH 6/8] mm/damon: Add minimal user-space tools Date: Mon, 20 Jan 2020 17:30:22 +0100 Message-ID: <20200120163024.647-2-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200120163024.647-1-sjpark@amazon.com> References: <20200120162757.32375-1-sjpark@amazon.com> <20200120163024.647-1-sjpark@amazon.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.43.161.253] X-ClientProxiedBy: EX13D34UWC003.ant.amazon.com (10.43.162.66) To EX13D31EUA001.ant.amazon.com (10.43.165.15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: SeongJae Park This commit adds a shallow wrapper python script, ``/tools/damon/damo`` that provides more convenient interface. Note that it is only aimed to be used for minimal reference of the DAMON's raw interfaces and for debugging of the DAMON itself. Based on the debugfs interface, you can create another cool and more convenient user space tools. Quick Tutorial -------------- 1. Ensure your kernel is built with CONFIG_DAMON turned on, and debugfs is mounted at ``/sys/kernel/debug/``. 2. ``/tools/damon/damo -h`` Signed-off-by: SeongJae Park --- MAINTAINERS | 1 + tools/damon/.gitignore | 1 + tools/damon/_dist.py | 35 ++++ tools/damon/bin2txt.py | 64 +++++++ tools/damon/damo | 37 ++++ tools/damon/heats.py | 358 ++++++++++++++++++++++++++++++++++++++ tools/damon/nr_regions.py | 88 ++++++++++ tools/damon/record.py | 193 ++++++++++++++++++++ tools/damon/report.py | 45 +++++ tools/damon/wss.py | 94 ++++++++++ 10 files changed, 916 insertions(+) create mode 100644 tools/damon/.gitignore create mode 100644 tools/damon/_dist.py create mode 100644 tools/damon/bin2txt.py create mode 100755 tools/damon/damo create mode 100644 tools/damon/heats.py create mode 100644 tools/damon/nr_regions.py create mode 100644 tools/damon/record.py create mode 100644 tools/damon/report.py create mode 100644 tools/damon/wss.py diff --git a/MAINTAINERS b/MAINTAINERS index c8db500a182f..fb41236f3aed 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4588,6 +4588,7 @@ M: SeongJae Park L: linux-mm@kvack.org S: Maintained F: mm/damon.c +F: tools/damon/* DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER L: netdev@vger.kernel.org diff --git a/tools/damon/.gitignore b/tools/damon/.gitignore new file mode 100644 index 000000000000..96403d36ff93 --- /dev/null +++ b/tools/damon/.gitignore @@ -0,0 +1 @@ +__pycache__/* diff --git a/tools/damon/_dist.py b/tools/damon/_dist.py new file mode 100644 index 000000000000..f26409cf9232 --- /dev/null +++ b/tools/damon/_dist.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +import os +import struct +import subprocess + +def access_patterns(f): + nr_regions = struct.unpack('I', f.read(4))[0] + + patterns = [] + for r in range(nr_regions): + saddr = struct.unpack('L', f.read(8))[0] + eaddr = struct.unpack('L', f.read(8))[0] + nr_accesses = struct.unpack('I', f.read(4))[0] + patterns.append([eaddr - saddr, nr_accesses]) + return patterns + +def plot_dist(data_file, output_file, xlabel): + terminal = output_file.split('.')[-1] + if not terminal in ['pdf', 'jpeg', 'png', 'svg']: + os.remove(data_file) + print("Unsupported plot output type.") + exit(-1) + + gnuplot_cmd = """ + set term %s; + set output '%s'; + set key off; + set ylabel 'working set size (bytes)'; + set xlabel '%s'; + plot '%s' with linespoints;""" % (terminal, output_file, xlabel, data_file) + subprocess.call(['gnuplot', '-e', gnuplot_cmd]) + os.remove(data_file) + diff --git a/tools/damon/bin2txt.py b/tools/damon/bin2txt.py new file mode 100644 index 000000000000..d5ffac60e02c --- /dev/null +++ b/tools/damon/bin2txt.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +import argparse +import os +import struct +import sys + +def parse_time(bindat): + "bindat should be 16 bytes" + sec = struct.unpack('l', bindat[0:8])[0] + nsec = struct.unpack('l', bindat[8:16])[0] + return sec * 1000000000 + nsec; + +def pr_region(f): + saddr = struct.unpack('L', f.read(8))[0] + eaddr = struct.unpack('L', f.read(8))[0] + nr_accesses = struct.unpack('I', f.read(4))[0] + print("%012x-%012x(%10d):\t%d" % + (saddr, eaddr, eaddr - saddr, nr_accesses)) + +def pr_task_info(f): + pid = struct.unpack('L', f.read(8))[0] + print("pid: ", pid) + nr_regions = struct.unpack('I', f.read(4))[0] + print("nr_regions: ", nr_regions) + for r in range(nr_regions): + pr_region(f) + +def set_argparser(parser): + parser.add_argument('--input', '-i', type=str, metavar='', + default='damon.data', help='input file name') + +def main(args=None): + if not args: + parser = argparse.ArgumentParser() + set_argparser(parser) + args = parser.parse_args() + + file_path = args.input + + if not os.path.isfile(file_path): + print('input file (%s) is not exist' % file_path) + exit(1) + + with open(file_path, 'rb') as f: + start_time = None + while True: + timebin = f.read(16) + if len(timebin) != 16: + break + time = parse_time(timebin) + if not start_time: + start_time = time + print("start_time: ", start_time) + print("rel time: %16d" % (time - start_time)) + nr_tasks = struct.unpack('I', f.read(4))[0] + print("nr_tasks: ", nr_tasks) + for t in range(nr_tasks): + pr_task_info(f) + print("") + +if __name__ == '__main__': + main() diff --git a/tools/damon/damo b/tools/damon/damo new file mode 100755 index 000000000000..58e1099ae5fc --- /dev/null +++ b/tools/damon/damo @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +import argparse + +import record +import report + +class SubCmdHelpFormatter(argparse.RawDescriptionHelpFormatter): + def _format_action(self, action): + parts = super(argparse.RawDescriptionHelpFormatter, + self)._format_action(action) + # skip sub parsers help + if action.nargs == argparse.PARSER: + parts = '\n'.join(parts.split('\n')[1:]) + return parts + +parser = argparse.ArgumentParser(formatter_class=SubCmdHelpFormatter) + +subparser = parser.add_subparsers(title='command', dest='command', + metavar='') +subparser.required = True + +parser_record = subparser.add_parser('record', + help='record data accesses of the given target processes') +record.set_argparser(parser_record) + +parser_report = subparser.add_parser('report', + help='report the recorded data accesses in the specified form') +report.set_argparser(parser_report) + +args = parser.parse_args() + +if args.command == 'record': + record.main(args) +elif args.command == 'report': + report.main(args) diff --git a/tools/damon/heats.py b/tools/damon/heats.py new file mode 100644 index 000000000000..48e966c5ca02 --- /dev/null +++ b/tools/damon/heats.py @@ -0,0 +1,358 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 + +""" +Transform binary trace data into human readable text that can be used for +heatmap drawing, or directly plot the data in a heatmap format. + +Format of the text is: + +