诚然,我不明白。假设您有一个长度为 1 字节的内存字的内存。为什么不能在未对齐地址(即不能被 4 整除)上的单个内存访问中访问 4 字节长的变量,就像对齐地址的情况一样?
最佳答案
现代处理器上的内存子系统仅限于以字长的粒度和对齐方式访问内存;原因有很多。
现代处理器具有多个级别的高速缓存,必须通过这些高速缓存来提取数据;支持单字节读取将使内存子系统的吞吐量与执行单元的吞吐量紧密绑定(bind)(又名 cpu-bound);这一切都让人想起 PIO mode was surpassed by DMA硬盘驱动器中的许多相同原因。
CPU总是读取它的字长(在 32 位处理器上为 4 个字节),因此当您在支持它的处理器上执行未对齐的地址访问时,处理器将读多个单词。 CPU 将读取您请求的地址跨越的每个内存字。这导致访问请求的数据所需的内存事务数量最多增加 2 倍。
因此,读取两个字节很容易比读取四个字节慢。例如,假设您在内存中有一个如下所示的结构:
struct mystruct {
char c; // one byte
int i; // four bytes
short s; // two bytes
}
在 32 位处理器上,它很可能会如下所示对齐:
处理器可以在一个事务中读取这些成员中的每一个。
假设你有一个打包版本的结构,可能来自网络,它是为了传输效率而打包的;它可能看起来像这样:
读取第一个字节将是相同的。
当您要求处理器从 0x0005 给您 16 位时,它必须从 0x0004 读取一个字并左移 1 个字节以将其放入 16 位寄存器;一些额外的工作,但大多数人可以在一个周期内完成。
当您从 0x0001 请求 32 位时,您将获得 2X 放大。处理器将从 0x0000 读取到结果寄存器并左移 1 个字节,然后再次从 0x0004 读取到临时寄存器,右移 3 个字节,然后与结果寄存器进行 OR。
对于任何给定的地址空间,如果架构可以假设 2 个 LSB 始终为 0(例如,32 位机器),那么它可以访问 4 倍的内存(2 个保存的位可以代表 4 个不同的状态),或者相同数量的内存与 2 位用于标志之类的东西。从地址中取出 2 个 LSB 将使您获得 4 字节对齐;也称为 stride 4字节。每次增加地址时,它实际上是在增加第 2 位,而不是第 0 位,即最后 2 位将始终继续为 00。
这甚至会影响系统的物理设计。如果地址总线需要少 2 位,CPU 上的引脚可以少 2 个,电路板上的走线也可以少 2 个。
CPU 可以原子地对对齐的内存字进行操作,这意味着没有其他指令可以中断该操作。这对许多 lock-free data structures 的正确操作至关重要。和其他 concurrency范式。
处理器的内存系统比这里描述的要复杂得多。关于 how an x86 processor actually addresses memory 的讨论可以提供帮助(许多处理器的工作方式类似)。
坚持内存对齐还有很多好处,您可以在 this IBM article 阅读。 .
计算机的主要用途是转换数据。几十年来,现代内存架构和技术已经过优化,以促进以高度可靠的方式在更多更快的执行单元之间获取更多数据。
我之前提到的另一个性能对齐是缓存行上的对齐(例如,在某些 CPU 上)64B。
有关利用缓存可以获得多少性能的更多信息,请查看 Gallery of Processor Cache Effects ;从此question on cache-line sizes
Understanding of cache lines can be important for certain types of program optimizations. For example, the alignment of data may determine whether an operation touches one or two cache lines. As we saw in the example above, this can easily mean that in the misaligned case, the operation will be twice slower.
关于memory - 内存对齐的目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/381244/
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序
你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p
这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e
嗨,我正在使用rolify,只是意识到我并没有真正利用它的全部潜力。目前,我正在Controller中执行某些操作,如current_user.has_role?:whatever_role重新路由用户,并允许用户担任其他角色……有人问了有关rolify的stackoverflow问题,当我要回答它时,我意识到我做错了。现在,这是我的困惑开始的地方...在capability.rb中,我有:user||=User.new#guestuser(notloggedin)ifuser.has_role?:consumercan:manage,Reviewelsecan:read,Review
我知道Rake代表RubyMake,我知道Make是一个unix构建实用程序。现在,我在Xcode工作,将iPhone应用程序构建到Ruby,所以我以前从未使用过Make,我唯一一次使用rake是在rails中或安装一些第三方包时,我输入了像rakedb这样的命令:迁移。我不明白的是……构建实用程序到底是什么?rake的目的是什么?它让我做什么?因此,如果有人能帮我回答这些问题中的任何一个,我将不胜感激。 最佳答案 Rake允许您在每个项目的基础上编写某些任务的脚本,就像Makefile允许Unix开发人员编写他们的编译和构建过程的
在部署在heroku上的Rails应用程序(v:3.1)中,我在内存中获得了更多具有相同ID的对象。我的heroku控制台日志:>>Project.find_all_by_id(92).size=>2>>ActiveRecord::Base.connection.execute('select*fromprojectswhereid=92').to_a.size=>1这怎么可能?可能是什么问题? 最佳答案 解决方案根据您的SQL查询,您的数据库中显然没有重复条目。也许您的类项目中的size或length方法已被覆盖。我试过find_
我的两个不同的Rails应用程序的内存有一些奇怪的问题。这两个应用程序都使用rails3.0.7。每个Controller请求分配20-30-50MB的内存。在生产模式下,这个数量减少到5-10。但这是同样的事情。这是两个应用程序使用的gem列表:gem'pg'gem'haml'gem'sass'gem'devise'gem'simple_form'gem'state_machine'gem"globalize3","0.1.0.beta"gem"easy_globalize3_accessors"gem'paperclip'gem'andand'关闭所有这些gem不会给我任何结果。我
正如标题,我有一个处理大量数据的ruby程序。该程序占用了所有内存,其中调用了系统命令hostname,并且发生错误无法分配内存-主机名我试过GC.start但它不起作用。那么如何强制ruby释放未使用的内存呢?OK,这是别人的测试代码,最后报错是big_var被回收了。但是内存仍然没有释放。require"weakref"defreportputs"#{param}:\t\tMemory"+`psax-opid,rss|grep-E"^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)[1].to_s+'KB'endbig_var=""#big
我想上传我在运行时用Ruby生成的数据,就像从block中提供上传数据一样。我找到的所有示例仅展示了如何流式传输必须在请求之前位于磁盘上的文件,但我不想缓冲该文件。除了滚动我自己的套接字连接之外,最好的解决方案是什么?这是一个伪代码示例:post_stream('127.0.0.1','/stream/')do|body|generate_xmldo|segment|body 最佳答案 有效的代码。require'thread'require'net/http'require'base64'require'openssl'class