Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp181783ybl; Tue, 28 Jan 2020 01:02:20 -0800 (PST) X-Google-Smtp-Source: APXvYqxLrxAlqcYHu/pN7qbVdaicq0zEhh/HthsTBC6KK2gOF2gQzRbtjfvuKkJJWQSlsqR+k9jb X-Received: by 2002:aca:554d:: with SMTP id j74mr2196167oib.92.1580202139910; Tue, 28 Jan 2020 01:02:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1580202139; cv=none; d=google.com; s=arc-20160816; b=KpdodR21Em16S/BBjg5Pgu7640zMtmt3nEkbmgVwiTOYrXj3ohjP/EFRaLLexcxeSb lbuXi2aIRpBj8ATJjS/CEkAwxumsqHcjWTtEW7A9rKKmOD35FVdk7goBoJLVPbpVgsDz Mju9FFGKYiL7T7Z7dJkKihYH2xewMakA3gCE7FqSTEHtt0BdiUuOvx/e9f1rpThsbmLC 4ot0jzN+Vwckqt9jMiADiW/k0BvSOlpmR+Wyi0fmqHUbJkQh+Q1VXjh77qc4QuFC1PGv Sce8xcpNuqVljqidAVWarY+AKJjcpK5JlhqPgZ+uF5i04lpvgNspby6YJbhEksrhuDht K5DA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:ironport-sdr:dkim-signature; bh=naeFZW8bSBiU7zlODfiqW7TzEVOnMaVhpUXimbmy6FE=; b=MMKJIGuyYa3fOERJ7/wHKx5G7399DphlM4ILo9ziqmFpRc4CPM3CK1qMsL9D1EktMZ OZCTeKyPB+yxpuaD9GnKr9xo9ekXdgmQgnhN8AwpGncE36Tt5l5DMwEAS7ogxrVaQxLQ SjGbNjxWeufyXJU2SMRDKHFErgNm1hqDL04jynIDwaEJaIOX033XDXmDv21ucb634Qz+ VBPUGb2GMgtqaIxiK6cFzfXPNECNPTdVa9zDs8IEyUAcmmQp4uNx2rARfHno2sf1zNlt g8UVGi+QFaJ7+PN5LjSPztApQ/CkMwoqMo4lnlXJlTQE3zTkjRBp8smkRMhJCH6rUUAe mmgQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amazon.com header.s=amazon201209 header.b="SwRR/jgz"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c67si1378680oib.276.2020.01.28.01.02.06; Tue, 28 Jan 2020 01:02:19 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@amazon.com header.s=amazon201209 header.b="SwRR/jgz"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726066AbgA1JA6 (ORCPT + 99 others); Tue, 28 Jan 2020 04:00:58 -0500 Received: from smtp-fw-6001.amazon.com ([52.95.48.154]:14710 "EHLO smtp-fw-6001.amazon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725882AbgA1JA6 (ORCPT ); Tue, 28 Jan 2020 04:00:58 -0500 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 Content-Type: text/plain 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) 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. 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: + +