Linux编程:测试-高效内存复制与随机数生成的性能

简介: 该文探讨了软件工程中的性能优化,重点关注内存复制和随机数生成。文章通过测试指出,`g_memmove`在内存复制中表现出显著优势,比简单for循环快约32倍。在随机数生成方面,`GRand`库在1000万次循环中的效率超过传统`rand()`。文中提供了测试代码和Makefile,建议在性能关键场景中使用`memcpy`、`g_memmove`以及高效的随机数生成库。

文章是我2011年写的,搬运过来。 顺便用大模型润色了一下。


引言

在软件工程领域,性能优化始终是一个热门话题,尤其是在内存操作和随机数生成方面。本文将通过一系列测试结果,对比不同方法在内存复制和随机数生成上的效率,重点突出memcpyg_memmove的优异表现。同时,我们将分享具体的测试代码和构建流程,帮助读者更好地理解和实践。

内存复制性能对比

在内存复制操作中,我们分别测试了字节级复制、4字节复制、8字节复制,以及使用g_memmove函数的性能。结果显示,g_memmove在10万次循环的测试中,仅耗时32.19ms,远低于其他逐字节或逐元素复制的方式。具体而言,g_memmove比简单的for循环快约32倍,这得益于其内部优化的内存复制算法。

随机数生成效率分析

在随机数生成方面,我们对比了三种方法:传统rand()函数、简化的rand()使用方式,以及使用GRand库的随机数生成。测试表明,虽然rand()和其简化版本的性能相当,但GRand库提供的随机数生成在1000万次循环中表现出了更高的效率,平均每次循环耗时仅61.44ns,这体现了高级随机数生成库的优化效果。

测试代码与构建流程

以下为用于性能测试的源代码及Makefile配置,便于读者复现实验结果。

C

#include <gtk/gtk.h>
#include <glib.h>
#include <stdlib.h>

#define MAX_SIZE       1024

void Comput_Print_Result(gchar *str, guint loops, GTimeVal tStart);

int main(int argc, char **argv)
{
    guchar buf111[MAX_SIZE];
    guchar buf222[MAX_SIZE];
    GTimeVal tstart;
    guint i, j;
    guint testTimes = 100000;

    // 初始化数据
    for(i = 0; i < MAX_SIZE; i++)
    {
        buf111[i] = 1;
        buf222[i] = 2;
    }

    // 开始测试:1字节复制
    g_get_current_time(&tstart);
    for(j = 0; j < testTimes; j++)
        for(i = 0; i < MAX_SIZE; i++)
            buf111[i] = buf222[i];
    Comput_Print_Result("1byte copy    ", testTimes, tstart);

    // 更多测试代码...

    // 结束测试:内存复制验证
    for(i = 0; i < MAX_SIZE; i++)
        if(buf111[i] != buf222[i])
            g_print("mem copy failed\n");

    // 随机数生成测试代码...
    
    return 0;
}

void Comput_Print_Result(gchar *str, guint loops, GTimeVal tStart)
{
    GTimeVal tEnd;
    g_get_current_time(&tEnd);
    gfloat time_msec = (1000000.00 * (tEnd.tv_sec - tStart.tv_sec) + tEnd.tv_usec - tStart.tv_usec) / 1000;
    gfloat time_each = time_msec / loops * 1000000;
    g_print("Time %s: %.2fms used for %d loops. Each loop %.2fns\n", str, time_msec, loops, time_each);
}

Makefile配置如下:

Makefile

CC=gcc
PROG_NAME=PerformanceTest
INCS=
SRCS=PerformanceTest.c
OBJS=${SRCS:.c=.o}
LIBS=gtk+-2.0

CFLAGS=`pkg-config --cflags ${LIBS}` -g -Wall
LDFLAGS=`pkg-config --libs ${LIBS}` -g -Wall

all: ${PROG_NAME}

${PROG_NAME}:${OBJS}
    ${CC} -o ${PROG_NAME} ${OBJS} ${LDFLAGS}

${OBJS}:${INCS}

.c.o:
    ${CC} -c $< ${CFLAGS}

clean:
    rm -f *.o ${PROG_NAME}

rebuild: clean all

结论

通过上述测试,我们得出结论:当涉及大量内存复制时,g_memmove应作为首选,因为它在性能上明显优于传统的for循环复制方法。同样,在随机数生成场景下,使用GRand库可以带来更好的效率。这些发现强调了选择合适工具的重要性,尤其是在追求高性能的应用场景中。

推荐实践

  • 对于频繁的内存复制操作,考虑使用memcpyg_memmove,它们经过优化,能显著提高复制速度。
  • 当需要生成大量随机数时,评估并选择性能最优的随机数生成库,如GRand,以减少计算延迟。
  • 在编写性能敏感的代码时,进行基准测试是必要的,以确保选择的方法达到预期的性能目标。

通过本文的测试和分析,我们不仅验证了memcpyg_memmove在内存复制上的高效性,也展示了如何通过适当的工具和方法优化随机数生成的性能。希望这些发现能为你的项目带来实质性的性能提升

相关文章
|
7月前
|
存储 缓存 Java
【高薪程序员必看】万字长文拆解Java并发编程!(5):深入理解JMM:Java内存模型的三大特性与volatile底层原理
JMM,Java Memory Model,Java内存模型,定义了主内存,工作内存,确保Java在不同平台上的正确运行主内存Main Memory:所有线程共享的内存区域,所有的变量都存储在主存中工作内存Working Memory:每个线程拥有自己的工作内存,用于保存变量的副本.线程执行过程中先将主内存中的变量读到工作内存中,对变量进行操作之后再将变量写入主内存,jvm概念说明主内存所有线程共享的内存区域,存储原始变量(堆内存中的对象实例和静态变量)工作内存。
254 0
|
3月前
|
测试技术 UED 开发者
性能测试报告-用于项目的性能验证、性能调优、发现性能缺陷等应用场景
性能测试报告用于评估系统性能、稳定性和安全性,涵盖测试环境、方法、指标分析及缺陷优化建议,是保障软件质量与用户体验的关键文档。
|
7月前
|
安全 算法 Ubuntu
Linux(openssl)环境:编程控制让证书自签的技巧。
总结:在Linux环境中,OpenSSL是一个非常实用的工具,可以帮助我们轻松地生成自签名证书。通过上述三个简单步骤,即可为内部网络、测试环境或开发环境创建自签名证书。但在公共访问场景下,建议购买经过权威认证机构签发的证书,以避免安全警告。
349 13
|
9月前
|
JavaScript Ubuntu Linux
如何在阿里云的linux上搭建Node.js编程环境?
本指南介绍如何在阿里云Linux服务器(Ubuntu/CentOS)上搭建Node.js环境,包含两种安装方式:包管理器快速安装和NVM多版本管理。同时覆盖全局npm工具配置、应用部署示例(如Express服务)、PM2持久化运行、阿里云安全组设置及外部访问验证等步骤,助你完成开发与生产环境的搭建。
|
10月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
213 26
|
10月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
214 17
|
算法 Java 测试技术
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
319 13
|
开发框架 .NET Java
C#集合数据去重的5种方式及其性能对比测试分析
C#集合数据去重的5种方式及其性能对比测试分析
183 11
|
开发框架 .NET Java
C#集合数据去重的5种方式及其性能对比测试分析
C#集合数据去重的5种方式及其性能对比测试分析
225 10
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
556 13