99精品伊人亚洲|最近国产中文炮友|九草在线视频支援|AV网站大全最新|美女黄片免费观看|国产精品资源视频|精彩无码视频一区|91大神在线后入|伊人终合在线播放|久草综合久久中文

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【性能優(yōu)化】memcpy函數(shù)有沒有更高效的拷貝實(shí)現(xiàn)方法?

嵌入式物聯(lián)網(wǎng)開發(fā) ? 來(lái)源:嵌入式物聯(lián)網(wǎng)開發(fā) ? 作者:嵌入式物聯(lián)網(wǎng)開發(fā) ? 2022-12-07 08:59 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

C語(yǔ)言經(jīng)典面試題】memcpy函數(shù)有沒有更高效的拷貝實(shí)現(xiàn)方法?

我相信大部分初中級(jí)C程序員在面試的過(guò)程中,可能都被問(wèn)過(guò)關(guān)于memcpy函數(shù)的問(wèn)題,甚至需要手撕memcpy。本文從另一個(gè)角度帶你領(lǐng)悟一下memcpy的面試題,你可以看看是否能接得???

1 寫在前面2 源碼實(shí)現(xiàn)2.1 函數(shù)申明2.2 簡(jiǎn)單的功能實(shí)現(xiàn)2.3 滿足大數(shù)據(jù)量拷貝的功能實(shí)現(xiàn)3 源碼測(cè)試4 小小總結(jié)5 更多分享

1 寫在前面

假如你遇到下面的面試題,你會(huì)怎么做?題目大意如下:

請(qǐng)參考標(biāo)準(zhǔn)C庫(kù)對(duì)memcpy的申明定義,使用C語(yǔ)言的語(yǔ)法實(shí)現(xiàn)其基本功能,并盡量保證它在拷貝大數(shù)據(jù)(KK級(jí)別)的時(shí)候,有比較好的性能表現(xiàn)。

2 源碼實(shí)現(xiàn)

2.1 函數(shù)申明

通過(guò)查看man幫助,我們可以知道m(xù)emcpy函數(shù)的功能及其簡(jiǎn)要申明。

NAME
        memcpy - copy memory area
 ?
 SYNOPSIS
        #include

英文翻譯過(guò)來(lái)就是說(shuō),memcpy實(shí)現(xiàn)的就是內(nèi)存拷貝,其是按字節(jié)進(jìn)行拷貝,同時(shí)還可能會(huì)存在內(nèi)存區(qū)域重合的情況。

2.2 簡(jiǎn)單的功能實(shí)現(xiàn)

根據(jù)功能需求,以下是我的一個(gè)簡(jiǎn)單實(shí)現(xiàn)源碼,僅供參考:

char *my_memcpy(char* dest, const char *src, size_t len)
 {
     assert(dest && src && (len > 0));
 
 if (dest == src) {
 ;
 } else {
         char *p = dest;
 size_t i;
         for (i = 0; i < len; i++) {
             *p++ = *src++;
 }
     } 
 ?
     return dest;
 }

但是,這段代碼的缺陷也比較明顯,但數(shù)據(jù)量過(guò)大的時(shí),即len很大時(shí),整一個(gè)拷貝耗時(shí)將會(huì)非常不理想。那么如果考慮性能問(wèn)題,又該如何實(shí)現(xiàn)它呢?

2.3 滿足大數(shù)據(jù)量拷貝的功能實(shí)現(xiàn)

下面給出一個(gè)參考實(shí)現(xiàn):

/* Nonzero if either X or Y is not aligned on a "long" boundary.  */
 #define UNALIGNED(X, Y) \\
 (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1)))
 ?
 /* How many bytes are copied each iteration of the 4X unrolled loop.  */
 #define BIGBLOCKSIZE    (sizeof(long) << 2)
 ?
 /* How many bytes are copied each iteration of the word copy loop.  */
 #define LITTLEBLOCKSIZE (sizeof(long))
 ?
 /* Threshhold for punting to the byte copier.  */
 #define TOO_SMALL(LEN)  ((LEN) < BIGBLOCKSIZE)
 ?
 char *my_memcopy_super(char* dest0, const char *src0, size_t len0)
 {
     assert(dest0 && src0 && (len0 > 0));
 
 char *dest = dest0;
 const char *src = src0;
 long *aligned_dest;
 const long *aligned_src;
 ?
 /* If the size is small, or either SRC or DST is unaligned,
    then punt into the byte copy loop.  This should be rare.  */
 if (!TOO_SMALL(len0) && !UNALIGNED(src, dest)) {
 aligned_dest = (long *)dest;
 aligned_src = (long *)src;
 ?
 /* Copy 4X long words at a time if possible.  */
 while (len0 >= BIGBLOCKSIZE) {
 *aligned_dest++ = *aligned_src++;
 *aligned_dest++ = *aligned_src++;
 *aligned_dest++ = *aligned_src++;
 *aligned_dest++ = *aligned_src++;
 len0 -= BIGBLOCKSIZE;
 }
 ?
 /* Copy one long word at a time if possible.  */
 while (len0 >= LITTLEBLOCKSIZE) {
 *aligned_dest++ = *aligned_src++;
 len0 -= LITTLEBLOCKSIZE;
 }
 ?
 /* Pick up any residual with a byte copier.  */
 dest = (char *)aligned_dest;
 src = (char *)aligned_src;
 }
 ?
 while (len0--)
 *dest++ = *src++;
 ?
 return dest0;
 }
 ?

