std::copy性能分析与memmove机器级实现
复制数据的快速方法std::copy
C++复制数据各种方法大家都会,很多时候我们都会用到std::copy这个STL函数,这个效率确实很不错,比我们一个一个元素复制或者用迭代器复制都来的要快很多。
const int size = ;
int *k = new int[size];
int *p = new int[size];
//const int size = 5F5E100h; DWORD t1, t2; t1 = GetTickCount();
for (int i = ; i != size; i++)
p[i] = k[i];
t2 = GetTickCount();
cout << t2 - t1 << "ms" << std::endl; t1 = GetTickCount();
int *pStart = k, *pEnd = k + size, *pDest = p;
for (; pStart != pEnd; pDest++, pStart++)
*pDest = *pStart;
t2 = GetTickCount();
cout << t2 - t1 << "ms" << std::endl; t1 = GetTickCount();
std::copy(k, k + size, p);
t2 = GetTickCount();
cout << t2 - t1 << "ms" << std::endl;

for (int i = ; i != size; i++)
00F0A8B1 mov dword ptr [ebp-54h],
00F0A8B8 jmp main+0A3h (0F0A8C3h)
00F0A8BA mov eax,dword ptr [ebp-54h]
00F0A8BD add eax,
00F0A8C0 mov dword ptr [ebp-54h],eax
00F0A8C3 cmp dword ptr [ebp-54h],5F5E100h
00F0A8CA je main+0C0h (0F0A8E0h)
p[i] = k[i];
00F0A8CC mov eax,dword ptr [ebp-54h]
00F0A8CF mov ecx,dword ptr [p]
00F0A8D2 mov edx,dword ptr [ebp-54h]
00F0A8D5 mov esi,dword ptr [k]
00F0A8D8 mov edx,dword ptr [esi+edx*]
00F0A8DB mov dword ptr [ecx+eax*],edx
00F0A8DE jmp main+9Ah (0F0A8BAh)
int *pStart = k, *pEnd = k + size, *pDest = p;
00F0A944 mov eax,dword ptr [k]
00F0A947 mov dword ptr [pStart],eax
00F0A94A mov eax,dword ptr [k]
00F0A94D add eax,17D78400h
00F0A952 mov dword ptr [pEnd],eax
00F0A955 mov eax,dword ptr [p]
00F0A958 mov dword ptr [pDest],eax
for (; pStart != pEnd; pDest++, pStart++)
00F0A95B jmp main+14Fh (0F0A96Fh)
00F0A95D mov eax,dword ptr [pDest]
00F0A960 add eax,
00F0A963 mov dword ptr [pDest],eax
00F0A966 mov ecx,dword ptr [pStart]
00F0A969 add ecx,
00F0A96C mov dword ptr [pStart],ecx
00F0A96F mov eax,dword ptr [pStart]
00F0A972 cmp eax,dword ptr [pEnd]
00F0A975 je main+163h (0F0A983h)
*pDest = *pStart;
00F0A977 mov eax,dword ptr [pDest]
00F0A97A mov ecx,dword ptr [pStart]
00F0A97D mov edx,dword ptr [ecx]
00F0A97F mov dword ptr [eax],edx
00F0A981 jmp main+13Dh (0F0A95Dh)
template<class _InIt,
class _OutIt> inline
_OutIt _Copy_memmove(_InIt _First, _InIt _Last,
_OutIt _Dest)
{ // implement copy-like function as memmove
const char * const _First_ch = reinterpret_cast<const char *>(_First);
const char * const _Last_ch = reinterpret_cast<const char *>(_Last);
char * const _Dest_ch = reinterpret_cast<char *>(_Dest);
const size_t _Count = _Last_ch - _First_ch;
_CSTD memmove(_Dest_ch, _First_ch, _Count);
return (reinterpret_cast<_OutIt>(_Dest_ch + _Count));
}
template<class _InIt,
class _OutIt> inline
_OutIt _Copy_unchecked1(_InIt _First, _InIt _Last,
_OutIt _Dest, _General_ptr_iterator_tag)
{ // copy [_First, _Last) to [_Dest, ...), arbitrary iterators
for (; _First != _Last; ++_Dest, (void)++_First)
*_Dest = *_First;
return (_Dest);
}
template<class _InIt,
class _OutIt> inline
_OutIt _Copy_unchecked1(_InIt _First, _InIt _Last,
_OutIt _Dest, _Trivially_copyable_ptr_iterator_tag)
{ // copy [_First, _Last) to [_Dest, ...), pointers to trivially copyable
return (_Copy_memmove(_First, _Last, _Dest));
}
template<class _InIt,
class _OutIt> inline
_OutIt _Copy_unchecked(_InIt _First, _InIt _Last,
_OutIt _Dest)
{ // copy [_First, _Last) to [_Dest, ...)
// note: _Copy_unchecked is called directly elsewhere in the STL
return (_Copy_unchecked1(_First, _Last,
_Dest, _Ptr_copy_cat(_First, _Dest)));
}
template<class _InIt,
class _OutIt> inline
_OutIt _Copy_no_deprecate1(_InIt _First, _InIt _Last,
_OutIt _Dest, input_iterator_tag, _Any_tag)
{ // copy [_First, _Last) to [_Dest, ...), arbitrary iterators
return (_Rechecked(_Dest,
_Copy_unchecked(_First, _Last, _Unchecked_idl0(_Dest))));
}
template<class _InIt,
class _OutIt> inline
_OutIt _Copy_no_deprecate1(_InIt _First, _InIt _Last,
_OutIt _Dest, random_access_iterator_tag, random_access_iterator_tag)
{ // copy [_First, _Last) to [_Dest, ...), random-access iterators
_CHECK_RANIT_RANGE(_First, _Last, _Dest);
return (_Rechecked(_Dest,
_Copy_unchecked(_First, _Last, _Unchecked(_Dest))));
}
template<class _InIt,
class _OutIt> inline
_OutIt _Copy_no_deprecate(_InIt _First, _InIt _Last,
_OutIt _Dest)
{ // copy [_First, _Last) to [_Dest, ...), no _SCL_INSECURE_DEPRECATE_FN warnings
_DEBUG_RANGE_PTR(_First, _Last, _Dest);
return (_Copy_no_deprecate1(_Unchecked(_First), _Unchecked(_Last),
_Dest, _Iter_cat_t<_InIt>(), _Iter_cat_t<_OutIt>()));
}
template<class _InIt,
class _OutIt> inline
_OutIt copy(_InIt _First, _InIt _Last,
_OutIt _Dest)
{ // copy [_First, _Last) to [_Dest, ...)
_DEPRECATE_UNCHECKED(copy, _Dest);
return (_Copy_no_deprecate(_First, _Last, _Dest));
}
return (_Copy_no_deprecate1(_Unchecked(_First), _Unchecked(_Last),
_Dest, _Iter_cat_t<_InIt>(), _Iter_cat_t<_OutIt>()));
template<class _Iter>
using _Iter_cat_t = typename iterator_traits<_Iter>::iterator_category;
input_iterator_tag //输入迭代器,单向一次一步移动,读取一次
output_iterator_tag //输出迭代器,单向一次一步移动,涂写一次
forward_iterator_tag //向前迭代器,单向一次一步移动,多次读写,继承自输入迭代器
bidirectional_iterator_tag //双向迭代器,双向一次一步移动,多次读写,继承自向前迭代器
random_access_iterator_tag //随机迭代器,任意位置多次读写,继承自双向迭代器
template<class _Source,
class _Dest> inline
_General_ptr_iterator_tag _Ptr_copy_cat(const _Source&, const _Dest&)
{ // return pointer copy optimization category for arbitrary iterators
return {};
}
template<class _Source,
class _Dest> inline
conditional_t<is_trivially_assignable<_Dest&, _Source&>::value,
typename _Ptr_cat_helper<remove_const_t<_Source>, _Dest>::type,
_General_ptr_iterator_tag>
_Ptr_copy_cat(_Source * const&, _Dest * const&)
{ // return pointer copy optimization category for pointers
return {};
}
_CSTD memmove(_Dest_ch, _First_ch, _Count);
当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
当源内存的首地址大于目标内存的首地址时,实行正向拷贝
当源内存的首地址小于目标内存的首地址时,实行反向拷贝
这三个指令每一次执行都会将源地址到目的地址的数据的复制
目标地址由di决定(对于movsb,movsw是di,movsd是edi),每执行一次,根据DF的值+1(DF == 0)或者-1(DF ==1)
源地址由si决定(对于movsb,movsw是si,movsd是esi),每执行一次,根据DF的值+1(DF == 0)或者-1(DF ==1)
__asm
{
mov esi, dword ptr[k];
mov edi, dword ptr[p];
mov ecx, 5F5E100h;
rep movsd;
};
好吧,其实上面是memcpy。如果要实现memmove,还需要多进行一些判断,就像memmove要求的那样
事实上,我们只要单步调试就可以看到memmove执行的代码了,在VS里面看,的确是进行了汇编优化(注意VS编译器用的memmove的并不是在memmove.c定义的C的版本,而是在memcpy.asm的汇编版本),在我们的例子中,汇编代码如下:
ifdef MEM_MOVE
_MEM_ equ <memmove>
else ; MEM_MOVE
_MEM_ equ <memcpy>
endif ; MEM_MOVE % public _MEM_
_MEM_ proc \
dst:ptr byte, \
src:ptr byte, \
count:IWORD ; destination pointer
; source pointer
; number of bytes to copy OPTION PROLOGUE:NONE, EPILOGUE:NONE push edi ; save edi
push esi ; save esi ; size param/4 prolog byte #reg saved
.FPO ( , , $-_MEM_ , , , ) mov esi,[esp + 010h] ; esi = source
mov ecx,[esp + 014h] ; ecx = number of bytes to move
mov edi,[esp + 0Ch] ; edi = dest ;
; Check for overlapping buffers:
; If (dst <= src) Or (dst >= src + Count) Then
; Do normal (Upwards) Copy
; Else
; Do Downwards Copy to avoid propagation
; mov eax,ecx ; eax = byte count mov edx,ecx ; edx = byte count
add eax,esi ; eax = point past source end cmp edi,esi ; dst <= src ?
jbe short CopyUp ; no overlap: copy toward higher addresses cmp edi,eax ; dst < (src + count) ?
jb CopyDown ; overlap: copy toward lower addresses ;
; Buffers do not overlap, copy toward higher addresses. CopyUp:
cmp ecx, 020h
jb CopyUpDwordMov ; size smaller than 32 bytes, use dwords
cmp ecx, 080h
jae CopyUpLargeMov ; if greater than or equal to 128 bytes, use Enhanced fast Strings
bt __isa_enabled, __ISA_AVAILABLE_SSE2
jc XmmCopySmallTest
jmp Dword_align CopyUpLargeMov:
bt __favor, __FAVOR_ENFSTRG ; check if Enhanced Fast Strings is supported
jnc CopyUpSSE2Check ; if not, check for SSE2 support
rep movsb
mov eax,[esp + 0Ch] ; return original destination pointer
pop esi
pop edi
M_EXIT
因为我们的例子中没有重叠的内存区,而且大小也比128bytes要大,自然就进入了CopyUpLargeMov过程,我们可以很清楚地发现rep movsb了,memmove实现过程就是我们所想的那样。实际上memmove汇编版本还有其他大量的优化,有兴趣的朋友可以点进去memcpy.asm去看一看。
这样感觉很不错,用movsd指令以后我们可以很直观地发现我们已经减少了很多无谓的寄存器赋值操作(movsd指令还有被CPU进行加速的)我们接下来试下效果:

