From: Zaafar Ahmed Date: Tue, 29 Mar 2016 17:13:50 +0000 (+0500) Subject: optimised the percpu support patch. X-Git-Tag: v0.2.0~129^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=642582560fcf15aa3815957edecd8fcc0a2bff3f;p=platform%2Fupstream%2Fbcc.git optimised the percpu support patch. removed kernel checks. --- diff --git a/src/cc/frontends/clang/b_frontend_action.cc b/src/cc/frontends/clang/b_frontend_action.cc index 1ba30cb..358a894 100644 --- a/src/cc/frontends/clang/b_frontend_action.cc +++ b/src/cc/frontends/clang/b_frontend_action.cc @@ -571,11 +571,9 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) { } else if (A->getName() == "maps/array") { map_type = BPF_MAP_TYPE_ARRAY; } else if (A->getName() == "maps/pc_hash") { - if (KERNEL_VERSION(major,minor,0) >= KERNEL_VERSION(4,5,0)) - map_type = BPF_MAP_TYPE_PERCPU_HASH; + map_type = BPF_MAP_TYPE_PERCPU_HASH; } else if (A->getName() == "maps/pc_array") { - if (KERNEL_VERSION(major,minor,0) >= KERNEL_VERSION(4,5,0)) - map_type = BPF_MAP_TYPE_PERCPU_ARRAY; + map_type = BPF_MAP_TYPE_PERCPU_ARRAY; } else if (A->getName() == "maps/histogram") { if (table.key_desc == "\"int\"") map_type = BPF_MAP_TYPE_ARRAY; diff --git a/src/python/bcc/__init__.py b/src/python/bcc/__init__.py index a286f26..0da5632 100644 --- a/src/python/bcc/__init__.py +++ b/src/python/bcc/__init__.py @@ -228,7 +228,7 @@ class BPF(object): cls = type(str(desc[0]), (base,), dict(_fields_=fields)) return cls - def get_table(self, name, keytype=None, leaftype=None, func_reducer=None): + def get_table(self, name, keytype=None, leaftype=None, reducer=None): map_id = lib.bpf_table_id(self.module, name.encode("ascii")) map_fd = lib.bpf_table_fd(self.module, name.encode("ascii")) if map_fd < 0: @@ -243,7 +243,7 @@ class BPF(object): if not leaf_desc: raise Exception("Failed to load BPF Table %s leaf desc" % name) leaftype = BPF._decode_table_type(json.loads(leaf_desc.decode())) - return Table(self, map_id, map_fd, keytype, leaftype, func_reducer) + return Table(self, map_id, map_fd, keytype, leaftype, reducer=reducer) def __getitem__(self, key): if key not in self.tables: diff --git a/src/python/bcc/table.py b/src/python/bcc/table.py index f1c317d..47d5227 100644 --- a/src/python/bcc/table.py +++ b/src/python/bcc/table.py @@ -74,8 +74,8 @@ def _print_log2_hist(vals, val_type): _stars(val, val_max, stars))) -def Table(bpf, map_id, map_fd, keytype, leaftype, func_reducer): - """Table(bpf, map_id, map_fd, keytype, leaftype, func_reducer) +def Table(bpf, map_id, map_fd, keytype, leaftype, **kwargs): + """Table(bpf, map_id, map_fd, keytype, leaftype, **kwargs) Create a python object out of a reference to a bpf table handle""" @@ -90,11 +90,9 @@ def Table(bpf, map_id, map_fd, keytype, leaftype, func_reducer): elif ttype == BPF_MAP_TYPE_PERF_EVENT_ARRAY: t = PerfEventArray(bpf, map_id, map_fd, keytype, leaftype) elif ttype == BPF_MAP_TYPE_PERCPU_HASH: - t = PerCpuHash(bpf, map_id, map_fd, keytype, - leaftype, func=func_reducer) + t = PerCpuHash(bpf, map_id, map_fd, keytype, leaftype, **kwargs) elif ttype == BPF_MAP_TYPE_PERCPU_ARRAY: - t = PerCpuArray(bpf, map_id, map_fd, keytype, - leaftype, func=func_reducer) + t = PerCpuArray(bpf, map_id, map_fd, keytype, leaftype, **kwargs) elif ttype == BPF_MAP_TYPE_STACK_TRACE: t = StackTrace(bpf, map_id, map_fd, keytype, leaftype) if t == None: @@ -149,9 +147,9 @@ class TableBase(MutableMapping): raise Exception("Could not scanf leaf") return leaf - def __getitem__(self, key, leaf=None): + def __getitem__(self, key): key_p = ct.pointer(key) - if not leaf: leaf = self.Leaf() + leaf = self.Leaf() leaf_p = ct.pointer(leaf) res = lib.bpf_lookup_elem(self.map_fd, ct.cast(key_p, ct.c_void_p), @@ -312,9 +310,9 @@ class ArrayBase(TableBase): def __len__(self): return self.max_entries - def __getitem__(self, key, leaf=None): + def __getitem__(self, key): key = self._normalize_key(key) - return super(ArrayBase, self).__getitem__(key, leaf) + return super(ArrayBase, self).__getitem__(key) def __setitem__(self, key, leaf): key = self._normalize_key(key) @@ -408,127 +406,121 @@ class PerfEventArray(ArrayBase): class PerCpuHash(HashTable): def __init__(self, *args, **kwargs): - self.func_reducer = kwargs['func'] - del kwargs['func'] - self.total_cpu = multiprocessing.cpu_count() - self.alignment = int(check_output(["grep", "-m", "1", "cache_alignment", "/proc/cpuinfo"]).split(' ', 2)[1])/8 + self.reducer = kwargs["reducer"] + del kwargs["reducer"] super(PerCpuHash, self).__init__(*args, **kwargs) - self.leafsize = ct.sizeof(self.Leaf) - if isinstance(self.Leaf(), ct.Structure) and self.leafsize % self.alignment is not 0: - # Struct that are not aligned to cache. - raise IndexError("Struct must be aligned to %s, please add some padding" % self.alignment) + self.sLeaf = self.Leaf + self.total_cpu = multiprocessing.cpu_count() + # This needs to be 8 as hard coded into the linux kernel. + self.alignment = ct.sizeof(self.sLeaf) % 8 + if self.alignment is 0: + self.Leaf = self.sLeaf * self.total_cpu + else: + # Currently Float, Char, un-aligned structs are not supported + if self.sLeaf == ct.c_uint: + self.Leaf = ct.c_uint64 * self.total_cpu + elif self.sLeaf == ct.c_int: + self.Leaf = ct.c_int64 * self.total_cpu + else: + raise IndexError("Leaf must be aligned to 8 bytes") def __getitem__(self, key): - if self.leafsize % self.alignment is 0: - # Struct/DataTypes that are aligned to cache - leaf_arr = (self.Leaf * self.total_cpu)() + result = super(PerCpuHash, self).__getitem__(key) + if self.alignment is 0: + ret = result else: - # DataTypes that are not aligned to cache - leaf_arr = (ct.c_uint64 * self.total_cpu)() - - if (self.func_reducer): - super(PerCpuHash, self).__getitem__(key, leaf_arr) - leaf_ret = (self.Leaf * self.total_cpu)() + ret = (self.sLeaf * self.total_cpu)() for i in range(0, self.total_cpu): - leaf_ret[i] = leaf_arr[i] - return reduce(self.func_reducer, leaf_ret) + ret[i] = result[i] + if (self.reducer): + return reduce(self.reducer, ret) else: - super(PerCpuHash,self).__getitem__(key,leaf_arr) - leaf_ret = (self.Leaf * self.total_cpu)() - for i in range(0, self.total_cpu): - leaf_ret[i] = leaf_arr[i] - return leaf_ret + return ret def __setitem__(self, key, leaf): - if self.leafsize % self.alignment is 0: - leaf_arr = (self.Leaf * self.total_cpu)() - for i in range(0, self.total_cpu): - leaf_arr[i] = leaf - else: - leaf_arr = (ct.c_uint64 * self.total_cpu)() - for i in range(0, self.total_cpu): - leaf_arr[i] = leaf.value - super(PerCpuHash, self).__setitem__(key, leaf_arr) + super(PerCpuHash, self).__setitem__(key, leaf) def sum(self, key): if isinstance(self.Leaf(), ct.Structure): raise IndexError("Leaf must be an integer type for default sum functions") - leaf_arr = (ct.c_uint64 * self.total_cpu)() - return self.Leaf(reduce(lambda x,y: x+y, super(PerCpuHash, self).__getitem__(key, leaf_arr))) + temp = self.reducer + self.reducer = None + result = self.__getitem__(key) + self.reducer = temp + return self.sLeaf(reduce(lambda x,y: x+y, result)) def max(self, key): if isinstance(self.Leaf(), ct.Structure): - raise IndexError("Leaf must be an integer type for default sum functions") - leaf_arr = (ct.c_uint64 * self.total_cpu)() - return self.Leaf(max(super(PerCpuHash, self).__getitem__(key, leaf_arr))) + 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)) def average(self, key): - if isinstance(self.Leaf(), ct.Structure): - raise IndexError("Leaf must be an integer type for default sum functions") - leaf_arr = (ct.c_uint64 * self.total_cpu)() - return self.Leaf(reduce(lambda x,y: x+y, super(PerCpuHash, self).__getitem__(key, leaf_arr))/self.total_cpu) + result = self.sum(key) + result.value/=self.total_cpu + return result class PerCpuArray(ArrayBase): def __init__(self, *args, **kwargs): - self.func_reducer = kwargs['func'] - del kwargs['func'] - self.total_cpu = multiprocessing.cpu_count() - self.alignment = int(check_output(["grep", "-m", "1", "cache_alignment", "/proc/cpuinfo"]).split(' ', 2)[1])/8 + self.reducer = kwargs["reducer"] + del kwargs["reducer"] super(PerCpuArray, self).__init__(*args, **kwargs) - self.leafsize = ct.sizeof(self.Leaf) - if isinstance(self.Leaf(), ct.Structure) and self.leafsize % self.alignment is not 0: - # Struct that are not aligned to cache. - raise IndexError("Struct must be aligned to %s, please add some padding" % self.alignment) + self.sLeaf = self.Leaf + self.total_cpu = multiprocessing.cpu_count() + # This needs to be 8 as hard coded into the linux kernel. + self.alignment = ct.sizeof(self.sLeaf) % 8 + if self.alignment is 0: + self.Leaf = self.sLeaf * self.total_cpu + else: + # Currently Float, Char, un-aligned structs are not supported + if self.sLeaf == ct.c_uint: + self.Leaf = ct.c_uint64 * self.total_cpu + elif self.sLeaf == ct.c_int: + self.Leaf = ct.c_int64 * self.total_cpu + else: + raise IndexError("Leaf must be aligned to 8 bytes") def __getitem__(self, key): - if self.leafsize % self.alignment is 0: - # Struct/DataTypes that are aligned to cache - leaf_arr = (self.Leaf * self.total_cpu)() + result = super(PerCpuArray, self).__getitem__(key) + if self.alignment is 0: + ret = result else: - # DataTypes that are not aligned to cache - leaf_arr = (ct.c_uint64 * self.total_cpu)() - - if (self.func_reducer): - super(PerCpuArray, self).__getitem__(key, leaf_arr) - leaf_ret = (self.Leaf * self.total_cpu)() + ret = (self.sLeaf * self.total_cpu)() for i in range(0, self.total_cpu): - leaf_ret[i] = leaf_arr[i] - return reduce(self.func_reducer, leaf_ret) + ret[i] = result[i] + if (self.reducer): + return reduce(self.reducer, ret) else: - super(PerCpuArray,self).__getitem__(key,leaf_arr) - leaf_ret = (self.Leaf * self.total_cpu)() - for i in range(0, self.total_cpu): - leaf_ret[i] = leaf_arr[i] - return leaf_ret + return ret def __setitem__(self, key, leaf): - if self.leafsize % self.alignment is 0: - leaf_arr = (self.Leaf * self.total_cpu)() - for i in range(0, self.total_cpu): - leaf_arr[i] = leaf - else: - leaf_arr = (ct.c_uint64 * self.total_cpu)() - for i in range(0, self.total_cpu): - leaf_arr[i] = leaf.value - super(PerCpuArray, self).__setitem__(key, leaf_arr) + super(PerCpuArray, self).__setitem__(key, leaf) def sum(self, key): if isinstance(self.Leaf(), ct.Structure): raise IndexError("Leaf must be an integer type for default sum functions") - leaf_arr = (ct.c_uint64 * self.total_cpu)() - return self.Leaf(reduce(lambda x,y: x+y, super(PerCpuArray, self).__getitem__(key, leaf_arr))) + temp = self.reducer + self.reducer = None + result = self.__getitem__(key) + self.reducer = temp + return self.sLeaf(reduce(lambda x,y: x+y, result)) def max(self, key): if isinstance(self.Leaf(), ct.Structure): - raise IndexError("Leaf must be an integer type for default sum functions") - leaf_arr = (ct.c_uint64 * self.total_cpu)() - return self.Leaf(max(super(PerCpuArray, self).__getitem__(key, leaf_arr))) + 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)) def average(self, key): - if isinstance(self.Leaf(), ct.Structure): - raise IndexError("Leaf must be an integer type for default sum functions") - leaf_arr = (ct.c_uint64 * self.total_cpu)() - return self.Leaf(reduce(lambda x,y: x+y, super(PerCpuArray, self).__getitem__(key, leaf_arr))/self.total_cpu) + result = self.sum(key) + result.value/=self.total_cpu + return result class StackTrace(TableBase): def __init__(self, *args, **kwargs):