From patchwork Tue Jan 28 09:00:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 11353793 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C1012112B for ; Tue, 28 Jan 2020 09:00:57 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 5773320678 for ; Tue, 28 Jan 2020 09:00:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="SwRR/jgz" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5773320678 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 7B0E46B000A; Tue, 28 Jan 2020 04:00:56 -0500 (EST) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 738F26B000C; Tue, 28 Jan 2020 04:00:56 -0500 (EST) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 6029B6B000E; Tue, 28 Jan 2020 04:00:56 -0500 (EST) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0208.hostedemail.com [216.40.44.208]) by kanga.kvack.org (Postfix) with ESMTP id 4000D6B000A for ; Tue, 28 Jan 2020 04:00:56 -0500 (EST) Received: from smtpin23.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay04.hostedemail.com (Postfix) with SMTP id EB5449079 for ; Tue, 28 Jan 2020 09:00:55 +0000 (UTC) X-FDA: 76426448070.23.frogs49_8072af8bfe40 X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,prvs=289b61846=sjpark@amazon.com,:akpm@linux-foundation.org:sjpark@amazon.de:sj38.park@gmail.com:acme@kernel.org:amit@kernel.org:brendan.d.gregg@gmail.com:corbet@lwn.net:dwmw@amazon.com:mgorman@suse.de:rostedt@goodmis.org:kirill@shutemov.name:brendanhiggins@google.com:colin.king@canonical.com:minchan@kernel.org:vdavydov.dev@gmail.com:vdavydov@parallels.com::linux-doc@vger.kernel.org:linux-kernel@vger.kernel.org,RULES_HIT:30003:30029:30034:30051:30054:30064:30070:30075:30079:30090,0,RBL:52.95.48.154:@amazon.com:.lbl8.mailshell.net-62.18.0.100 64.10.201.10,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fp,MSBL:0,DNSBL:none,Custom_rules:0:0:0,LFtime:24,LUA_SUMMARY:none X-HE-Tag: frogs49_8072af8bfe40 X-Filterd-Recvd-Size: 36764 Received: from smtp-fw-6001.amazon.com (smtp-fw-6001.amazon.com [52.95.48.154]) by imf25.hostedemail.com (Postfix) with ESMTP for ; Tue, 28 Jan 2020 09:00:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1580202055; x=1611738055; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=naeFZW8bSBiU7zlODfiqW7TzEVOnMaVhpUXimbmy6FE=; b=SwRR/jgzmFp9DnRqhQPjDK0dERcmLet7gB01UZsGYb9uTti+TkvkZCuF YhexrL5AgzdE5PlW7dY/wiBioMDuuLo8UzFoOB7wXtUbnS+iygZ10ZKlj DHBIL/VDOjSvdnqvYJZy8TF57CEziOA//ORXbL6zGDHQxKJdDG2dA1rf6 4=; IronPort-SDR: f4aWxNNkbVpwZ9uycl2/K7RUFOwksQcvg/RII000GYPPLEnSreUhnUroiRYdFOOh/54JrxkTNC QTBMr9h71E6g== X-IronPort-AV: E=Sophos;i="5.70,373,1574121600"; d="scan'208";a="15066841" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-2b-55156cd4.us-west-2.amazon.com) ([10.43.8.6]) by smtp-border-fw-out-6001.iad6.amazon.com with ESMTP; 28 Jan 2020 09:00:53 +0000 Received: from EX13MTAUEA002.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan2.pdx.amazon.com [10.170.41.162]) by email-inbound-relay-2b-55156cd4.us-west-2.amazon.com (Postfix) with ESMTPS id BC11CA1CB6; Tue, 28 Jan 2020 09:00:51 +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; Tue, 28 Jan 2020 09:00:51 +0000 Received: from u886c93fd17d25d.ant.amazon.com (10.43.161.117) by EX13D31EUA001.ant.amazon.com (10.43.165.15) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Tue, 28 Jan 2020 09:00:43 +0000 From: To: CC: SeongJae Park , , , , , , , , , , , , , , , , , Subject: [PATCH v2 6/9] mm/damon: Add minimal user-space tools Date: Tue, 28 Jan 2020 10:00:29 +0100 Message-ID: <20200128090029.15691-1-sjpark@amazon.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200128085742.14566-1-sjpark@amazon.com> References: <20200128085742.14566-1-sjpark@amazon.com> MIME-Version: 1.0 X-Originating-IP: [10.43.161.117] X-ClientProxiedBy: EX13D32UWB002.ant.amazon.com (10.43.161.139) To EX13D31EUA001.ant.amazon.com (10.43.165.15) X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: 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. 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 | 194 +++++++++++++++++++++ tools/damon/report.py | 45 +++++ tools/damon/wss.py | 94 ++++++++++ 10 files changed, 917 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 5a4db07cad33..95729c138d34 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4616,6 +4616,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: + +