Skip to content

IV / NV upgrades often seem unnecessary and costly #17777

@richardleach

Description

@richardleach

Description
Many arithmetic or comparison operators change the SV type of their operands when the operands are of different type.

For example, when adding an IV and an NV, the NV will always be upgraded:

perl -MDevel::Peek -e '$nv = 1.33; Dump($nv); $res = 2 + $nv; Dump($res); Dump($nv);'
SV = NV(0x561243b9ee90) at 0x561243b9eea8
  REFCNT = 1
  FLAGS = (NOK,pNOK)
  NV = 1.33
SV = NV(0x561243b9ef38) at 0x561243b9ef50
  REFCNT = 1
  FLAGS = (NOK,pNOK)
  NV = 3.33
SV = PVNV(0x561243b6e040) at 0x561243b9eea8
  REFCNT = 1
  FLAGS = (NOK,pIOK,pNOK)
  IV = 1
  NV = 1.33
  PV = 0

When the operands are only SvIOK(sv) and SvNOK(sv) like this, it's not clear what the benefits are of changing the SV type, rather than just fetching the actual value and converting it within the op, and not altering the SV at all. (Conversion could be done either directly in the likes of the SvIV_nomg and SvNV_nomg macros, or by calling a new inline.h function from the likes of those macros.)

Changing the SV type comes with performance costs associated with:

  • allocating a different body type (if required) - this also uses additional memory and changes memory locality
  • updating the type/flags in the SV head
  • calling non-inline functions (e.g. S_sv_2iuv_common or Perl_sv_2iv_flags) in sv.c

The interpreter doesn't take account of how the SV is going to be used elsewhere, so:

  • a cascade of potentially-unnecessary SV upgrades could occur
  • the SV may repeatedly flip-flop between SvIOK(sv) and SvNOK(sv) - perhaps in different ops - triggering repeated calls to sv.c functions, updates to SV head flags, and probably still a I/UV <-> NV value conversion every time
  • the SV may immediately be destroyed, so the upgrade cost were incurred for naught

In comparison, while not upgrading an IV or NV that will repeatedly be used in the same one operation (e.g. as a constant) would also cause repeated value conversion, doing this inline should (hopefully) be much cheaper, especially with modern CPUs.

Questions

  1. Is there actually a very good reason - in core - for the current behaviour and it should be left as-is?
  2. Would changes likely cause much/any breakage on CPAN?
  3. If changes are viable, should new macros/functions be introduced or the existing ones modified?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Closable?We might be able to close this ticket, but we need to check with the reporterperformance

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions