aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/evsel.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2013-08-04 22:41:26 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-08-16 16:17:57 -0400
commitbec196720431db2fd6a9b03cbd77eb336e6f52de (patch)
tree01f671397f4ba0e811cf6d3b244777e2d97f8d88 /tools/perf/util/evsel.c
parentfe32ee0fc1c43f780529da79329d8c87ebc51464 (diff)
perf tools: Try to increase the file descriptor limits on EMFILE
perf stat -a needs 10 open file descriptors per logical CPU perf stat -a -dddd needs 20 open fds for each. This implies that stat -a doesn't work on any system with the default ulimit -n 1024 which has more than ~100 CPUs and stat -a -dddd doesn't work on anything with more than 46 CPUs. Longer term there needs to be probably some way to lower the file descriptor requirements. This would need some changes in the kernel/user interface. But short term this patch just tries to increase the file descriptor limit in perf itself, when it runs into a EMFILE. It first sets it to the hard limit, and then tries to increase the hard limit. On Fedora systems the default seems to be soft limit 1024 and hard limit 4*1024. So even non root can support 409 or 186 CPUs respectively. root can go far higher. Signed-off-by: Andi Kleen <ak@linux.intel.com> Link: http://lkml.kernel.org/r/1375670486-15480-1-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/evsel.c')
-rw-r--r--tools/perf/util/evsel.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 960394ea1e3a..a29c8d03ac69 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -13,6 +13,7 @@
13#include <traceevent/event-parse.h> 13#include <traceevent/event-parse.h>
14#include <linux/hw_breakpoint.h> 14#include <linux/hw_breakpoint.h>
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
16#include <sys/resource.h>
16#include "asm/bug.h" 17#include "asm/bug.h"
17#include "evsel.h" 18#include "evsel.h"
18#include "evlist.h" 19#include "evlist.h"
@@ -867,6 +868,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
867 int cpu, thread; 868 int cpu, thread;
868 unsigned long flags = 0; 869 unsigned long flags = 0;
869 int pid = -1, err; 870 int pid = -1, err;
871 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
870 872
871 if (evsel->fd == NULL && 873 if (evsel->fd == NULL &&
872 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 874 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
@@ -894,6 +896,7 @@ retry_sample_id:
894 896
895 group_fd = get_group_fd(evsel, cpu, thread); 897 group_fd = get_group_fd(evsel, cpu, thread);
896 898
899retry_open:
897 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, 900 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
898 pid, 901 pid,
899 cpus->map[cpu], 902 cpus->map[cpu],
@@ -902,12 +905,37 @@ retry_sample_id:
902 err = -errno; 905 err = -errno;
903 goto try_fallback; 906 goto try_fallback;
904 } 907 }
908 set_rlimit = NO_CHANGE;
905 } 909 }
906 } 910 }
907 911
908 return 0; 912 return 0;
909 913
910try_fallback: 914try_fallback:
915 /*
916 * perf stat needs between 5 and 22 fds per CPU. When we run out
917 * of them try to increase the limits.
918 */
919 if (err == -EMFILE && set_rlimit < INCREASED_MAX) {
920 struct rlimit l;
921 int old_errno = errno;
922
923 if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
924 if (set_rlimit == NO_CHANGE)
925 l.rlim_cur = l.rlim_max;
926 else {
927 l.rlim_cur = l.rlim_max + 1000;
928 l.rlim_max = l.rlim_cur;
929 }
930 if (setrlimit(RLIMIT_NOFILE, &l) == 0) {
931 set_rlimit++;
932 errno = old_errno;
933 goto retry_open;
934 }
935 }
936 errno = old_errno;
937 }
938
911 if (err != -EINVAL || cpu > 0 || thread > 0) 939 if (err != -EINVAL || cpu > 0 || thread > 0)
912 goto out_close; 940 goto out_close;
913 941