[PERF] Turn some pimpl pointers into naked pointers

The private data pointers of libabigail IR types are usually managed
using shared_ptr.  But performance profiling has shown that
de-referencing some of these private data shared_ptr can have a
noticeable performance impact.  This is because de-referencing
shared_ptr involves some locking that show up on some performance
profile.

So, for decl_base, type_base, and function_decl, this patch replaces
the private data shared pointers by naked pointers.  This speeds up
the access to private data members, especially during comparison of
class pointer, reference and function types.  And that has a
noticeable impact when libabigail handles huge binaries with lots of
functions an type, like r300_dri.so.

	* include/abg-ir.h ({decl_base, type_base, function_decl}::priv_)
	Make this a naked pointer to priv, rather than a shared_ptr<priv>.
	* src/abg-ir.cc (decl_base::~decl_base): Destroy the private data
	pointer, aka pimpl pointer.
	(type_base::~type_base): Likewise.
	(function_decl::~function_decl): Likewise.
	(class_decl::~class_decl): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2015-12-11 10:33:28 +01:00
parent 1466510881
commit c0de97846c
2 changed files with 44 additions and 12 deletions

View File

@ -949,7 +949,6 @@ class decl_base : public virtual type_or_decl_base
decl_base();
struct priv;
typedef shared_ptr<priv> priv_sptr;
protected:
@ -968,8 +967,15 @@ protected:
public:
// This is public because some internals of the library need to
// update it. But it's opaque to client code anyway, so no big
// deal.
priv_sptr priv_;
// deal. Also, it's not handled by a shared_ptr because accessing
// the data members of the priv struct for this decl_base shows up
// on performance profiles when dealing with big binaries with a lot
// of types; dereferencing the shared_ptr involves locking of some
// sort and that is slower than just dereferencing a pointer likere
// here. There are other types for which the priv pointer is
// managed using shared_ptr just fine, because those didn't show up
// during our performance profiling.
priv* priv_;
/// Facility to hash instances of decl_base.
struct hash;
@ -1283,10 +1289,17 @@ equals(const type_base&, const type_base&, change_kind*);
class type_base : public virtual type_or_decl_base
{
struct priv;
typedef shared_ptr<priv> priv_sptr;
protected:
priv_sptr priv_;
// This priv pointer is not handled by a shared_ptr because
// accessing the data members of the priv struct for this type_base
// shows up on performance profiles when dealing with big binaries
// with a lot of types; dereferencing the shared_ptr involves
// locking of some sort and that is slower than just dereferencing a
// pointer likere here. There are other types for which the priv
// pointer is managed using shared_ptr just fine, because those
// didn't show up during our performance profiling.
priv* priv_;
private:
// Forbid this.
@ -2137,7 +2150,15 @@ typedef shared_ptr<function_decl> function_decl_sptr;
class function_decl : public virtual decl_base
{
struct priv;
shared_ptr<priv> priv_;
// This priv pointer is not handled by a shared_ptr because
// accessing the data members of the priv struct for this
// function_decl shows up on performance profiles when dealing with
// big binaries with a lot of types; dereferencing the shared_ptr
// involves locking of some sort and that is slower than just
// dereferencing a pointer likere here. There are other types for
// which the priv pointer is managed using shared_ptr just fine,
// because those didn't show up during our performance profiling.
priv* priv_;
public:
/// Hasher for function_decl
@ -2876,8 +2897,15 @@ public:
private:
struct priv;
typedef shared_ptr<priv> priv_sptr;
priv_sptr priv_;
// This priv it's not handled by a shared_ptr because accessing the
// data members of the priv struct for this class_decl shows up on
// performance profiles when dealing with big binaries with a lot of
// types; dereferencing the shared_ptr involves locking of some sort
// and that is slower than just dereferencing a pointer likere here.
// There are other types for which the priv pointer is managed using
// shared_ptr just fine, because those didn't show up during our
// performance profiling.
priv * priv_;
protected:
virtual decl_base_sptr

View File

@ -2458,8 +2458,9 @@ bool
decl_base::operator==(const decl_base& other) const
{return equals(*this, other, 0);}
/// Destructor of the @ref decl_base type.
decl_base::~decl_base()
{}
{delete priv_;}
/// This implements the ir_traversable_base::traverse pure virtual
/// function.
@ -6561,7 +6562,8 @@ type_base::traverse(ir_node_visitor& v)
}
type_base::~type_base()
{}
{delete priv_;}
// </type_base definitions>
//<type_decl definitions>
@ -10196,8 +10198,9 @@ function_decl::traverse(ir_node_visitor& v)
return v.visit_end(this);
}
/// Destructor of the @ref function_decl type.
function_decl::~function_decl()
{}
{delete priv_;}
// <function_decl definitions>
@ -12140,8 +12143,9 @@ class_decl::traverse(ir_node_visitor& v)
return v.visit_end(this);
}
/// Destructor of the @ref class_decl type.
class_decl::~class_decl()
{}
{delete priv_;}
context_rel::~context_rel()
{}