This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][C++] Fix PR29433, make C++ use a lot less time/memory


This patch is the Nth try to attack the problems around 
classtype_mangled_name and the testcase in PR29433 which happens to
use 1GB of identifiers:

String pool
entries         61748 
identifiers     61748 (100.00%)
slots           131072
bytes           1009M (8320k overhead)
table size      1024k
coll/search     0.7539
ins/search      0.2796
avg. entry      17139.54 bytes (+/- 72649.10)
longest entry   2130575

so, if you compile the testcase with -O0 you end up with a
maximum virtual memory usage of around 2.5GB, if you add -g to that
it'll jump to 3.9GB (because dwarf2out.c thinks xstrduping all
identifiers again is a good idea).

With the patch below we limit the excessive identifier generation by

 - re-using identifiers we already printed somehow earlier
 - shortening identifiers by omitting context of dependent types

this results in

String pool
entries         58730
identifiers     58730 (100.00%)
slots           131072
bytes           73M (3642k overhead)
table size      1024k
coll/search     0.7525
ins/search      0.2449
avg. entry      1311.51 bytes (+/- 6277.89)
longest entry   89298

and a memory usage of around 380MB for the -O0 compile.

You may notice that we generated fewer unique identifiers which, unless
more magic is going on in the C++ frontend as I envision, does not
harm us.  To show one example of a now merged identifier (left side
is before the patch, right side after it, in order of generation):

__is_scalar<_Tp>		__is_scalar<_Tp>
__is_scalar<typename std::iterator_traits<_Iter>::value_type>
				__is_scalar<value_type>
__is_scalar<typename std::iterator_traits<_ForwardIterator2>::value_type> 
				(unified with above)

you see that we omit 'typename std::iterator_traits<_ForwardIterator2>'
and 'typename std::iterator_traits<_Iter>' where we couldn't say before
that those name distinct types and we couldn't say before that if the
second would have been named 'typename std::iterator_traits<_Iter>' also
that they do _not_ name two distinct types.  So we err on the memory
friendly side and always unify them in this case.

Pretty big savings from this patch.  Compile-time cut in half and
memory usage down from 2.5GB to 400MB.

Bootstrapped & tested on x86_64-unknown-linux-gnu.

Ok for mainline?  Mike, it looks like you invented 
mangle_class_name_for_template - do you remember what invariants
the identifiers it generates have to guarantee?

Thanks,
Richard.

:ADDPATCH C++:

2006-11-27  Richard Guenther  <rguenther@suse.de>

	PR c++/29433
	* pt.c (mangle_class_name_for_template): Use cached
	names where appropriate.

Index: pt.c
===================================================================
*** pt.c	(revision 119249)
--- pt.c	(working copy)
*************** mangle_class_name_for_template (const ch
*** 4290,4296 ****
  
        if (TREE_CODE (parm) == TYPE_DECL)
  	{
! 	  cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
  	  continue;
  	}
        else if (TREE_CODE (parm) == TEMPLATE_DECL)
--- 4291,4302 ----
  
        if (TREE_CODE (parm) == TYPE_DECL)
  	{
! 	  if (TYPE_NAME (arg)
! 	      && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
! 	      && DECL_NAME (TYPE_NAME (arg)))
! 	    cat (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (arg))));
! 	  else
! 	    cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
  	  continue;
  	}
        else if (TREE_CODE (parm) == TEMPLATE_DECL)
*************** mangle_class_name_for_template (const ch
*** 4313,4320 ****
  	      cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
  	    }
  	  else
! 	    /* Output the parameter declaration.  */
! 	    cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
  	  continue;
  	}
        else
--- 4319,4333 ----
  	      cat (IDENTIFIER_POINTER (DECL_NAME (arg)));
  	    }
  	  else
! 	    {
! 	      if (TYPE_NAME (arg)
! 		  && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL
! 		  && DECL_NAME (TYPE_NAME (arg)))
! 		cat (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (arg))));
! 	      else
! 		/* Output the parameter declaration.  */
! 		cat (type_as_string (arg, TFF_CHASE_TYPEDEF));
! 	    }
  	  continue;
  	}
        else


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]