public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 0/3] [Announcement] Performance Counters for Linux
@ 2008-12-04 23:44 Thomas Gleixner
  2008-12-04 23:44 ` [patch 1/3] performance counters: core code Thomas Gleixner
                   ` (7 more replies)
  0 siblings, 8 replies; 67+ messages in thread
From: Thomas Gleixner @ 2008-12-04 23:44 UTC (permalink / raw)
  To: LKML
  Cc: linux-arch, Andrew Morton, Ingo Molnar, Stephane Eranian,
	Eric Dumazet, Robert Richter, Arjan van de Veen, Peter Anvin,
	Peter Zijlstra, Steven Rostedt, David Miller, Paul Mackerras

Performance counters are special hardware registers available on most modern
CPUs. These register count the number of certain types of hw events: such
as instructions executed, cachemisses suffered, or branches mis-predicted,
without slowing down the kernel or applications. These registers can also
trigger interrupts when a threshold number of events have passed - and can
thus be used to profile the code that runs on that CPU.

We'd like to announce a brand new implementation of performance counter
support for Linux. It is a very simple and extensible design that has the
potential to implement the full range of features we would expect from such
a subsystem.

The Linux Performance Counter subsystem (implemented via the patches
posted in this announcement) provides an abstraction of performance counter
hardware capabilities. It provides per task and per CPU counters, and it
provides event capabilities on top of those.

The code is far from complete - but the basic approach is already there
and stable.

The biggest missing detail is lowlevel support for non-Intel CPUs and
older Intel CPUs - right now the code is implemented for Intel Core2
(and later) Intel CPUs that have the PERFMON CPU feature. (see below
a wider list of missing/upcoming features)

We are aware of the perfmon3 patchset that has been submitted to lkml
recently. Our patchset tries to achieve a similar end result, with
a fundamentally different (and we believe, superior :-) design:

 - The API is based on a single counter abstraction

 - Only one single new system call is needed: sys_perf_counter_open().
   All performance-counter operations are implemented via standard
   VFS APIs such as read() / fcntl() and poll().

 - User-space is not exposed to lowlevel details like contexts or
   arrays of counters. Opening and reading a basic counter is as simple
   as 2 lines of C code:

   void main(void)
   {
      u64 count;

      fd = perf_counter_open(3 /* PERF_COUNT_CACHE_MISSES */, 0, 0, 0, -1);
      ret = read(fd, &count, sizeof(count));
      if (ret == sizeof(count))
              printf("Current count: %Ld cachemisses!", count);
   }

 - Events, blocking/sleep are natural built-in properties of counters.

 - No interaction with ptrace: any task (with sufficient permissions) can
   monitor other tasks, without having to stop that task.

 - Mapping of counters to hw counters is not static - counters are
   scheduled dynamically on each CPU where a task runs.

 - There's a /sys based reservation facility that allows the allocation
   of a certain number of hw counters for guaranteed sysadmin access.

 - Generalized enumeration for common hw event types. Raw event codes
   can be passed to the API too - but the most common (and most useful)
   event codes are generalized into a hardware-independent registry
   of events:

    enum hw_event_types {
           PERF_COUNT_CYCLES,
           PERF_COUNT_INSTRUCTIONS,
           PERF_COUNT_CACHE_REFERENCES,
           PERF_COUNT_CACHE_MISSES,
           PERF_COUNT_BRANCH_INSTRUCTIONS,
           PERF_COUNT_BRANCH_MISSES,
    };

 - Simplified lowlevel/arch support. The x86 code for Intel CPUs (with
   the PERFMON CPU feature) is 340 lines of code that implements
   7 straightforward lowlevel API calls:

    int hw_perf_counter_init(struct perf_counter *counter, u32 hw_event_type);
    void hw_perf_counter_enable(struct perf_counter *counter);
    void hw_perf_counter_disable(struct perf_counter *counter);
    void hw_perf_counter_read(struct perf_counter *counter);
    void hw_perf_counter_enable_config(struct perf_counter *counter);
    void hw_perf_counter_disable_config(struct perf_counter *counter);
    void hw_perf_counter_setup(void);

   There's one kernel/perf_counter.c core file, and a single
   arch/x86/kernel/cpu/perf_counter.c architecture support file.

   The impact on the kernel tree is relatively moderate:

       27 files changed, 1641 insertions(+), 7 deletions(-)

TODO:

 - Non-Intel CPU support. Help is welcome :-)

 - Round-robin scheduling of counters, when there's more task counters
   than hw counters available.

 - Support for extended record types such as PEBS.

 - Support for NMI events in the x86 code (the core design is ready)

 - Make sure it works well with OProfile and the x86 NMI watchdog

Short documentation is available in Documentation/perf-counters.txt

Find below the source of a simple monitoring demo.

We'd like to seek the feedback of perfmon developers and architecture
maintainers - what do you think about this approach?

Comments, reports, suggestions, flames and other types of feedback
is more than welcome,

	Thomas, Ingo
---

