From patchwork Thu May 28 08:42:25 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Fedin X-Patchwork-Id: 478105 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1YxtOf-0007kk-Qp for mharc-qemu-devel@gnu.org; Thu, 28 May 2015 04:42:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60359) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxtOa-0007dD-Gv for qemu-devel@nongnu.org; Thu, 28 May 2015 04:42:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YxtOX-0002Io-6A for qemu-devel@nongnu.org; Thu, 28 May 2015 04:42:32 -0400 Received: from mailout4.w1.samsung.com ([210.118.77.14]:59653) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YxtOW-0002If-UI for qemu-devel@nongnu.org; Thu, 28 May 2015 04:42:29 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NP100DH6XIQ2M50@mailout4.w1.samsung.com> for qemu-devel@nongnu.org; Thu, 28 May 2015 09:42:26 +0100 (BST) X-AuditID: cbfec7f4-f79c56d0000012ee-55-5566d4f2d725 Received: from eusync1.samsung.com ( [203.254.199.211]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id 1E.B6.04846.2F4D6655; Thu, 28 May 2015 09:42:26 +0100 (BST) Received: from fedinw7x64 ([106.109.131.169]) by eusync1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NP100I00XIPAI70@eusync1.samsung.com>; Thu, 28 May 2015 09:42:26 +0100 (BST) From: Pavel Fedin To: qemu-devel@nongnu.org Date: Thu, 28 May 2015 11:42:25 +0300 Message-id: <00a701d09922$39384070$aba8c150$@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7bit X-Mailer: Microsoft Outlook 14.0 Thread-index: AdCZIjjUtQIwRG9GS46tWpMDnjuisQ== Content-language: ru X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrALMWRmVeSWpSXmKPExsVy+t/xy7qfrqSFGmw7LWTR//g7u8Xx3h0s DkweT65tZvJ4v+8qWwBTFJdNSmpOZllqkb5dAlfGlp5VTAWbtCpmbJzB3MB4QaaLkZNDQsBE 4vbyHiYIW0ziwr31bF2MXBxCAksZJQ7NesYKkhAS+M4oMf9GLYjNJqAucfrrBxYQW0RAUuJ3 12lmEJtZQE9i8eF7YHFhAXeJXe9fg8VZBFQlPl9bChbnFbCUmNreAWULSvyYDFHPLKAlsX7n cSYIW15i85q3zBAHKUjsOPuaEWKXnsS5Nd9YIWpEJKb9u8c8gVFgFpJRs5CMmoVk1CwkLQsY WVYxiqaWJhcUJ6XnGuoVJ+YWl+al6yXn525ihITrlx2Mi49ZHWIU4GBU4uFVmJMWKsSaWFZc mXuIUYKDWUmEN3QTUIg3JbGyKrUoP76oNCe1+BCjNAeLkjjv3F3vQ4QE0hNLUrNTUwtSi2Cy TBycUg2MbZfSZ0S9zV+zOSypTvZxq/SaIluxpQ1rVmQ8ecG6uyByVn7RrEO3P1xV9Tl1TSX8 6sW+Rasv/rq8/ybDxod/aqrfpfeuFk/dsYhl7rTGRdzGKrb3JbctsxTgvahUYr86Xnj2X9Hm soo6zZCDP63M4zRF+k9rV7161Xdq9Uflz1OKHhTsidt0XYmlOCPRUIu5qDgRAMPSsNlTAgAA X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 210.118.77.14 Cc: 'Luiz Capitulino' Subject: [Qemu-devel] [PATCH] qobject: object_property_add() performance improvement X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 May 2015 08:42:34 -0000 The function originally behaves very badly when adding properties with "[*]" suffix. Nomnally these are used for numbering IRQ pins. In order to find the correct starting number the function started from zero and checked for duplicates. This took incredibly long time with large number of CPUs because number of IRQ pins on some architectures (like ARM GICv3) gets multiplied by number of CPUs. The solution is to add one more property which caches last used index so that duplication check is not repeated thousands of times. Every time an array is expanded the index is picked up from this cache. Cache property is a uint32_t and has the original name of the array ('name[*]') for simplicity. Some more improvements: - Call object_property_add_single() instead of recursing into itself - keeps off memcmp() check every time when its result is already known. - Allocate name_no_array only once and not every time for every property (there can be thousands of them) The modification decreases qemu startup time with 32 ARMv8 CPUs by a factor of 2 (~10 sec vs ~20 sec). Signed-off-by: Pavel Fedin --- qom/object.c | 89 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/qom/object.c b/qom/object.c index b8dff43..72480bc 100644 --- a/qom/object.c +++ b/qom/object.c @@ -10,6 +10,8 @@ * See the COPYING file in the top-level directory. */ +#include + #include "qom/object.h" #include "qemu-common.h" #include "qapi/visitor.h" @@ -721,35 +723,14 @@ void object_unref(Object *obj) } } -ObjectProperty * -object_property_add(Object *obj, const char *name, const char *type, - ObjectPropertyAccessor *get, - ObjectPropertyAccessor *set, - ObjectPropertyRelease *release, - void *opaque, Error **errp) +static ObjectProperty * +object_property_add_single(Object *obj, const char *name, const char *type, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, + void *opaque, Error **errp) { ObjectProperty *prop; - size_t name_len = strlen(name); - - if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) { - int i; - ObjectProperty *ret; - char *name_no_array = g_strdup(name); - - name_no_array[name_len - 3] = '\0'; - for (i = 0; ; ++i) { - char *full_name = g_strdup_printf("%s[%d]", name_no_array, i); - - ret = object_property_add(obj, full_name, type, get, set, - release, opaque, NULL); - g_free(full_name); - if (ret) { - break; - } - } - g_free(name_no_array); - return ret; - } QTAILQ_FOREACH(prop, &obj->properties, node) { if (strcmp(prop->name, name) == 0) { @@ -774,6 +755,60 @@ object_property_add(Object *obj, const char *name, const char *type, return prop; } +static void property_get_uint32_ptr(Object *obj, Visitor *v, + void *opaque, const char *name, + Error **errp); + +ObjectProperty * +object_property_add(Object *obj, const char *name, const char *type, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, + void *opaque, Error **errp) +{ + size_t name_len = strlen(name); + + if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) { + int i; + ObjectProperty *ret, *count; + /* 10 characters for maximum possible integer number */ + char *name_no_array = g_malloc(name_len + 10); + + count = object_property_find(obj, name, NULL); + if (count == NULL) { + void *v = g_malloc0(sizeof(uint32_t)); + + /* This is the same as object_property_add_uint32_ptr(), but: + * - Slightly faster and returns pointer + * - Will not recurse here so that we can use + * raw name with [*] here */ + count = object_property_add_single(obj, name, "uint32", + property_get_uint32_ptr, NULL, + NULL, v, &error_abort); + } + + name_len -= 2; + memcpy(name_no_array, name, name_len); + + for (i = *((uint32_t *)count->opaque); ; ++i) { + g_sprintf(&name_no_array[name_len], "%d]", i); + + ret = object_property_add_single(obj, name_no_array, type, get, set, + release, opaque, NULL); + if (ret) { + break; + } + } + *((uint32_t *)count->opaque) = i + 1; + + g_free(name_no_array); + return ret; + } + + return object_property_add_single(obj, name, type, + get, set, release, opaque, errp); +} + ObjectProperty *object_property_find(Object *obj, const char *name, Error **errp) {