Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large commit with very significant speedup of class/object method calls ... #4

Closed
wants to merge 1 commit into from
Closed

Conversation

syberrus
Copy link
Contributor

...and several more features:

  1. Added hashmap.h - extremely fast low-level C hash to use for perl code needs (see below).

  2. Speeding up stash cache, make gv_stash* use the cache and by this make all of perl core and XS modules use
    this cache, not only S_method_common.

    • Change PL_stashcache from HV* to SVMAP* (hashmap of SVMAP_ENT values)
    • The lowest-level function is now gv_stashent which receives precomputed hash64 value for class name
      and searches the cache. If nothing found, calls slow S_gv_stashpvn (former Perl_gv_stashpvn) and
      fills the cache.
    • gv_stashpvn is now a wrapper for gv_stashent, computing hash value.
    • add API functions to clear stash cache locally (1 class) and globally. Make use of them.
    • added one more flag to gv_stash* - GV_CACHE_ONLY which returns stash only if found in cache,
      otherwise NULL. Required for correct behaviour of rule "IO globs take precedence over class names".
    • use private hash function PERL_HASH64 for computing hash values for class names. This function is
      much faster than PERL_HASH function (especially for long keys, which is likely for full class names)
      and returns a 64bit value. It doesn't use randomization because stash cache is a private core data,
      not a user data.
  3. Speeding up method cache and super method cache, make gv_fetchmeth_/gv_fetchmethod_ use the cache.

    • store method cache in meta->mro_method instead of package stash's HV itself.
    • rename meta->mro_super -> meta->mro_supermethod
    • meta->mro_method & meta->mro_supermethod are both SVMAP*
    • The lowest-level function for gv_fetchmeth* is now gv_fetchmeth_ent which receives precomputed
      hash value for method name.
    • gv_fetchmeth_pvn is now a wrapper for gv_fetchmeth_ent, computing hash64 value.
    • The lowest-level function for gv_fetchmethod* is now gv_fetchmethod_ent which receives precomputed
      hash value for method name. Method cannot contain '::', gv_fetchmethod_ent doesn't search for '::'.
    • gv_fetchmethod_pvn is now a wrapper for gv_fetchmethod_ent, searching for '::', changing method name
      (and possibly stash, flags) and computing hash64 value.
    • new flag for gv_fetchmethod_pvn - GV_METHOD_SIMPLE, which means gv_fetchmethod_pvn doesn't need to scan
      for '::' in method name.
  4. Precomputing hash64 values for perl code.

    • added 2 more op types:
      • OP_METHOD_SUPER "$proto->SUPER::func()"
      • OP_METHOD_REDIR "$proto->OtherClass::func()" or "$proto->OtherClass::SUPER::func()"
    • added new op struct type - struct methop (typedef METHOP).
      It actually behaves like UNOP for OP_METHOD and like SVOP for OP_METHOD_* and fully compatible with
      them for backward compability. It contains additional fields:
      • hash for method name (for OP_METHOD__). Method name SV and targ are still in ->op_sv and ->op_targ
      • hash, sv and targ for class name (for all types)
      • hash, sv and targ for redirect class name (for OP_METHOD_REDIR)
    • ck_method detects const method name, fills hash and sv, and creates OP_METHOD_NAMED
    • ck_method detects const method name with SUPER keyword, fills hash and sv, and creates OP_METHOD_SUPER
    • ck_method detects const method name with class redirect (possibly with SUPER keyword),
      fills hash, sv, rclass hash and rclass sv and creates OP_METHOD_REDIR
    • ck_subr now detects if left operand is a const (MyClass->method()), and stores the data (class hash and sv)
      in underlying OP_METHOD_ op.
    • all of these infos are used in runtime to greatly speedup pp_method* calls
  5. OOP context for XSUBs.
    Calculated stash HV of left operand (object/class/IO/etc) is now saved in PL_methstash for later use by XSUBS.
    This prevents double caclucation of stash's HV for such functions as UNIVERSAL::can and so on and speeds up them
    a lot.
    Moreover it has one more usage: pp_entersub sets PL_methstash to NULL if CV is called as function, and sets
    PL_methstash to object/class/IO/etc stash's HV if CV is called as class/object/etc method.
    This makes it possible for XS code to detect if it is called as funtion or method in case if user wants to implement
    separate behaviour for those cases.
    For example if (PL_methstash) { ... called as method, object/class/etc stash is in PL_methstash }
    else { ... called as function }
    Additionaly for XSUBs like UNIVERSAL::can which always want to interpret its calls as method calls (i.e. first arg is
    object/class/etc), there is a macro dMETHSTASH which defines variable 'HV* stash' and either sets it to PL_methstash
    (if called as method) or (if called as function) calculate stash in the same way as pp_method* would do in case of
    real method call.
    Note that PL_methstash is not stacked (to not introduce any overheat), that means you have to either use it
    before you made a new perl CV call or save it to a variable.

  6. Bring B, B::Deparse and B::Concise in consistency with new ops.

  7. misc:

  • bugfix in Opcode.xs: _safe_call_sv (and therefore module Safe) had critical vulnerability
    which made it possible for code in $safe->reval("...") to hack your entire program.
  • Remove "local's" unneccesary overheat. ("local GLOB = GLOB" - OK, "local GLOB = CODEREF" - OVERHEAT)
    {
    local *MyClass::func = sub {...}; # LINE A
    ...
    } # LINE B
    This example caused global method cache reset at both lines A and B because glob_assign_ref and leave_scope
    thought that GV's GP refcnt was 2 (because of saving to Save Stack).
    Issue has been fixed (added gp_flags and new GP flag LOCALIZED, if flag is set then 1 refcnt from save stack is
    not counted in gv_method_changed calls).
  • bugfix in dump.c : sv_dump(stash) (where stash is HV* - someone's stash) crashes if stash has cached destructor -
    sv_dump thought that it was a stash and tried to dump CV* as HV*.
  • UNIVERSAL::can (in universal.c) is rewritten to make use of PL_methstash and runs much faster now.

…ls and several more features:

1) Added hashmap.h - extremely fast low-level C hash to use for perl code needs (see below).

