C++ Low level performance optimize 2

上一篇 文章讨论了一些底层代码的优化技巧,本文继续讨论一些相关的内容。

首先,上一篇文章讨论cache missing的重要性时,用了list做比较,目的并不是说list没有用,而是说明cache missing会对性能有重要影响。如果元素不多,并且对象复制的代价很大,那么list可能就是更好的选择。其次,这里讨论的大部分是编码时一些比较底层的技巧,当遇到性能问题时,应该先考虑是否能在高层改进算法,减少运算,实在不行,在考虑这类优化技巧。性能优化的挑战就在于没有完美的永远适用的方案,了解这些技巧让我们在优化代码时有更多武器,但最终选择哪个方案还需要更加实际情况,并且以profile的实际数据为依据来做。

1.  Data Layout

调整数据布局是常见的优化手段,做此类优化时有几点需要注意:首先是内存占用,现代编译器默认大多以16或32位对齐,因此

struct BadLayout
{
int8_t i0;
int32_t i1;
int8_t i2;
}; struct GoodLayout
{
int8_t i0;
int8_t i2;
int32_t i1;
};

sizeof(Goodlayout) >= sizeof(BadLayout) 在vs2013默认对齐设置下,BadLayout==12 byte,GoodLayout==8byte。

其次,经常访问或者相关的数据应该放到一起,减少cache missing。Going native2013 Andrei Alexandrescu介绍了facebook做的重要性能优化就是把php代码编译为c++代码,而在代码转换中重要的一步就是根据数据的”hotness”重新布局。

struct BadLayout
{
auto user0_data0;
auto user1_data1;
auto user0_data1;
auto user1_data0;
}; struct GoodLayout
{
auto user0_data0;
auto user0_data1;
auto user1_data0;
auto user1_data1; };

最后,可维护性!这一点非常重要,对于一些生命周期较长的项目来说,把数据按逻辑组织更易于维护,减少潜在bug的重要性,如果性能差别不大,我通常更愿意让代码看起来好读J

2.  Code cache

struct BitBool
{
bool b0 :;
bool b1 :;
bool b2 :;
} struct NormalBool
{
bool b0;
bool b1;
bool b2;
}

上次的例子中,这段代码比较有争议,让我们从时间和空间方面来分析。时间上,因为BitBool需要额外指令来访问元素,因此效率一定比NormalBool低,但差别非常小,几乎可以忽略。再看空间上,但从结构本身看,显然BitBool更小,但是由于访问元素需要额外指令,实际应用中,生成的代码一定比NormalBool多,读取访问的次数越多,生成的代码也越多(内联的结果),而代码也需要占用内存空间!!cache line中通常一半是代码,一半是数据。因此,不一定因为BitBool本身小就得到更好的cache。大部分文章在讨论cache missing时都只介绍了数据,而忽略了代码也需要占用内存,也会有cache missing。某些游戏引擎会在update entity时先把对象按照类型排序,就是为了减少代码的cache missing。

最后,这个例子的目的是让大家了解过度优化可能并不会带来性能提升,实际应用中两种写法的虽然有性能差距,但基本可以忽略。

 3.  more about bit field

上一个例子让我想起了bitfield另一个微妙的地方,假设f1和f2在两个不同线程中,考虑下面代码是安全的吗?

struct BitField
{
bool b0 : ;
bool b1 : ;
bool b2 : ;
uint8_t i0 :;
} BitField bf;
std::mutex mtx1;
std::mutex mtx2;
//thread 1
void f1()
{
mtx1.lock();
bf.b1 = somevalue;
mtx1.unlock();
}
//thread 2
void f2()
{
mtx2.lock();
bf.i0 = somevalue;
mtx2.unlock();
}

No!!!虽然代码可以通过编译运行,但却并不是线程安全的,因为b1,i0都属于同一快内存”单元”,因此根本无法生成只更新b1,但是不写入i0的代码!!实际上c++11明确指出了这种情况会导致race,临近的bit总是被当做一个”对象” :)

