From f8228364a75f97b367ca406366e7b16e021b35a3 Mon Sep 17 00:00:00 2001 From: Zaafar Ahmed Date: Wed, 30 Mar 2016 17:59:54 +0500 Subject: [PATCH] b_frontend_action.cc changed pc_hash/array to percpu_hash/array table.py optimised/fixup table.py code based on Brenden feedback test_percpu.py Now tests are processor aware and doesn't use sleep added new line at the EOF --- src/cc/frontends/clang/b_frontend_action.cc | 4 +- src/python/bcc/table.py | 50 +++++++----------- tests/python/test_percpu.py | 79 +++++++++++++++-------------- 3 files changed, 61 insertions(+), 72 deletions(-) diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc index 3e30c60..a9bd2b8 100644 --- a/src/cc/frontends/clang/b_frontend_action.cc +++ b/src/cc/frontends/clang/b_frontend_action.cc @@ -570,9 +570,9 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) { map_type = BPF_MAP_TYPE_HASH; } else if (A->getName() == "maps/array") { map_type = BPF_MAP_TYPE_ARRAY; - } else if (A->getName() == "maps/pc_hash") { + } else if (A->getName() == "maps/percpu_hash") { map_type = BPF_MAP_TYPE_PERCPU_HASH; - } else if (A->getName() == "maps/pc_array") { + } else if (A->getName() == "maps/percpu_array") { map_type = BPF_MAP_TYPE_PERCPU_ARRAY; } else if (A->getName() == "maps/histogram") { if (table.key_desc == "\"int\"") diff --git a/src/python/bcc/table.py b/src/python/bcc/table.py index 948ef4a..72d039c 100644 --- a/src/python/bcc/table.py +++ b/src/python/bcc/table.py @@ -406,8 +406,7 @@ class PerfEventArray(ArrayBase): class PerCpuHash(HashTable): def __init__(self, *args, **kwargs): - self.reducer = kwargs["reducer"] - del kwargs["reducer"] + self.reducer = kwargs.pop("reducer", None) super(PerCpuHash, self).__init__(*args, **kwargs) self.sLeaf = self.Leaf self.total_cpu = multiprocessing.cpu_count() @@ -424,7 +423,7 @@ class PerCpuHash(HashTable): else: raise IndexError("Leaf must be aligned to 8 bytes") - def __getitem__(self, key): + def getvalue(self, key): result = super(PerCpuHash, self).__getitem__(key) if self.alignment is 0: ret = result @@ -432,10 +431,13 @@ class PerCpuHash(HashTable): ret = (self.sLeaf * self.total_cpu)() for i in range(0, self.total_cpu): ret[i] = result[i] - if (self.reducer): - return reduce(self.reducer, ret) + return ret + + def __getitem__(self, key): + if self.reducer: + return reduce(self.reducer, self.getvalue(key)) else: - return ret + return self.getvalue(key) def __setitem__(self, key, leaf): super(PerCpuHash, self).__setitem__(key, leaf) @@ -443,20 +445,12 @@ class PerCpuHash(HashTable): def sum(self, key): if isinstance(self.Leaf(), ct.Structure): raise IndexError("Leaf must be an integer type for default sum functions") - temp = self.reducer - self.reducer = None - result = self.__getitem__(key) - self.reducer = temp - return self.sLeaf(reduce(lambda x,y: x+y, result)) + return self.sLeaf(reduce(lambda x,y: x+y, self.getvalue(key))) def max(self, key): if isinstance(self.Leaf(), ct.Structure): raise IndexError("Leaf must be an integer type for default max functions") - temp = self.reducer - self.reducer = None - result = self.__getitem__(key) - self.reducer = temp - return self.sLeaf(max(result)) + return self.sLeaf(max(self.getvalue(key))) def average(self, key): result = self.sum(key) @@ -465,8 +459,7 @@ class PerCpuHash(HashTable): class PerCpuArray(ArrayBase): def __init__(self, *args, **kwargs): - self.reducer = kwargs["reducer"] - del kwargs["reducer"] + self.reducer = kwargs.pop("reducer", None) super(PerCpuArray, self).__init__(*args, **kwargs) self.sLeaf = self.Leaf self.total_cpu = multiprocessing.cpu_count() @@ -483,7 +476,7 @@ class PerCpuArray(ArrayBase): else: raise IndexError("Leaf must be aligned to 8 bytes") - def __getitem__(self, key): + def getvalue(self, key): result = super(PerCpuArray, self).__getitem__(key) if self.alignment is 0: ret = result @@ -491,10 +484,13 @@ class PerCpuArray(ArrayBase): ret = (self.sLeaf * self.total_cpu)() for i in range(0, self.total_cpu): ret[i] = result[i] + return ret + + def __getitem__(self, key): if (self.reducer): - return reduce(self.reducer, ret) + return reduce(self.reducer, self.getvalue(key)) else: - return ret + return self.getvalue(key) def __setitem__(self, key, leaf): super(PerCpuArray, self).__setitem__(key, leaf) @@ -502,20 +498,12 @@ class PerCpuArray(ArrayBase): def sum(self, key): if isinstance(self.Leaf(), ct.Structure): raise IndexError("Leaf must be an integer type for default sum functions") - temp = self.reducer - self.reducer = None - result = self.__getitem__(key) - self.reducer = temp - return self.sLeaf(reduce(lambda x,y: x+y, result)) + return self.sLeaf(reduce(lambda x,y: x+y, self.getvalue(key))) def max(self, key): if isinstance(self.Leaf(), ct.Structure): raise IndexError("Leaf must be an integer type for default max functions") - temp = self.reducer - self.reducer = None - result = self.__getitem__(key) - self.reducer = temp - return self.sLeaf(max(result)) + return self.sLeaf(max(self.getvalue(key))) def average(self, key): result = self.sum(key) diff --git a/tests/python/test_percpu.py b/tests/python/test_percpu.py index fa5539d..3f89a54 100755 --- a/tests/python/test_percpu.py +++ b/tests/python/test_percpu.py @@ -2,15 +2,16 @@ # Copyright (c) PLUMgrid, Inc. # Licensed under the Apache License, Version 2.0 (the "License") +import os +import unittest from bcc import BPF -from time import sleep -import unittest as ut +import multiprocessing -class TestPercpu(ut.TestCase): +class TestPercpu(unittest.TestCase): def test_u64(self): test_prog1 = """ - BPF_TABLE("pc_hash", u32, u64, stats, 1); + BPF_TABLE("percpu_hash", u32, u64, stats, 1); int hello_world(void *ctx) { u32 key=0; u64 value = 0, *val; @@ -23,23 +24,23 @@ class TestPercpu(ut.TestCase): bpf_code = BPF(text=test_prog1) stats_map = bpf_code.get_table("stats") bpf_code.attach_kprobe(event="sys_clone", fn_name="hello_world") - sleep(1) + ini = stats_map.Leaf() + for i in range(0, multiprocessing.cpu_count()): + ini[i] = 0 + stats_map[ stats_map.Key(0) ] = ini + f = os.popen("hostname") + f.close() self.assertEqual(len(stats_map),1) - for x in range(0, 10): - ini = stats_map.Leaf(0,0,0,0,0,0,0,0) - stats_map[ stats_map.Key(0) ] = ini - sleep(1) - k = stats_map[ stats_map.Key(0) ] - x = stats_map.sum(stats_map.Key(0)) - y = stats_map.average(stats_map.Key(0)) - z = stats_map.max(stats_map.Key(0)) - print (x.value) - self.assertGreater(x.value, 1L) - self.assertGreater(z.value, 1L) + val = stats_map[ stats_map.Key(0) ] + sum = stats_map.sum(stats_map.Key(0)) + avg = stats_map.average(stats_map.Key(0)) + max = stats_map.max(stats_map.Key(0)) + self.assertGreater(sum.value, 0L) + self.assertGreater(max.value, 0L) def test_u32(self): test_prog1 = """ - BPF_TABLE("pc_array", u32, u32, stats, 1); + BPF_TABLE("percpu_array", u32, u32, stats, 1); int hello_world(void *ctx) { u32 key=0; u32 value = 0, *val; @@ -52,18 +53,19 @@ class TestPercpu(ut.TestCase): bpf_code = BPF(text=test_prog1) stats_map = bpf_code.get_table("stats") bpf_code.attach_kprobe(event="sys_clone", fn_name="hello_world") - sleep(1) + ini = stats_map.Leaf() + for i in range(0, multiprocessing.cpu_count()): + ini[i] = 0 + stats_map[ stats_map.Key(0) ] = ini + f = os.popen("hostname") + f.close() self.assertEqual(len(stats_map),1) - for x in range(0, 10): - ini = stats_map.Leaf(0,0,0,0,0,0,0,0) - stats_map[ stats_map.Key(0) ] = ini - sleep(1) - k = stats_map[ stats_map.Key(0) ] - x = stats_map.sum(stats_map.Key(0)) - y = stats_map.average(stats_map.Key(0)) - z = stats_map.max(stats_map.Key(0)) - self.assertGreater(x.value, 1L) - self.assertGreater(z.value, 1L) + val = stats_map[ stats_map.Key(0) ] + sum = stats_map.sum(stats_map.Key(0)) + avg = stats_map.average(stats_map.Key(0)) + max = stats_map.max(stats_map.Key(0)) + self.assertGreater(sum.value, 0L) + self.assertGreater(max.value, 0L) def test_struct_custom_func(self): test_prog2 = """ @@ -71,7 +73,7 @@ class TestPercpu(ut.TestCase): u32 c1; u32 c2; } counter; - BPF_TABLE("pc_hash", u32, counter, stats, 1); + BPF_TABLE("percpu_hash", u32, counter, stats, 1); int hello_world(void *ctx) { u32 key=0; counter value = {0,0}, *val; @@ -86,20 +88,19 @@ class TestPercpu(ut.TestCase): stats_map = bpf_code.get_table("stats", reducer=lambda x,y: stats_map.sLeaf(x.c1+y.c1)) bpf_code.attach_kprobe(event="sys_clone", fn_name="hello_world") - sleep(1) + ini = stats_map.Leaf() + for i in ini: + i = stats_map.sLeaf(0,0) + stats_map[ stats_map.Key(0) ] = ini + f = os.popen("hostname") + f.close() self.assertEqual(len(stats_map),1) - for x in range(0, 10): - ini = stats_map.Leaf() - for i in ini: - i = stats_map.sLeaf(0,0) - stats_map[ stats_map.Key(0) ] = ini - sleep(1) - k = stats_map[ stats_map.Key(0) ] - self.assertGreater(k.c1, 1L) + k = stats_map[ stats_map.Key(0) ] + self.assertGreater(k.c1, 0L) def cleanup(self): BPF.detach_kprobe("sys_clone") if __name__ == "__main__": - ut.main() \ No newline at end of file + unittest.main() -- 2.7.4