2) Speeding up stash cache, make gv_stash* use the cache and by this make all of perl core and XS modules use
   this cache, not only S_method_common.
     - Change PL_stashcache from HV* to SVMAP* (hashmap of SVMAP_ENT values)
     - The lowest-level function is now gv_stashent which receives precomputed hash64 value for class name
       and searches the cache. If nothing found, calls slow S_gv_stashpvn (former Perl_gv_stashpvn) and
       fills the cache.
     - gv_stashpvn is now a wrapper for gv_stashent, computing hash value.
     - add API functions to clear stash cache locally (1 class) and globally. Make use of them.
     - added one more flag to gv_stash* - GV_CACHE_ONLY which returns stash only if found in cache,
       otherwise NULL. Required for correct behaviour of rule "IO globs take precedence over class names".
     - use private hash function PERL_HASH64 for computing hash values for class names. This function is
       much faster than PERL_HASH function (especially for long keys, which is likely for full class names)
       and returns a 64bit value. It doesn't use randomization because stash cache is a private core data,
       not a user data.

3) Speeding up method cache and super method cache, make gv_fetchmeth*/gv_fetchmethod* use the cache.
     - store method cache in meta->mro_method instead of package stash's HV itself.
	 - rename meta->mro_super -> meta->mro_supermethod
	 - meta->mro_method & meta->mro_supermethod are both SVMAP*
	 - The lowest-level function for gv_fetchmeth* is now gv_fetchmeth_ent which receives precomputed
	   hash value for method name.
	 - gv_fetchmeth_pvn is now a wrapper for gv_fetchmeth_ent, computing hash64 value.
	 - The lowest-level function for gv_fetchmethod* is now gv_fetchmethod_ent which receives precomputed
	   hash value for method name. Method cannot contain '::', gv_fetchmethod_ent doesn't search for '::'.
	 - gv_fetchmethod_pvn is now a wrapper for gv_fetchmethod_ent, searching for '::', changing method name
	   (and possibly stash, flags) and computing hash64 value.
	 - new flag for gv_fetchmethod_pvn - GV_METHOD_SIMPLE, which means gv_fetchmethod_pvn doesn't need to scan
	   for '::' in method name.

