On 20/09/2017 13:46, Alexey Kardashevskiy wrote: > This shares an cached empty FlatView among address spaces. The empty > FV is used every time when a root MR renders into a FV without memory > sections which happens when MR or its children are not enabled or > zero-sized. The empty_view is not NULL to keep the rest of memory > API intact; it also has a dispatch tree for the same reason. > > On POWER8 with 255 CPUs, 255 virtio-net, 40 PCI bridges guest this halves > the amount of FlatView's in use (557 -> 260) and dispatch tables > (~800000 -> ~370000), however the total memory footprint is pretty much > the same as RCU is holding all these temporary FVs which are created > (and then released) to make sure that they are empty and can be replaced > with @empty_view. > > Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru> > --- > memory.c | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > > diff --git a/memory.c b/memory.c > index 4add0fd030..92b1304a20 100644 > --- a/memory.c > +++ b/memory.c > @@ -48,6 +48,7 @@ static QTAILQ_HEAD(, AddressSpace) address_spaces > = QTAILQ_HEAD_INITIALIZER(address_spaces); > > static GHashTable *flat_views; > +static FlatView *empty_view; > > typedef struct AddrRange AddrRange; > > @@ -755,6 +756,19 @@ static FlatView *generate_memory_topology(MemoryRegion > *mr) > } > flatview_simplify(view); > > + if (!view->nr) { > + flatview_unref(view);
This can be changed to flatview_destroy directly to avoid overloading RCU with all these temporary FlatViews. Paolo > + if (!empty_view) { > + empty_view = flatview_new(NULL); > + } > + view = empty_view; > + flatview_ref(view); > + } > + > + if (view->dispatch) { > + return view; > + } > + > view->dispatch = address_space_dispatch_new(view); > for (i = 0; i < view->nr; i++) { > MemoryRegionSection mrs = >