From af5568843594fb71055debe36e521fa8072fcecc Mon Sep 17 00:00:00 2001
From: Bruno Randolf <br1@einfach.org>
Date: Thu, 2 Dec 2010 19:50:37 +0900
Subject: [PATCH] lib: Improve EWMA efficiency by using bitshifts
Using bitshifts instead of division and multiplication should improve
performance. That requires weight and factor to be powers of two, but i think
this is something we can live with.
Thanks to Peter Zijlstra for the improved formula!
Signedoffby: Bruno Randolf <br1@einfach.org>

v2: use log2.h functions
Signedoffby: John W. Linville <linville@tuxdriver.com>

include/linux/average.h  4 +
lib/average.c  20 ++++++++++++
2 files changed, 13 insertions(+), 11 deletions()
diff git a/include/linux/average.h b/include/linux/average.h
index 7706e40..c6028fd 100644
a

b


1  1  #ifndef _LINUX_AVERAGE_H 
2  2  #define _LINUX_AVERAGE_H 
3  3  
4   #include <linux/kernel.h> 
5   
6  4  /* Exponentially weighted moving average (EWMA) */ 
7  5  
8  6  /* For more documentation see lib/average.c */ 
… 
… 
extern struct ewma *ewma_add(struct ewma *avg, unsigned long val); 
26  24  */ 
27  25  static inline unsigned long ewma_read(const struct ewma *avg) 
28  26  { 
29   return DIV_ROUND_CLOSEST(avg>internal, avg>factor); 
 27  return avg>internal >> avg>factor; 
30  28  } 
31  29  
32  30  #endif /* _LINUX_AVERAGE_H */ 
diff git a/lib/average.c b/lib/average.c
index f1d1b46..5576c28 100644
a

b


8  8  #include <linux/module.h> 
9  9  #include <linux/average.h> 
10  10  #include <linux/bug.h> 
 11  #include <linux/log2.h> 
11  12  
12  13  /** 
13  14  * DOC: Exponentially Weighted Moving Average (EWMA) 
… 
… 

24  25  * ewma_init()  Initialize EWMA parameters 
25  26  * @avg: Average structure 
26  27  * @factor: Factor to use for the scaled up internal value. The maximum value 
27   * of averages can be ULONG_MAX/(factor*weight). 
 28  * of averages can be ULONG_MAX/(factor*weight). For performance reasons 
 29  * factor has to be a power of 2. 
28  30  * @weight: Exponential weight, or decay rate. This defines how fast the 
29   * influence of older values decreases. Has to be bigger than 1. 
 31  * influence of older values decreases. For performance reasons weight has 
 32  * to be a power of 2. 
30  33  * 
31  34  * Initialize the EWMA parameters for a given struct ewma @avg. 
32  35  */ 
33  36  void ewma_init(struct ewma *avg, unsigned long factor, unsigned long weight) 
34  37  { 
35   WARN_ON(weight <= 1  factor == 0); 
 38  WARN_ON(!is_power_of_2(weight)  !is_power_of_2(factor)); 
 39  
 40  avg>weight = ilog2(weight); 
 41  avg>factor = ilog2(factor); 
36  42  avg>internal = 0; 
37   avg>weight = weight; 
38   avg>factor = factor; 
39  43  } 
40  44  EXPORT_SYMBOL(ewma_init); 
41  45  
… 
… 
EXPORT_SYMBOL(ewma_init); 
49  53  struct ewma *ewma_add(struct ewma *avg, unsigned long val) 
50  54  { 
51  55  avg>internal = avg>internal ? 
52   (((avg>internal * (avg>weight  1)) + 
53   (val * avg>factor)) / avg>weight) : 
54   (val * avg>factor); 
 56  (((avg>internal << avg>weight)  avg>internal) + 
 57  (val << avg>factor)) >> avg>weight : 
 58  (val << avg>factor); 
55  59  return avg; 
56  60  } 
57  61  EXPORT_SYMBOL(ewma_add); 