https://bugzilla.redhat.com/show_bug.cgi?id=1264008
The existing algorithm assumed that someone was making small, incremental
changes; however, it is possible to change iothreads from 0 (or relatively
small number) to some really large number and the algorithm would possibly
spin its wheels doing unnecessary searches.
So, optimize the algorithm in order to first detect whether there are any
iothreadid's defined in the XML. If not, then rather than add one at a time
searching for the next valid id, just allocate the whole array and populate
it as designed starting at iothread_id = 1 up to the number of iothreads
defined in the XML
Otherwise, we have a situation where "some number" of iothreadid's were
defined in the XML and we're filling in the holes of iothread_id's. Thus,
instead of determining if the iothread_id was used (ThreadIDFind) for
every ID entry that needs to be filled in, let's only call the find while
we still have holes and rather than additionally calling ThreadIDAdd
(which also calls the ThreadIDFind), let's just directly add the entry.
These algorithm changes only "penalize" those with a large iothreads
value that also have a large number of iothread id's which aren't
completely defined.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/conf/domain_conf.c | 46 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 41 insertions(+), 5 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 217179d..6c90653 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2334,6 +2334,8 @@ virDomainIOThreadIDDefArrayInit(virDomainDefPtr def)
{
unsigned int iothread_id = 1;
int retval = -1;
+ size_t i;
+ virDomainIOThreadIDDefPtr iothrid = NULL;
/* Same value (either 0 or some number), then we have none to fill in or
* the iothreadid array was filled from the XML
@@ -2341,15 +2343,49 @@ virDomainIOThreadIDDefArrayInit(virDomainDefPtr def)
if (def->iothreads == def->niothreadids)
return 0;
- while (def->niothreadids != def->iothreads) {
- if (!virDomainIOThreadIDFind(def, iothread_id)) {
- virDomainIOThreadIDDefPtr iothrid;
+ /* Optimize - there are no <iothread id='#'> in the XML */
+ if (def->niothreadids == 0) {
+ if (VIR_ALLOC_N(def->iothreadids, def->iothreads) < 0)
+ goto error;
+ def->niothreadids = def->iothreads;
+ for (i = 1; i <= def->iothreads; i++) {
+ if (VIR_ALLOC(iothrid) < 0)
+ goto error;
+ def->iothreadids[i - 1] = iothrid;
+ iothrid->iothread_id = i;
+ iothrid->autofill = true;
+ }
+ } else {
+ int found = 0;
+ int orig_nids = def->niothreadids;
+
+ /* <iothread id='#'> entries were found, then let's fill in
the
+ * holes one at a time, e.g. the relatively hard way. Rather than
+ * using ThreadIDFind and call ThreadIDAdd which also calls
+ * ThreadIDFind again which could cause lots of needless spinning
+ * let's just add the entries directly
+ */
+ for (i = 0;
+ i < def->iothreads && def->niothreadids !=
def->iothreads; i++) {
+ /* While we still have defined <thread id='#'>'s compare
our
+ * current thread_id value against the array.
+ */
+ if (found < orig_nids &&
+ virDomainIOThreadIDFind(def, iothread_id)) {
+ iothread_id++;
+ found++;
+ continue;
+ }
- if (!(iothrid = virDomainIOThreadIDAdd(def, iothread_id)))
+ /* Add a new entry using the current iothread_id */
+ if (VIR_ALLOC(iothrid) < 0)
goto error;
+ iothrid->iothread_id = iothread_id++;
iothrid->autofill = true;
+ if (VIR_APPEND_ELEMENT_COPY(def->iothreadids, def->niothreadids,
+ iothrid) < 0)
+ goto error;
}
- iothread_id++;
}
retval = 0;
--
2.1.0