C++ Low level performance optimize 2的更多相关文章

  1. C++ Low level performance optimize

    C++ Low level performance optimize 1.  May I have 1 bit ? 下面两段代码,哪一个占用空间更少,那个速度更快?思考10秒再继续往下看:) //v1 ...

  2. Solr实现Low Level查询解析(QParser)

    Solr实现Low Level查询解析(QParser) Solr基于Lucene提供了方便的查询解析和搜索服务器的功能,可以以插件的方式集成,非常容易的扩展我们自己需要的查询解析方式.其中,Solr ...

  3. zabbix监控redis多实例(low level discovery)

    对于多实例部署的tomcat.redis等应用,可以利用zabbix的low level discovery功能来实现监控,减少重复操作.  注:Zabbix版本: Zabbix 3.0.2 一.服务 ...

  4. 使用Java Low Level REST Client操作elasticsearch

    Java REST客户端有两种风格: Java低级别REST客户端(Java Low Level REST Client,以后都简称低级客户端算了,难得码字):Elasticsearch的官方low- ...

  5. Zabbix监控Low level discovery实时监控网站URL状态

    今天我们来聊一聊Low level discovery这个功能,我们为什么要用到loe level discovery这个功能呢? 很多时候,在使用zabbix监控一些东西,需要对类似于Itens进行 ...

  6. ChibiOS/RT 2.6.9 CAN Low Level Driver for STM32

    /* ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio Licensed under the Apache License, Version 2 ...

  7. Consumer设计-high/low Level Consumer

    1 Producer和Consumer的数据推送拉取方式   Producer Producer通过主动Push的方式将消息发布到Broker n Consumer Consumer通过Pull从Br ...

  8. zabbix(10)自动发现规则(low level discovery)

    1.概念 在配置Iterms的过程中,有时候需要对类似的Iterms进行添加,这些Iterms具有共同的特征,表现为某些特定的参数是变量,而其他设置都是一样的,例如:一个程序有多个端口,而需要对端口配 ...

  9. Elasticsearch java api操作(一)(Java Low Level Rest Client)

    一.说明: 一.Elasticsearch提供了两个JAVA REST Client版本: 1.java low level rest client: 低级别的rest客户端,通过http与集群交互, ...

随机推荐

  1. docker解决数据存储问题的方案

    现在docker在云计算领域发展的势头很猛,各个公司不论大小都开始研究这个开源工具和技术,围绕docker的开源项目和创业公司也多如牛毛,就是一个简单管理container的web ui都有很多开源项 ...

  2. 仿Material UI框架的动画特效

    Material UI是一款功能非常强大,界面却十分清新简洁的CSS框架,Material UI利用了Google的Material Design 全新设计语言,并且让每一个UI组件都变得非常独立,因 ...

  3. winform下重画ListBox

    Windows Forms是由Win32 API封装的开发组件,最初是为了替代mfc,但却没有体现与Model View Controller架构对应的特色,进而在.net framework 3.0 ...

  4. Factory模式

    使用new的Code都违反了DIP. 但是,依赖于稳定的具体类,是无害的.例如string. 另一方面,对于正在开发中的APP,很多具体类是易变的.此时应该依赖于抽象接口. Factory模式:只依赖 ...

  5. raspberry pi 如何汉化显示中文

    1 树莓派初装系统之后,首次启动会出现“raspi-config”工具,如下图:(若不是初次启动,在命令模式下,请输入 sudo raspi-config 命令,即可调出此界面.若在图形桌面下,打开桌 ...

  6. python实现自动发送微博,当自己写博客时同步上去。

    一.需求: 自己在github上搭建一个基于Jekyll的博客(http://beginman.cn/),每次写完博客后就要push上去,博客写的再好,基本上没人访问,为了增加访问量,就想利用起来微博 ...

  7. js for in对象key排序

    最近遇到一个比较奇葩的事情,for in 循环的时候,如果对象key 默认可以转化为整数,会把key转化为整数排序. code: 运行结果 大家看到data2的key默认顺序是"2" ...

  8. Android--使用Canvas绘图

    前言 除了使用已有的图片之外,Android应用常常需要在运行时根据场景动态生成2D图片,比如手机游戏,这就需要借助于Android2D绘图的支持.本篇博客主要讲解一下Android下使用Canvas ...

  9. 解决Electron加载带jquery的项目报错问题

    <!-- Insert this line above script imports --> <script>if (typeof module === 'object') { ...

  10. nginx-upstream-keepalive;accept_mutex-proxy_http_version-1.1-proxy_set_header-connection

    nginx+resin+redis+mysql的架构: 有外部模拟用户请求的大量攻击:它尝试请求了80就断开:看到的现象是在跑有nginx80的主机上TCP连接数少 : ESTABLISHED少: 在 ...