我們可以看到,里面做了對(duì)齊的判斷,還有數(shù)據(jù)量長(zhǎng)度的判斷;通過(guò)充分利用機(jī)器的操作性能,從而提升memcpy拷貝的效率。

3 源碼測(cè)試

**簡(jiǎn)單的測(cè)試代碼如下,目的就是測(cè)試在拷貝 **1KB數(shù)據(jù)和10MB數(shù)據(jù) 時(shí),標(biāo)準(zhǔn)C的memcpy、自定義的memcpy_normal、以及自定義的memcpy_super直接的性能差異:

#include 
 #include 
 ?
 static void get_rand_bytes(unsigned char *data, int len)
 {
     int a;
     int i;
 ?
     srand((unsigned)time(NULL)); //種下隨機(jī)種子
     for (i = 0; i < len; i++) {
         data[i] = rand() % 255; //取隨機(jī)數(shù),并保證數(shù)在0-255之間
         //printf("%02X ", data[i]);
     }  
 }
 ?
 static int get_cur_time_us(void)
 {
     struct timeval tv;
 ?
     gettimeofday(&tv, NULL);  //使用gettimeofday獲取當(dāng)前系統(tǒng)時(shí)間
 ?
     return (tv.tv_sec * 1000 * 1000 + tv.tv_usec); //利用struct timeval結(jié)構(gòu)體將時(shí)間轉(zhuǎn)換為ms
 }
 ?
 #define ARRAY_SIZE(n)  sizeof(n) / sizeof(n[0])
 ?
 int main(void)
 {
 int size_list[] = {
 1024 * 1024 * 10,  // 10MB
 1024 * 1024 * 1,  // 1MB
 1024 * 100, // 100KB
 1024 * 10, // 10KB
 1024 * 1, // 1KB
 };
     char *data1;
     char *data2;
     int t1;
     int t2;
     int i = 0;
 ?
     data1 = (char *)malloc(size_list[0]);
     data2 = (char *)malloc(size_list[0]);
 ?
     get_rand_bytes(data1, size_list[0]);
 ?
     for (i = 0; i < ARRAY_SIZE(size_list); i++) {
     t1 = get_cur_time_us();
     memcpy(data2, data1, size_list[i]);
     t2 = get_cur_time_us();
     printf("copy %d bytes, memcpy_stdc   waste time %dus\\n", size_list[i], t2 - t1);
 ?
     t1 = get_cur_time_us();
     my_memcopy_normal(data2, data1, size_list[i]);
     t2 = get_cur_time_us();
     printf("copy %d bytes, memcpy_normal waste time %dus\\n", size_list[i], t2 - t1);
 ?
     t1 = get_cur_time_us();
     my_memcopy_super(data2, data1, size_list[i]);
     t2 = get_cur_time_us();
     printf("copy %d bytes, memcpy_super  waste time %dus\\n\\n", size_list[i], t2 - t1);
     }
 ?
     free(data1);
     free(data2);
 ?
 return 0;
 }
 ?

簡(jiǎn)單執(zhí)行編譯后,運(yùn)行小程序的結(jié)果:

image-20221205135556210

從運(yùn)行結(jié)果上看:

  • **拷貝數(shù)據(jù)量比較小時(shí),拷貝效率排行: **normal < super < stdc
  • **拷貝數(shù)據(jù)量比較大時(shí),拷貝效率排行: **normal < stdc < super

4 小小總結(jié)

memcpy的源碼實(shí)現(xiàn),核心就是內(nèi)存拷貝,要想提升拷貝的效率,還得充分利用機(jī)器的運(yùn)算性能,比如考慮對(duì)齊問(wèn)題。

