微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

标量如何存储在“引擎盖”下的perl?

perl中的基本类型与大多数语言不同,类型为标量,数组,哈希(但显然不是子例程,而我认为其实只是使用语法糖的标量引用).最奇怪的是,最常见的数据类型是int,boolean,char,string,都属于基本数据类型“ scalar”.似乎perl决定将标量视为基于修饰它的运算符的字符串,布尔值或数字,这意味着标量本身在保存时实际上并不被定义为“int”或“String”.

这使我很好奇这些标量如何存储在“引擎盖”下,特别是在效率方面存在(是的,我知道脚本语言牺牲了灵活性的效率,但是当灵活性问题仍然需要时,它们仍然需要尽可能优化)不受影响).存储65535(这需要两个字节),然后是字符串“65535”,这需要6个字节,因为这样识别$val = 65535存储一个int将允许我使用1/3的内存容易得多,在大阵列中,这也意味着更少的缓存命中.

当然不仅限于节省内存.有时我可以提供更多的优化,如果我知道什么类型的标量期望.例如,如果我使用非常大的整数作为键的哈希值,如果我将密钥识别为int,则可以更快地查找一个值,允许简单的模式来创建我的哈希密钥,那么如果我必须运行更复杂的哈希一个字符串的逻辑,具有3倍的字节.

所以我想知道perl如何处理这些标尺.它是否将每个值作为字符串存储,在标量始终用作int的情况下,牺牲额外的内存和cpu常量将字符串转换为int的代价?还是有一些逻辑推理用于确定如何保存和操作的标量类型?

编辑:

TJD链接到perlguts,这回答了我的一半问题.标量实际上存储为字符串,int(signed,unsigned,double)或指针.我不是太惊讶,我主要是希望这种行为发生在引擎盖下,虽然看到确切的类型很有趣.我打开这个问题,因为perlgut实际上是低水平的.其他的告诉我有5种数据类型存在,它没有指定perl如何在它们之间进行交替,即如何在保存标量时如何决定使用哪种SV类型,以及如何知道何时/如何转换.

解决方法

实际上有许多类型的标量. SVt_IV类型的标量可以保存undef,有符号整数(IV)或无符号整数(UV). SVT_PVIV类型之一也可以保存一个字符串.标尺根据需要从一种类型静升级到另一种类型[1]. TYPE字段指示标量的类型.实际上,数组(SVt_AV)和散列(SVt_HV)实际上只是标量的类型.

虽然标量的类型表示标量可以包含什么,但标志用于指示标量所包含的内容.这被存储在FLAGS字段中. SVf_IOK表示标量包含有符号整数,而SVf_POK表示它包含一个字符串[2].

Devel::Peek的转储是查看标量内部的好工具. (Dump省略了常量前缀SVt_和SVf_)

$perl -e'
   use Devel::Peek qw( Dump );
   my $x = 123;
   Dump($x);
   $x = "456";
   Dump($x);
   $x + 0;
   Dump($x);
'
SV = IV(0x25f0d20) at 0x25f0d30       <-- SvTYPE(sv) == SVt_IV,so it can contain an IV.
  REFCNT = 1
  FLAGS = (IOK,pIOK)                  <-- IOK: Contains an IV.
  IV = 123                            <-- The contained signed integer (IV).

SV = PVIV(0x25f5ce0) at 0x25f0d30     <-- The SV has been upgraded to SVt_PVIV
  REFCNT = 1                              so it can also contain a string Now.
  FLAGS = (POK,IsCOW,pPOK)            <-- POK: Contains a string (but no IV since !IOK).
  IV = 123                            <-- Meaningless without IOK.
  PV = 0x25f9310 "456"\0              <-- The contained string.
  CUR = 3                             <-- Number of bytes used by PV (not incl \0).
  LEN = 10                            <-- Number of bytes allocated for PV.
  COW_REFCNT = 1

SV = PVIV(0x25f5ce0) at 0x25f0d30
  REFCNT = 1
  FLAGS = (IOK,POK,pIOK,pPOK)   <-- Now contains both a string (POK) and an IV (IOK).
  IV = 456                            <-- This will be used in numerical contexts.
  PV = 0x25f9310 "456"\0              <-- This will be used in string contexts.
  CUR = 3
  LEN = 10
  COW_REFCNT = 1

illguts文件内容变量的格式相当彻底,但perlguts可能是一个更好的起点.

如果您开始编写XS代码,请记住,检查标量包含通常是一个坏主意.相反,您应该请求应提供的内容(例如使用SvIV或SvPVutf8). Perl将自动将该值转换为请求的类型(如果适用,则警告). API调用记录在perlapi.

>所有标量(包括数组和散列,不包括只能容纳undef的标量类型)在其基础上有两个内存块.指向标量的指针指向其头部,其中包含TYPE字段和指向身体的指针.升级标量代替标量的正文.这样,升级的指针不会被无效.> undef变量是没有任何大写OK标志的变量.

原文地址:https://www.jb51.cc/Perl/172325.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