0

0

Perl 停滞不前的日子:揭示 C 的隐藏力量

王林

王林

发布时间:2024-08-16 15:26:22

|

395人浏览过

|

来源于dev.to

转载

perl 停滞不前的日子:揭示 c 的隐藏力量

有时会发生意想不到的事情,必须与世界分享......这就是这样的情况。

最近,我开始尝试使用 perl 进行数据科学应用程序的工作流管理和低级代码的高级监督。在这种情况下,我为 perl 保留的一个角色是内存缓冲区的生命周期管理,使用 perl 应用程序“分配”内存缓冲区并在用 c、assembly、fortran 编写的计算组件和最好的隐藏宝石之间穿梭。 perl 世界,perl 数据语言。
perl 至少可以通过 3 种方式来分配内存缓冲区:

  1. 生成字节列表并使用 pack 函数将它们转换为字符串。
  2. 使用重复运算符 (x) 生成一个长度等于所需缓冲区大小减一的字符串(在 perl 中,字符串通过空字节终止,因此空字节补偿了我的一个 ).
  3. 通过 inline 或 ffi::platypus 访问外部内存分配器库来分配缓冲区。

以下 perl 代码实现了这三种方法(packstringc 中的 malloc),并允许尝试不同的缓冲区大小、初始值和结果精度(通过对分配的多次迭代进行平均)惯例)

#!/home/chrisarg/perl5/perlbrew/perls/current/bin/perl
use v5.38;
use inline (
    c         => 'data',
    cc        => 'g++',
    ld        => 'g++',
    inc       => q{},      # replace q{} with anything else you need
    ccflagsex => q{},      # replace q{} with anything else you need
    lddlflags => join(
        q{ },
        $config::config{lddlflags},
        q{ },              # replace q{ } with anything else you need
    ),
    libs => join(
        q{ },
        $config::config{libs},
        q{ },              # replace q{ } with anything else you need
    ),
    myextlib => ''
);

use benchmark qw(cmpthese);
use getopt::long;
my ($buffer_size, $init_value, $iterations);
getoptions(
    'buffer_size=i' => \$buffer_size,
    'init_value=s'  => \$init_value,
    'iterations=i'  => \$iterations,
) or die "usage: $0 --buffer_size  --init_value  --iterations \n";
my $init_value_byte = ord($init_value);
my %code_snippets   = (
    'string' => sub {
        $init_value x ( $buffer_size - 1 );
    },
    'pack' => sub {
        pack "c*", ( ($init_value_byte) x $buffer_size );
    },
    'c' => sub {
        allocate_and_initialize_array( $buffer_size, $init_value_byte );
    },
);

cmpthese( $iterations, \%code_snippets );

__data__

__c__

#include 
#include 
#include 

sv* allocate_and_initialize_array(size_t length, short initial_value) {
    // allocate memory for the array
    char* array = (char*)malloc(length * sizeof(char));
    char initial_value_byte = (char)initial_value;
    if (array == null) {
        fprintf(stderr, "memory allocation failed\n");
        exit(1);
    }

    // initialize each element with the initial_value
    memset(array, initial_value_byte, length);
    return newsvuv(ptr2uv(array));
}

将脚本调用为:

./time_mem_alloc.pl -buffer_size=1000000 -init_value=a -iterations=20000

产生了令人惊讶的结果:

笔启AI论文
笔启AI论文

专业高质量、低查重,免费论文大纲,在线AI生成原创论文,AI辅助生成论文的神器!

下载
          rate   pack      c string
pack     322/s     --   -92%   -99%
c       4008/s  1144%     --   -92%
string 50000/s 15417%  1147%     --

使用 perl string 方法比 c 的性能高出 10 倍

不相信巨大的性能提升,并认为我正在处理 inline::c 中的错误,我用纯 c 重新编码了分配(添加命令行处理/计时等的常用修饰):

#include 
#include 
#include 
#include 

char* allocate_and_initialize_array(size_t length, char initial_value) {
    // allocate memory for the array
    char* array = (char*)malloc(length * sizeof(char));
    if (array == null) {
        fprintf(stderr, "memory allocation failed\n");
        exit(1);
    }

    // initialize each element with the initial_value
    memset(array, initial_value, length);

    return array;
}

double time_allocation_and_initialization(size_t length, char initial_value) {
    clock_t start, end;
    double cpu_time_used;

    start = clock();
    char* array = allocate_and_initialize_array(length, initial_value);
    end = clock();

    cpu_time_used = ((double) (end - start)) / clocks_per_sec;
    /* this rudimentary loop prevents the compiler from optimizing out the 
     * allocation/initialization with the de-allocation
    */
    for(size_t i = 1; i < length; i++) {
       array[i]++;
       if(i % 100000 == 0) {
           printf("array[%zu] = %c\n", i, array[i]);
       }
    }
    free(array); // free the allocated memory

    return cpu_time_used;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "usage: %s  \n", argv[0]);
        return 1;
    }

    size_t length = strtoull(argv[1], null, 10);
    char initial_value = argv[2][0];

    double time_taken = time_allocation_and_initialization(length, initial_value);
    printf("time taken to allocate and initialize array: %f seconds\n", time_taken);
    printf("initializes per second: %f\n", 1/time_taken);

    return 0;
}

/*
compilation command:
gcc -o2 -o time_array_allocation time_array_allocation.c -std=c99

example invocation:
./time_array_allocation 10000000 a
*/

按照c代码中注释所说的那样调用c程序,
我得到了以下结果:

Time taken to allocate and initialize array: 0.000203 seconds
Initializes per second: 4926.108374

实际上执行的数量级与 inline::c malloc/c 方法的等效分配相同。
在进一步研究这个问题后,我发现我所欣赏的 malloc 牺牲了内存分配的速度以换取通用性,并且有大量更快的内存分配器。看来 perl 正在为其字符串使用这样一个分配器,并在分配缓冲区的任务中击败了 c。

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

85

2025.10.17

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

254

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

617

2023.11.24

Java 项目构建与依赖管理(Maven / Gradle)
Java 项目构建与依赖管理(Maven / Gradle)

本专题系统讲解 Java 项目构建与依赖管理的完整体系,重点覆盖 Maven 与 Gradle 的核心概念、项目生命周期、依赖冲突解决、多模块项目管理、构建加速与版本发布规范。通过真实项目结构示例,帮助学习者掌握 从零搭建、维护到发布 Java 工程的标准化流程,提升在实际团队开发中的工程能力与协作效率。

10

2026.01.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号