綜合來(lái)看,標(biāo)準(zhǔn)C庫(kù)實(shí)現(xiàn)的memcpy在大部分的場(chǎng)景下都可以有一個(gè)比較好的性能表現(xiàn),這一點(diǎn)是值得稱贊的。

5 更多分享

[架構(gòu)師李肯]

架構(gòu)師李肯全網(wǎng)同名 ),一個(gè)專注于嵌入式IoT領(lǐng)域的架構(gòu)師。有著近10年的嵌入式一線開發(fā)經(jīng)驗(yàn),深耕IoT領(lǐng)域多年,熟知IoT領(lǐng)域的業(yè)務(wù)發(fā)展,深度掌握IoT領(lǐng)域的相關(guān)技術(shù)棧,包括但不限于主流RTOS內(nèi)核的實(shí)現(xiàn)及其移植、硬件驅(qū)動(dòng)移植開發(fā)、網(wǎng)絡(luò)通訊協(xié)議開發(fā)、編譯構(gòu)建原理及其實(shí)現(xiàn)、底層匯編及編譯原理、編譯優(yōu)化及代碼重構(gòu)、主流IoT云平臺(tái)的對(duì)接、嵌入式IoT系統(tǒng)的架構(gòu)設(shè)計(jì)等等。擁有多項(xiàng)IoT領(lǐng)域的發(fā)明專利,熱衷于技術(shù)分享,有多年撰寫技術(shù)博客的經(jīng)驗(yàn)積累,連續(xù)多月獲得RT-Thread官方技術(shù)社區(qū)原創(chuàng)技術(shù)博文優(yōu)秀獎(jiǎng),榮獲[CSDN博客專家]、[CSDN物聯(lián)網(wǎng)領(lǐng)域優(yōu)質(zhì)創(chuàng)作者]、[2021年度CSDN&RT-Thread技術(shù)社區(qū)之星]、[2022年RT-Thread全球技術(shù)大會(huì)講師]、[RT-Thread官方嵌入式開源社區(qū)認(rèn)證專家]、[RT-Thread 2021年度論壇之星TOP4]、[華為云云享專家(嵌入式物聯(lián)網(wǎng)架構(gòu)設(shè)計(jì)師)]等榮譽(yù)。堅(jiān)信【知識(shí)改變命運(yùn),技術(shù)改變世界】!

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4381

    瀏覽量

    64898
  • RT-Thread
    +關(guān)注

    關(guān)注

    32

    文章

    1409

    瀏覽量

    41962
  • memcpy
    +關(guān)注

    關(guān)注

    0

    文章

    9

    瀏覽量

    2930
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    【C語(yǔ)言經(jīng)典面試題】源碼實(shí)現(xiàn)標(biāo)準(zhǔn)庫(kù)函數(shù)memcpy

    你有面試中,要求寫memcpy的源碼實(shí)現(xiàn)嗎?本文給出一個(gè)參考寫法!
    的頭像 發(fā)表于 09-30 17:12 ?4670次閱讀

    高效率的內(nèi)存拷貝函數(shù)memcpy

    memcpy是memory copy的縮寫,意為內(nèi)存復(fù)制,在寫C語(yǔ)言程序的時(shí)候,我們常常會(huì)用到它。
    發(fā)表于 11-08 09:48 ?9070次閱讀

    HBase性能優(yōu)化方法總結(jié)

    讀密集型對(duì)于隨機(jī)讀密集型工作負(fù)載,高效利用緩存和更好地索引會(huì)給HBase系統(tǒng)帶來(lái)更高性能2. 順序讀密集型對(duì)于順序讀密集型工作負(fù)載,可以采用不使用緩存的方式減少硬盤訪問(wèn)次數(shù)來(lái)提高性能
    發(fā)表于 04-20 17:16

    MSP430FRx MCU如何實(shí)現(xiàn)更高性能

    MSP MCU 的 MSP-IQMATHLIB 優(yōu)化型軟件庫(kù)可通過(guò)提供優(yōu)化型定點(diǎn)函數(shù)(包括加法、乘法、正弦和對(duì)數(shù))來(lái)幫助您縮短產(chǎn)品上市時(shí)間。 相較于采用標(biāo)準(zhǔn) math.h 頭文件,這些函數(shù)
    發(fā)表于 09-10 11:57

    memCopy函數(shù)怎么實(shí)現(xiàn)拷貝的呢?

    memCopy函數(shù)是將指定地址的代碼拷貝到目的地址,一般情況下是把flash的代碼拷貝到ram內(nèi)運(yùn)行,問(wèn)題是:在flash啟動(dòng)模式的情況下調(diào)用memcopy之前沒有初始化flash的等
    發(fā)表于 05-12 08:39

    STM32中的memcpy函數(shù)的使用 精選資料推薦

    定義是什么memcpy 函數(shù)用于 把資源內(nèi)存(src所指向的內(nèi)存區(qū)域) 拷貝到目標(biāo)內(nèi)存(dest所指向的內(nèi)存區(qū)域);拷貝多少個(gè)?有一個(gè)size變量控制
    發(fā)表于 08-24 08:11

    memcpy怎么用_memcpy用法總結(jié)

    memcpy指的是c和c++使用的內(nèi)存拷貝函數(shù)memcpy函數(shù)的功能是從源src所指的內(nèi)存地址的起始位置開始
    發(fā)表于 11-28 15:56 ?4.7w次閱讀
    <b class='flag-5'>memcpy</b>怎么用_<b class='flag-5'>memcpy</b>用法總結(jié)

    淺談linux c編程中的拷貝函數(shù)

    strcpy: 最常用的字符串拷貝函數(shù),但是要注意這個(gè)函數(shù)不會(huì)自己判斷源字符串是否比目標(biāo)空間大,必須要程序員自己檢查,否則很容易造成拷貝越界。
    發(fā)表于 05-31 01:46 ?2356次閱讀

    C++:詳談拷貝構(gòu)造函數(shù)

    只有單個(gè)形參,而且該形參是對(duì)本類類型對(duì)象的引用(常用const修飾),這樣的構(gòu)造函數(shù)稱為拷貝構(gòu)造函數(shù)。拷貝構(gòu)造函數(shù)是特殊的構(gòu)造
    的頭像 發(fā)表于 06-29 11:45 ?2317次閱讀
    C++:詳談<b class='flag-5'>拷貝</b>構(gòu)造<b class='flag-5'>函數(shù)</b>

    C語(yǔ)言模擬實(shí)現(xiàn)memcpy函數(shù)

    memcpy指的是c和c++使用的內(nèi)存拷貝函數(shù),memcpy函數(shù)的功能是從源src所指的內(nèi)存地址的起始位置開始
    的頭像 發(fā)表于 06-29 17:29 ?2674次閱讀
    C語(yǔ)言模擬<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>memcpy</b><b class='flag-5'>函數(shù)</b>

    C語(yǔ)言模擬實(shí)現(xiàn)memmove函數(shù)

    memmove用于從src拷貝count個(gè)字節(jié)到dest,如果目標(biāo)區(qū)域和源區(qū)域有重疊的話,memmove能夠保證源串在被覆蓋之前將重疊區(qū)域的字節(jié)拷貝到目標(biāo)區(qū)域中。但復(fù)制后src內(nèi)容會(huì)被更改。但是當(dāng)目標(biāo)區(qū)域與源區(qū)域沒有重疊則和
    的頭像 發(fā)表于 06-29 17:53 ?1903次閱讀
    C語(yǔ)言模擬<b class='flag-5'>實(shí)現(xiàn)</b>memmove<b class='flag-5'>函數(shù)</b>

    memcpy函數(shù)實(shí)現(xiàn)及其優(yōu)化

    函數(shù)原型void * memcpy ( void * destination, const void * source, size_t num );
    發(fā)表于 12-09 14:25 ?2928次閱讀

    C++之拷貝構(gòu)造函數(shù)的淺copy及深copy

    C++編譯器會(huì)默認(rèn)提供構(gòu)造函數(shù);無(wú)參構(gòu)造函數(shù)用于定義對(duì)象的默認(rèn)初始化狀態(tài);拷貝構(gòu)造函數(shù)在創(chuàng)建對(duì)象時(shí)拷貝對(duì)象的狀態(tài);對(duì)象的
    的頭像 發(fā)表于 12-24 15:31 ?1004次閱讀

    C語(yǔ)言庫(kù)memcpy和memmove的區(qū)別分析

    memcpy和memmove都是 C 語(yǔ)言的庫(kù)函數(shù),相比于 strcpy和 strncpy只能針對(duì)于字符類型的數(shù)組(),這兩個(gè)函數(shù)可以拷貝其他類型的數(shù)組,對(duì)于
    發(fā)表于 09-19 12:19 ?2373次閱讀

    memcpy和memmove的區(qū)別是什么

    `memcpy`和`memmove`都是 C語(yǔ)言的庫(kù)函數(shù),相比于 `strcpy`和 `strncpy`只能針對(duì)于字符類型的數(shù)組(),這兩個(gè)函數(shù)可以拷貝其他類型的數(shù)組,對(duì)于 `
    的頭像 發(fā)表于 01-20 16:55 ?3068次閱讀
    <b class='flag-5'>memcpy</b>和memmove的區(qū)別是什么