首页 > 系统相关 >每个程序员都应该了解的内存知识(五): 代码优化

每个程序员都应该了解的内存知识(五): 代码优化

时间:2024-03-29 20:12:01浏览次数:21  
标签:wg 变量 LL 程序员 代码优化 int64 内存 SC 操作

代码优化

多线程优化

尽量使用顺序读写

因为分支预测的关系, 顺序读写通常能够带来更好的性能.

共享变量

  1. 将只读变量和读写变量分离

    有可能因为缓存行的原因导致读写变量的更新影响到读变量, 进而影响了运行速度

  2. 提升数据的局部性, 将一起使用的读写变量分组到一个结构中

  3. 缓存行Padding (谨慎使用)

    package main
    
    import (
        "sync"
        "runtime"
    )
    
    type NoPad struct {
        a int64
        b int64
    }
    
    type Pad struct {
        a int64
        _ [56]byte // 填充56字节,与int64加起来正好是64字节,即一个缓存行的大小
        b int64
    }
    
    func main() {
        // 创建没有填充的结构体
        np := NoPad{0, 0}
        // 创建有填充的结构体
        p := Pad{0, [56]byte{}, 0}
    
        var wg sync.WaitGroup
        wg.Add(2)
    
        // 更新NoPad结构体的两个字段
        go func() {
            for i := 0; i < 1000000; i++ {
                np.a = int64(i)
            }
            wg.Done()
        }()
        go func() {
            for i := 0; i < 1000000; i++ {
                np.b = int64(i)
            }
            wg.Done()
        }()
    
        // 更新Pad结构体的两个字段
        go func() {
            for i := 0; i < 1000000; i++ {
                p.a = int64(i)
            }
            wg.Done()
        }()
        go func() {
            for i := 0; i < 1000000; i++ {
                p.b = int64(i)
            }
            wg.Done()
        }()
    
        wg.Wait()
        runtime.GC() // 垃圾回收,仅为了在程序结束前清理资源
    }
    
    

    通过填充, 是个某个结构体能够填充一整个缓存行, 而不会影响其他的变量

  4. 如果一个变量被多个线程使用,但每次使用都是独立的,copy It

原子性优化

相比较普通的操作, 原子性操作要更慢, 如果在已经存在并发保护的情况下, 考虑不要使用原子操作

LL/SC

LL操作会读取一个共享变量的值,并建立一个监视(monitor)或者链接(link)。这个链接会在相对应的Store Conditional(SC)操作之前保持活跃状态。这意味着,如果另一个处理器在LL和SC之间修改了该变量,SC操作就会失败。

Store Conditional (SC)操作

SC操作尝试写入一个新值到之前LL操作读取的那个共享变量。如果自LL操作以来该变量没有被其他处理器修改,那么SC将成功,否则它将失败。在失败的情况下,通常重试整个LL/SC序列。

LL/SC可以用来实现各种原子操作,如原子的加法、减法、比较和交换等。这些操作是构建更高级同步构造的基石,如锁、信号量和其他并发控制机制。

CAS

这是一个三进制操作,只有当当前值与第三参数值相同时,才将作为参数提供的值写入地址(第二参数)

这里稍微注意下ABA问题:

ABA问题发生在一个线程在CAS操作中读取了内存位置的值A,并且准备更新这个位置到某个新值B。如果在这个线程完成更新之前,另一个线程将该位置的值从A改为B,然后又改回A,这时原来的线程执行CAS操作时会发现该位置的值仍然是A,因此它会错误地认为这个值没有被其他线程更改过,从而成功地将值更新为B。

为了解决ABA问题,一种常见的方法是使用版本号或时间戳。每次变量更新时,除了变量的值,还会更新一个额外的版本号或时间戳。这样,即便变量的值被改回原值,版本号也会不同,从而CAS操作能够检测到中间的状态变化。在现代的处理器和编程语言中,通常会提供一些特殊的数据类型或原子操作,如原子引用计数(atomic reference counting)或者原子标记指针(atomic marked pointers),来帮助解决ABA问题。

标签:wg,变量,LL,程序员,代码优化,int64,内存,SC,操作
From: https://www.cnblogs.com/pDJJq/p/18104521/code-optimization-z2jro1b

