how to demonstrate cache-hit improvements (in sysfs callbacks) ?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



hi folks,

over on lm-sensors, we have a discussion about the merits of
2D-combo-callbacks vs 1D-callbacks.  Id like advice on how to measure
the cache effects of several variations ..

background and terminology:

0-D callback:
a dedicated callback thats used to handle a single instance of an attribute-file

1-D callback:
A routine that serves an 'array' of identical attributes, forex voltage inputs 0..10, temp 0..6, etc. These use struct sensor_attributes, which add an index onto struct device_attributes. The callback 'backcasts' from latter to former, then grabs the index, which it uses
to fetch the desired data.
The object-code savings can be significant, esp when used to clean out
functions which are macro-repeated (with ##offsets) for attr arrays of 10 or more items.


static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
{
   struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
   int index = attr->index;

      struct pc87360_data *data = pc87360_update_device(dev);
      return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[index],
                     FAN_DIV_FROM_REG(data->fan_status[index])));
}

static struct sensor_device_attribute fan_min[] = {
SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0), SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1), SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
};



2-D callbacks:
this takes an extra step, and handles multiple attribute access in one combo-callback.

static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, char *buf)
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
      int idx = attr->index;
      int func = attr->nr;
      struct pc87360_data *data = pc87360_update_device(dev);
      unsigned res = -1;

      switch(func) {
      case FN_FAN_INPUT:
              res = FAN_FROM_REG(data->fan[idx],
                                 FAN_DIV_FROM_REG(data->fan_status[idx]));
              break;
      case FN_FAN_MIN:
              res = FAN_FROM_REG(data->fan_min[idx],
                                 FAN_DIV_FROM_REG(data->fan_status[idx]));
              break;
      case FN_FAN_STATUS:
              res = FAN_STATUS_FROM_REG(data->fan_status[idx]);
              break;
      case FN_FAN_DIV:
              res = FAN_DIV_FROM_REG(data->fan_div[idx]);
              break;
      default:
              printk(KERN_ERR "unknown attr fetch\n");
      }
      return sprintf(buf, "%u\n", res);
}

Ive applied this 2nd technique to 1 driver, and see the expected code-shrink:

hwmon-stuff]$ size pre19-*/drivers/hwmon/pc87360.o
  text    data     bss     dec     hex filename
 12372    3016      29   15417    3c39 pre19-0/drivers/hwmon/pc87360.o
 10960    3432      29   14421    3855 pre19-1/drivers/hwmon/pc87360.o

[jimc@harpo hwmon-stuff]$ nm -S pre19-0/drivers/hwmon/pc87360.o |grep show_in
00000781 00000023 t show_in_alarms
0000062b 00000048 t show_in_input
000006bb 00000048 t show_in_max
00000673 00000048 t show_in_min
00000703 0000002c t show_in_status
[jimc@harpo hwmon-stuff]$ nm -S pre19-1/drivers/hwmon/pc87360.o |grep show_vin
000009e4 000000ad t show_vin

Thats all well and good, but the cache-effect has been questioned:

For example I wonder how the code above interacts with the
CPU cache, compared to 1-level-indexed callbacks, in the typical
"sensors" scenario. I don't really have the time to investigate this,
unfortunately. Switch/case is usually not recommended in performance
terms, even though I'd expect gcc to optimize it relatively nicely if
the "func" values are chosen wisely.



My initial thought is that, as 1st rule of thumb, smaller code means better cache-hits, esp instruction cache, which is I think the only concern being raised - data cache effects are far more global / action-at-a-distance, and hence unpredictable (correct?)

2nd, the standard usage pattern here is `sensors`, which appears (from output at least) to read all attributes of each sensor in turn. FWIW, given the naming convention used
for hwmon driver attributes, it describes the accesses done by
   cat /sys/devices/platform/i2c-9191/9191-6620/*

But, rather than arguing from what I 'know', Id like to learn some stuff I dont know.
SOOOO

how would I go about measuring this ?
It seems that this has generic value, and Im happy to put it up on 'our' ;-) wiki

tia
jimc

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux