input: calloc minimization for xi2mask_new
authorAdam Jackson <ajax@redhat.com>
Tue, 10 Sep 2013 18:18:18 +0000 (14:18 -0400)
committerPeter Hutterer <peter.hutterer@who-t.net>
Mon, 14 Oct 2013 01:07:37 +0000 (11:07 +1000)
There's no reason to do this as (nmasks + 2) callocs, and it's a
surprisingly hot path.  Turns out you hit this ~once per passive grab,
and you do a few bajillion passive grab changes every time you enter or
leave the overview in gnome-shell.  According to a callgrind of Xorg
with gnome-shell-perf-tool run against it:

Ir before: 721437275
Ir after:  454227086

Signed-off-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
dix/inpututils.c

index 9e38e17..a10a7c7 100644 (file)
@@ -960,8 +960,15 @@ XI2Mask *
 xi2mask_new_with_size(size_t nmasks, size_t size)
 {
     int i;
+    int alloc_size;
+    unsigned char *cursor;
+    XI2Mask *mask;
 
-    XI2Mask *mask = calloc(1, sizeof(*mask));
+    alloc_size = sizeof(struct _XI2Mask)
+              + nmasks * sizeof(unsigned char *)
+              + nmasks * size;
+
+    mask = calloc(1, alloc_size);
 
     if (!mask)
         return NULL;
@@ -969,20 +976,14 @@ xi2mask_new_with_size(size_t nmasks, size_t size)
     mask->nmasks = nmasks;
     mask->mask_size = size;
 
-    mask->masks = calloc(mask->nmasks, sizeof(*mask->masks));
-    if (!mask->masks)
-        goto unwind;
+    mask->masks = (unsigned char **)(mask + 1);
+    cursor = (unsigned char *)(mask + 1) + nmasks * sizeof(unsigned char *);
 
-    for (i = 0; i < mask->nmasks; i++) {
-        mask->masks[i] = calloc(1, mask->mask_size);
-        if (!mask->masks[i])
-            goto unwind;
+    for (i = 0; i < nmasks; i++) {
+        mask->masks[i] = cursor;
+       cursor += size;
     }
     return mask;
-
- unwind:
-    xi2mask_free(&mask);
-    return NULL;
 }
 
 /**
@@ -1003,14 +1004,9 @@ xi2mask_new(void)
 void
 xi2mask_free(XI2Mask **mask)
 {
-    int i;
-
     if (!(*mask))
         return;
 
-    for (i = 0; (*mask)->masks && i < (*mask)->nmasks; i++)
-        free((*mask)->masks[i]);
-    free((*mask)->masks);
     free((*mask));
     *mask = NULL;
 }