/*
 * Performance counters monitoring test case
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>

#define __user

#include "sys.h"

static int count = 10000;
static int eventid;
static int tid;
static char *debuginfo;

static void display_help(void)
{
	printf("monitor\n");
	printf("Usage:\n"
	       "monitor options threadid\n\n"
	       "-e EID   --eventid=EID  eventid\n"
	       "-c CNT   --count=CNT    event count on which IP is sampled\n"
	       "-d FILE  --debug=FILE   path to binary file with debug info\n");
	exit(0);
}

static void process_options (int argc, char *argv[])
{
	int error = 0;

	for (;;) {
		int option_index = 0;
		/** Options for getopt */
		static struct option long_options[] = {
			{"count", required_argument, NULL, 'c'},
			{"debug", required_argument, NULL, 'd'},
			{"eventid", required_argument, NULL, 'e'},
			{"help", no_argument, NULL, 'h'},
			{NULL, 0, NULL, 0}
		};
		int c = getopt_long(argc, argv, "c:d:e:",
				    long_options, &option_index);
		if (c == -1)
			break;
		switch (c) {
		case 'c': count = atoi(optarg); break;
		case 'd': debuginfo = strdup(optarg); break;
		case 'e': eventid = atoi(optarg); break;
		default: error = 1; break;
		}
	}
	if (error || optind == argc)
		display_help ();

	tid = atoi(argv[optind]);
}

int main(int argc, char *argv[])
{
	char str[256];
	uint64_t ip;
	ssize_t res;
	int fd;

	process_options(argc, argv);

	fd = perf_counter_open(eventid, count, 1, tid, -1);
	if (fd < 0) {
		perror("Create counter");
		exit(-1);
	}

	while (1) {
		res = read(fd, (char *) &ip, sizeof(ip));
		if (res != sizeof(ip)) {
			perror("Read counter");
			break;
		}

		if (!debuginfo) {
			printf("IP: 0x%016llx\n", (unsigned long long)ip);
		} else {
			sprintf(str, "addr2line -e %s 0x%llx\n", debuginfo,
				(unsigned long long)ip);
			system(str);
		}
	}

	close(fd);
	exit(0);
}




^ permalink raw reply	[flat|nested] 67+ messages in thread

end of thread, other threads:[~2008-12-10 17:10 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-04 23:44 [patch 0/3] [Announcement] Performance Counters for Linux Thomas Gleixner
2008-12-04 23:44 ` [patch 1/3] performance counters: core code Thomas Gleixner
2008-12-05 10:55   ` Paul Mackerras
2008-12-05 11:20     ` Ingo Molnar
2008-12-04 23:44 ` [patch 2/3] performance counters: documentation Thomas Gleixner
2008-12-05  0:33   ` Paul Mackerras
2008-12-05  0:37     ` David Miller
2008-12-05  2:50       ` Arjan van de Ven
2008-12-05  3:26         ` David Miller
2008-12-05  2:33     ` Andi Kleen
2008-12-04 23:45 ` [patch 3/3] performance counters: x86 support Thomas Gleixner
2008-12-05  0:22 ` [patch 0/3] [Announcement] Performance Counters for Linux Paul Mackerras
2008-12-05  6:31   ` Ingo Molnar
2008-12-05  7:02     ` Arjan van de Ven
2008-12-05  7:52       ` David Miller
2008-12-05  7:03     ` Ingo Molnar
2008-12-05  7:16       ` Peter Zijlstra
2008-12-05  7:57         ` Paul Mackerras
2008-12-05  8:03           ` Peter Zijlstra
2008-12-05  8:07             ` David Miller
2008-12-05  8:11               ` Ingo Molnar
2008-12-05  8:17                 ` David Miller
2008-12-05  8:24                   ` Ingo Molnar
2008-12-05  8:27                     ` David Miller
2008-12-05  8:42                       ` Ingo Molnar
2008-12-05  8:49                         ` David Miller
2008-12-05 12:13                           ` Ingo Molnar
2008-12-05 12:39                         ` Andi Kleen
2008-12-05 20:08                           ` David Miller
2008-12-10  3:48                             ` Paul Mundt
2008-12-10  4:42                               ` Paul Mackerras
2008-12-10  8:43                               ` Mikael Pettersson
2008-12-10 10:28                               ` Andi Kleen
2008-12-10 10:23                                 ` Paul Mundt
2008-12-10 11:03                                   ` Andi Kleen
2008-12-05 15:00               ` Arjan van de Ven
2008-12-05  9:16             ` Paul Mackerras
2008-12-05  7:57       ` David Miller
2008-12-05  8:18         ` Ingo Molnar
2008-12-05  8:20           ` David Miller
2008-12-05  7:54     ` Paul Mackerras
2008-12-05  8:08       ` Ingo Molnar
2008-12-05  8:15         ` David Miller
2008-12-05 13:25           ` Ingo Molnar
2008-12-05  9:10         ` Paul Mackerras
2008-12-05 12:07           ` Ingo Molnar
2008-12-06  0:05             ` Paul Mackerras
2008-12-06  1:23               ` Mikael Pettersson
2008-12-06 12:34               ` Peter Zijlstra
2008-12-07  5:15                 ` Paul Mackerras
2008-12-08  7:18                   ` stephane eranian
2008-12-08 11:11                     ` Ingo Molnar
2008-12-08 11:58                       ` David Miller
2008-12-09  0:21                       ` stephane eranian
2008-12-05  0:22 ` H. Peter Anvin
2008-12-05  0:43   ` Paul Mackerras
2008-12-05  1:12 ` David Miller
2008-12-05  6:10   ` Ingo Molnar
2008-12-05  7:50     ` David Miller
2008-12-05  9:34     ` Paul Mackerras
2008-12-05 10:41       ` Ingo Molnar
2008-12-05 10:05     ` Ingo Molnar
2008-12-05  3:30 ` Andrew Morton
2008-12-06  2:36 ` stephane eranian
2008-12-08  2:12   ` [perfmon2] [patch 0/3] [Announcement] Performance Counters forLinux Dan Terpstra
2008-12-10 16:27   ` [perfmon2] [patch 0/3] [Announcement] Performance Counters for Linux Rob Fowler
2008-12-10 17:11     ` Andi Kleen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox