[PATCH] input: calloc minimization for xi2mask_new

Adam Jackson ajax at redhat.com
Tue Sep 10 11:18:18 PDT 2013


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 at redhat.com>
---
 dix/inpututils.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/dix/inpututils.c b/dix/inpututils.c
index 9e38e17..a10a7c7 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -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;
 }
-- 
1.8.3.1



More information about the xorg-devel mailing list