4) Precomputing hash64 values for perl code.
     - added 2 more op types:
	   - OP_METHOD_SUPER "$proto->SUPER::func()"
	   - OP_METHOD_REDIR "$proto->OtherClass::func()" or "$proto->OtherClass::SUPER::func()"
	 - added new op struct type - struct methop (typedef METHOP).
	   It actually behaves like UNOP for OP_METHOD and like SVOP for OP_METHOD_* and fully compatible with
	   them for backward compability. It contains additional fields:
	     - hash for method name (for OP_METHOD_*). Method name SV and targ are still in ->op_sv and ->op_targ
		 - hash, sv and targ for class name (for all types)
		 - hash, sv and targ for redirect class name (for OP_METHOD_REDIR)
     - ck_method detects const method name, fills hash and sv, and creates OP_METHOD_NAMED
	 - ck_method detects const method name with SUPER keyword, fills hash and sv, and creates OP_METHOD_SUPER
	 - ck_method detects const method name with class redirect (possibly with SUPER keyword),
	   fills hash, sv, rclass hash and rclass sv and creates OP_METHOD_REDIR
	 - ck_subr now detects if left operand is a const (MyClass->method()), and stores the data (class hash and sv)
   	   in underlying OP_METHOD* op.
	 - all of these infos are used in runtime to greatly speedup pp_method* calls

5) OOP context for XSUBs.
   Calculated stash HV of left operand (object/class/IO/etc) is now saved in PL_methstash for later use by XSUBS.
   This prevents double caclucation of stash's HV for such functions as UNIVERSAL::can and so on and speeds up them
   a lot.
   Moreover it has one more usage: pp_entersub sets PL_methstash to NULL if CV is called as function, and sets
   PL_methstash to object/class/IO/etc stash's HV if CV is called as class/object/etc method.
   This makes it possible for XS code to detect if it is called as funtion or method in case if user wants to implement
   separate behaviour for those cases.
   For example    if (PL_methstash) { ... called as method, object/class/etc stash is in PL_methstash }
                  else { ... called as function }
   Additionaly for XSUBs like UNIVERSAL::can which always want to interpret its calls as method calls (i.e. first arg is
   object/class/etc), there is a macro dMETHSTASH which defines variable 'HV* stash' and either sets it to PL_methstash
   (if called as method) or (if called as function) calculate stash in the same way as pp_method* would do in case of
   real method call.
   Note that PL_methstash is not stacked (to not introduce any overheat), that means you have to either use it
   before you made a new perl CV call or save it to a variable.

6) Bring B, B::Deparse and B::Concise in consistency with new ops.