std::copy性能分析与memmove机器级实现的更多相关文章
- 系统级性能分析工具perf的介绍与使用
测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题) Kernel:3.13.0-32 系统级性能优化通常包括两个阶段:性能剖析(performance pro ...
- 系统级性能分析工具perf的介绍与使用[转]
测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题) Kernel:3.13.0-32 系统级性能优化通常包括两个阶段:性能剖析(performance pro ...
- 系统级性能分析工具 — Perf
从2.6.31内核开始,linux内核自带了一个性能分析工具perf,能够进行函数级与指令级的热点查找. perf Performance analysis tools for Linux. Perf ...
- 系统级性能分析工具 — Perf【转】
转自:https://blog.csdn.net/zhangskd/article/details/37902159 版权声明:本文为博主原创文章,转载请注明出处. https://blog.csdn ...
- CentOS6中OpenMP的运行时间或运行性能分析
OpenMp作为单机多核心共享内存并行编程的开发工具,具有编码简洁等,容易上手等特点. 关于OpenMP的入门,博主饮水思源(见参考资料)有了深入浅出,循序渐进的分析.做并行开发,做性能分析是永远逃避 ...
- DevTools 实现原理与性能分析实战
一.引言 从 2008 年 Google 释放出第一版的 Chrome 后,整个 Web 开发领域仿佛被注入了一股新鲜血液,渐渐打破了 IE 一家独大的时代.Chrome 和 Firefox 是 W3 ...
- Java 性能分析工具 , 第 3 部分: Java Mission Control
引言 本文为 Java 性能分析工具系列文章第三篇,这里将介绍如何使用 Java 任务控制器 Java Mission Control 深入分析 Java 应用程序的性能,为程序开发人员在使用 Jav ...
- 常用排序算法的python实现和性能分析
常用排序算法的python实现和性能分析 一年一度的换工作高峰又到了,HR大概每天都塞几份简历过来,基本上一天安排两个面试的话,当天就只能加班干活了.趁着面试别人的机会,自己也把一些基础算法和一些面试 ...
- 【转】一文掌握 Linux 性能分析之 CPU 篇
[转]一文掌握 Linux 性能分析之 CPU 篇 平常工作会涉及到一些 Linux 性能分析的问题,因此决定总结一下常用的一些性能分析手段,仅供参考. 说到性能分析,基本上就是 CPU.内存.磁盘 ...
随机推荐
- 使用Flex4容器若干技巧
本文适用于正在寻找使用Flex 4容器和布局的快速参考指南的开发人员. 尽管这不一定是一个复杂问题,但这似乎是许多开发人员的挫折的来源,特别是对于那些Flex刚刚入门的开发人员. 当开发人员不知道如何 ...
- Android 自定义Activity栈对Activity统一管理
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6307239.html public class AppManager { private static St ...
- JavaWeb知识回顾二
动态web资源相关 1.tomcat相关 tomcat的目录结构 bin -- tomcat服务器的批处理文件的存放目录 conf -- tomcat服务器配置文件的存放目录 lib -- tomca ...
- .NET 通用高扩展性的细粒度权限管理架构(webApi/Mvc)
一. 权限场景分析: 1. 系统具有角色概念, 部门概念, 且都具有相应不同的权限 2. 用户具有多个角色, 多个部门等关系, 并且能给单个用户指派独有的权限 3. 具有细粒度权限控制到资源的RBAC ...
- Dev的WPF控件与VS2012不兼容问题
在只有vs2010环境下Dev的wpf可以在视图模式下显示,但是安装vs2012后无法打开界面的视图模式,报错:无法创建控件实例! 发现是Dev的wpf控件与.net framework 4.5不兼容 ...
- Maven入门,Maven项目的创建,nexus 2.x搭建私服以及Maven多模块项目创建
maven的了解做一个总结,以便日后查阅, 若有不足之处,还望指出,学无止境 当然也能起到入门效果. 一,搭建maven私服 1.工具 a. Nexus 2.5.1-01 b. Maven 3.3.9 ...
- iOS详解MMDrawerController抽屉效果(一)
提前说好,本文绝对不是教你如何使用MMDrawerController这个第三方库,因为那太多人写了 ,也太简单了.这篇文章主要带你分析MMDrawerController是怎么实现抽屉效果,明白 ...
- Javascript面对对象. 第二篇
但是还有一个问题,就是识别的问题,因为根本无法搞清楚他们到底是哪个对象的实例. 1.构造函数 function CreateObject(name,age){ //创建一个对象,使用构造函数的对象都是 ...
- MVC - 单点登录中间件
本章将要和大家分享的是一个单点登录中间件,中间件听起来高深其实这里只是吧单点登录要用到的逻辑和处理流程封装成了几个方法而已,默认支持采用redis服务保存session的方式,也可以使用参数Func& ...
- 支持缩放的fresco图片控件 —— fresco sample: ZoomableDraweeView
最近在实现一个类似淘宝中的评论列表的功能,其中要在列表中显示评论图,点击图片后显示大图进行查看,各家app几乎都会有这样的功能. 可以看到,一个体验较好的查看大图的基本功能有, 第一,左右滑动时切换图 ...