相关文章

  • 每个程序员都应该了解的内存知识(一): 南桥&北桥&内存
    南桥&北桥&内存结构每个程序员都应该了解的内存知识.pdf-p5-每个程序员都应该了解的内存知识-P5-20240327103419​​功能每个程序员都应该了解的内存知识.pdf-p5-每个程序员都应该了解的内存知识-P5-20240327104347​​北桥主要是连接CPU以及RAM以及南桥,作为连......
  • 每个程序员都应该了解的内存知识(二): CPU Cache
    CPUCache架构每个程序员都应该了解的内存知识.pdf-p22-每个程序员都应该了解的内存知识-P22-20240328112647​​每个程序员都应该了解的内存知识.pdf-p23-每个程序员都应该了解的内存知识-P23-20240328112807​​每个程序员都应该了解的内存知识.pdf-p23-每个......
  • 程序员35岁会失业吗?
    程序员35岁会失业吗?年龄并不是决定程序员就业机会的唯一因素。尽管年龄可能会对就业产生一定影响,但仍然有很多因素会影响一个程序员是否会失业。以下是一些需要考虑的因素:技能水平:技能和经验是程序员就业的关键因素。如果一个程序员保持学习和更新技能,掌握最新的技术和工......
  • Android数据库升级,阿里程序员的Android之路
    publicsynchronizedstaticDBHelpergetInstance(Contextcontext){if(instance==null){instance=newDBHelper(context);}returninstance;}@OverridepublicvoidonCreate(SQLiteDatabasedb){db.execSQL(SQL.CREATE_TABLE_FAVORITE);//若不是第一个......
  • 程序员转行做什么比较可行?
    ​前言现阶段互联网发展迎来新机遇和新挑战,随着时代的发展网络安全已成刚需,也成为了社会治理现代化的重要一环。也是目前互联网行业的未来发展重点方向。而目前,网络安全人才极度匮乏,门槛也相对较低,对于求职者来说发展空间相当之大。根据《互联网安全报告》显示,我国网络......
  • Lec3 Lec4: 虚拟内存和RISC-V寄存器
    虚拟内存使用虚拟内存主要为了实现隔离内存隔离,所有程序指令存放在一个物理内存上,如果一个指令的操作位刚好是另一个指令的地址,那么会造成指令的丢失为了解决这个问题使用地址空间地址空间为每一个指令程序分配自己的地址空间,每个指令程序只能在自己的地址空间上操作。我们需......
  • 使用Andorid Studio解决app内存泄漏问题方法与实践
    某项目的app运行一段时间(切换页面、触发交互事件等)后就开始严重卡顿,使用top查看内存的使用情况,发现每次操作过后内存都有小幅增长,且永远不下降,存在内存泄露问题。目录1AndoridStudio内存泄露检测工具使用方法2内存泄露实例分析2.1页面切换后未主动释放​编辑2.2回调......
  • 如何在Java中读取超过内存大小的文件
    读取文件内容,然后进行处理,在Java中我们通常利用Files类中的方法,将可以文件内容加载到内存,并流顺利地进行处理。但是,在一些场景下,我们需要处理的文件可能比我们机器所拥有的内存要大。此时,我们则需要采用另一种策略:部分读取它,并具有其他结构来仅编译所需的数据。接下来,我们就来......
  • 内存屏障
    编译器屏障Compilerbarrier/*The"volatile"isduetogccbugs*/#definebarrier()__asm____volatile__("":::"memory") 阻止编译器重排,保证编译程序时在优化屏障之前的指令不会在优化屏障之后执行。 CPU屏障CPUbarrierCPU级别内存屏障其作用有两个:防止指令之间的......
  • MybatisPlus多参数分页查询,黑马程序员SpringBoot3+Vue3教程第22集使用MP代替pagehelpe
    前言:视频来源1:黑马程序员SpringBoot3+Vue3全套视频教程,springboot+vue企业级全栈开发从基础、实战到面试一套通关视频来源2:黑马程序员最新MybatisPlus全套视频教程,4小时快速精通mybatis-plus框架创作理由:网上MP实现分页查询功能的帖子易读性太差,具体实现看下面。根据视频完成......