7) misc:
   - bugfix in Opcode.xs: _safe_call_sv (and therefore module Safe) had critical vulnerability
     which made it possible for code in $safe->reval("...") to hack your entire program.
   - Remove "local's" unneccesary overheat. ("local GLOB = GLOB" - OK, "local GLOB = CODEREF" - OVERHEAT)
     {
        local *MyClass::func = sub {...}; # LINE A
		...
	 } # LINE B
	 This example caused global method cache reset at both lines A and B because glob_assign_ref and leave_scope
	 thought that GV's GP refcnt was 2 (because of saving to Save Stack).
	 Issue has been fixed (added gp_flags and new GP flag LOCALIZED, if flag is set then 1 refcnt from save stack is
	 not counted in gv_method_changed calls).
   - bugfix in dump.c : sv_dump(stash) (where stash is HV* - someone's stash) crashes if stash has cached destructor -
     sv_dump thought that it was a stash and tried to dump CV* as HV*.
   - UNIVERSAL::can (in universal.c) is rewritten to make use of PL_methstash and runs much faster now.
@seveas
Copy link
Contributor

seveas commented Jul 24, 2014

hi @syberrus,

The perl developers don't use pull requests. Patches should be sent as RT tickets. I'd also advise you to split up this huge patch into smaller, self-contained ones which will be easier to review and apply.

@syberrus
Copy link
Contributor Author

Unfortunately i can't split. Because data types of caches have changed, this leaded to a lot of changes in a lot of files.
I've spent about 2 weeks testing it with all of perl core tests and a lot of cpan modules. Everything seems to work. Except for a couple of modules, but they have buggy tests. I'll post to perl 5 list with explanation of all the details and benchmarks a little later.

@syberrus syberrus closed this Jul 30, 2014
p5p pushed a commit that referenced this pull request Feb 19, 2016
This has large memory savings, test prog,
perl -MTest::More -e"system 'pause'"
before 2196KB Private Bytes Win 7 32 bit to after 2092KB.

-On a CHEK the refcount is a U32 for memory savings on 64 bit CPUs while
 SHEKs are Size_t for refcount because of HE struct, on 32 bit Size_t and
 U32 happen to be the same thing, if there is future integration the
 refcount members will have to be the same type, then duping a SHEK or
 a CHEK is the same code, except that HVhek_COMPILING controls whether to
 aquire OP_REFCNT_LOCK before touching the ref count, in the future with
 atomic operations, the refcount can be manipulated with atomic operations
 regardless if it is a SHEK or CHEK since OP_REFCNT_LOCK lines were removed
-TODO figure out how to do static const CHEKs, hash member must be 0
 since its process specific randomized (rurban's B stores HEKs in RW static
 memory and fixes up the hash #s at runtime), add test and branch
 so that refcount isn't read and written or passed to PerlMemShared_free
 if static flag is on inidicating static const CHEK
-TODO Perl_newGP uses CHEKs not CopFILE, no memcpy and add _< that way
-TODO optimize the former alloca to smallbuf or Safefree or savestack
 newx free
p5p pushed a commit that referenced this pull request Feb 14, 2017
At this maximal level of debugging output, it displays the top 3 state
stack entries each time it pushes, but with no obvious indication that
a push is occurring. This commit changes this output:

                             |   1|  Setting an EVAL scope, savestack=9,
                             |   2|   #4   WHILEM_A_max
                             |   2|   #3   WHILEM_A_max
                             |   2|   #2   CURLYX_end yes
   0 <abcdef> <g>            |   2|   4:POSIXD[\w](5)

to be this (which includes the word "push" and extra indentation for the
stack dump):

                             |   1|  Setting an EVAL scope, savestack=9,
                             |   2|   push #4   WHILEM_A_max
                             |   2|        #3   WHILEM_A_max
                             |   2|        #2   CURLYX_end yes
   0 <abcdef> <g>            |   2|   4:POSIXD[\w](5)

Also, replace curd (current depth) var with a positive integer offset
(i) var, to avoid signed/unsigned mixing problems.
rjbs added a commit to rjbs/perl5 that referenced this pull request Apr 6, 2020
This requires a few small changes.

1. add a new option, which I stored in what looked like one of the
   standard ways
2. only store the item in terminal history if >= this length
3. only add to @hist if >= this length
4. only display hist item if >= this length

I believe Perl#4 is redundant and should be removed, but the code was
already effectively there.
@kentfredric
Copy link
Contributor

Given Perl developers now do use Pull Requests, maybe this should be resurrected.

@xenu
Copy link
Member

xenu commented Jun 21, 2020

I believe this was discussed here (alternative link).

It resulted in the following commits (from oldest to newest):

@syberrus
Copy link
Contributor Author

syberrus commented Jun 22, 2020 via email

atoomic added a commit that referenced this pull request Jun 29, 2020
gg_replace back perl7 perl7
toddr pushed a commit that referenced this pull request Jul 30, 2020
This requires a few small changes.

1. add a new option, which I stored in what looked like one of the
   standard ways
2. only store the item in terminal history if >= this length
3. only add to @hist if >= this length
4. only display hist item if >= this length

I believe #4 is redundant and should be removed, but the code was
already effectively there.
toddr added a commit to toddr/perl that referenced this pull request Sep 16, 2020
[DELTA]

1.854 16 September 2020

* Prefer direct notation over indirect (Perl#4)
* Make hint/BS snippets strict compliant.
* trim whitespace
atoomic pushed a commit that referenced this pull request Sep 16, 2020
[DELTA]

1.854 16 September 2020

* Prefer direct notation over indirect (#4)
* Make hint/BS snippets strict compliant.
* trim whitespace
khwilliamson pushed a commit to khwilliamson/perl5 that referenced this pull request Jan 30, 2023
export only necessary from POSIX (RT#99970)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants