[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2/2] xen: spread page scrubbing across all idle CPU
>>> On 10.06.14 at 14:18, <lliubbo@xxxxxxxxx> wrote: > --- a/xen/common/domain.c > +++ b/xen/common/domain.c > @@ -593,6 +593,10 @@ int domain_kill(struct domain *d) > BUG_ON(rc != -EAGAIN); > break; > } > + > + tasklet_init(&global_scrub_tasklet, scrub_free_pages, 1); > + tasklet_schedule_on_cpu(&global_scrub_tasklet, smp_processor_id()); Apart from this being a single global that you can't validly re-use this way (as already pointed out by Andrew), it also remains unclear why you want this scheduled on the current CPU rather than just anywhere. > --- a/xen/common/page_alloc.c > +++ b/xen/common/page_alloc.c > @@ -79,6 +79,14 @@ PAGE_LIST_HEAD(page_offlined_list); > /* Broken page list, protected by heap_lock. */ > PAGE_LIST_HEAD(page_broken_list); > > +/* Global scrub page list, protected by scrub_lock */ > +PAGE_LIST_HEAD(global_scrub_list); > +DEFINE_SPINLOCK(scrub_lock); > +struct tasklet global_scrub_tasklet; > + > +DEFINE_PER_CPU(struct page_list_head, scrub_list); > +DEFINE_PER_CPU(struct page_list_head, scrubbed_list); All static I suppose? > @@ -1680,6 +1693,62 @@ void scrub_one_page(struct page_info *pg) > unmap_domain_page(p); > } > > +#define SCRUB_BATCH 1024 > +void scrub_free_pages(unsigned long is_tasklet) > +{ > + struct page_info *pg; > + unsigned int i, cpu, empty = 0; > + > + cpu = smp_processor_id(); > + do > + { > + if ( page_list_empty(&this_cpu(scrub_list)) ) > + { > + /* Delist a batch of pages from global scrub list */ > + spin_lock(&scrub_lock); > + for( i = 0; i < SCRUB_BATCH; i++ ) > + { > + pg = page_list_remove_head(&global_scrub_list); > + if ( !pg ) > + { > + empty = 1; > + break; > + } > + page_list_add_tail(pg, &this_cpu(scrub_list)); > + } > + spin_unlock(&scrub_lock); > + } > + > + /* Scrub percpu list */ > + while ( !page_list_empty(&this_cpu(scrub_list)) ) > + { > + pg = page_list_remove_head(&this_cpu(scrub_list)); > + ASSERT(pg); > + scrub_one_page(pg); > + page_list_add_tail(pg, &this_cpu(scrubbed_list)); > + } So you scrub up to 1k pages at a time here - how long does that take? Did you take into consideration how much higher a wakeup latency this may cause when the invocation comes from the idle vCPU? > + /* Free percpu scrubbed list */ > + if ( !page_list_empty(&this_cpu(scrubbed_list)) ) > + { > + spin_lock(&heap_lock); > + while ( !page_list_empty(&this_cpu(scrubbed_list)) ) > + { > + pg = page_list_remove_head(&this_cpu(scrubbed_list)); > + __free_heap_pages(pg, 0); > + } > + spin_unlock(&heap_lock); > + } > + > + /* Global list is empty */ > + if (empty) > + return; > + } while ( !softirq_pending(cpu) ); > + > + if( is_tasklet ) > + tasklet_schedule_on_cpu(&global_scrub_tasklet, cpu); So you re-schedule this tasklet immediately - while this may be acceptable inside the hypervisor, did you consider the effect this will have on the guest (normally Dom0)? Its respective vCPU won't get run _at all_ until you're done scrubbing. In the end, this being an improvement by about 50% according to the numbers you gave, I'm not convinced the downsides of this are worth the gain. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |