草庐IT

C# 字典性能 : Default string Comparer's GetHashCode() allocates memory in violation of guidelines, 从而破坏性能?

coder 2024-05-20 原文

an established guideline获取哈希码不应分配内存,因为这会通过调用垃圾收集器对哈希表查找产生负面影响。

然而,这个确切的失败是我所看到的我使用 System.Collections.Generic.Dictionary 的应用程序的配置文件

在一个非常紧凑的循环中,我在分析器结果中发现以下内容:

  • [3.47%] TryGetValue(TKey, TValue&) (...字典)
  • [3.47%] FindEntry(TKey) (...字典)
  • [3.47%] GetHashCode(string) (System.CultureAwareComparer)
  • [3.46%] GetHashCodeOfString(String, CompareOptions) (System.Globalization.CompareInfo)
  • [3.39%] [垃圾收集]
  • [0.01%] [线程暂停]

  • 这是来自分析器的整个子树会计。

    我不是这种特定工作的经验丰富的专家,所以我可能会错误地阅读这些茶叶。但在我看来,GetHashCodeOfString“必须”分配内存并邀请垃圾收集器在这个循环中间中断我的程序我想要真正调整和紧密,这占了这个循环成本的惊人大部分。

    顺便说一句,here is an additional piece of evidence suggesting this code allocates memory

    我的下一步将是使用序数比较器初始化字典并重新运行我的测试。

    但我想知道是否存在围绕这个问题的智慧。似乎带有字符串键的字典很常见,并且可以很好地探索这种常见事物的成本。我找到了下面的分析,但它侧重于实际比较作为灾难的原因,而不是分配内存的哈希码方法。

    任何人都可以建议使用带有字符串键的字典的正确方法来避免这个问题吗?

    我的具体问题包括:
  • 如果我使用序数比较器,分配会消失吗?
  • 如果没有,我是否需要编写自己的比较器,这会使分配消失吗?
  • 如果我确实让比较器消失了,根据我开始使用的 MSFT 推荐链接,我真的可以期待真正的改进吗?

  • 编辑: Crud,我的错,但这不是默认的比较器属性,我们将它设置为 ignoreCase。不确定这是否会影响结果,但由于 ignoreCase 会影响相等性,因此它必须对哈希产生一些影响。

    更新:使用序数比较器(仍然使用 IgnoreCase)进行另一次测试,并将原始结果输出重新转换为 100% 成本 = TryGetValue,这样苹果对苹果就会更多

    原来的:
  • 100% 尝试获取值(value)
  • 100% FindEntry
  • 99.5% CultureAwareComparer.GetHashCode
  • 99.5% CompareInfo.GetHashCodeOfString
  • 95.86%【垃圾收集】
  • 3.31% [线程暂停]
  • 0.5% CultureAwareComparer.Equals
  • 0.5% 比较
  • 0.5%【垃圾回收】

  • 序数:
  • 100% 尝试获取值(value)
  • 100% FindEntry
  • 47.22% CultureAwareComparer.Equals
  • 47.22%【垃圾收集】

  • 在 TryGetValue 中花费的总时间似乎也显着减少。我没有小心地确保其他一切都相同,但这在第一次运行的 10 分钟压力测试中占了 46 秒,而在 oridal 运行中占了 252 毫秒。考虑一下轶事,而不是预期的相对成本。

    似乎散列的全部成本(曾经是成本的 99+%)现在是如此“免费”,以至于它甚至无法出现在分析器中,我认为它以采样模式运行。

    我想这秒了你应该使用序数比较的街道上的词。

    我仍然无法向自己证明为什么 GC 成本对第一个配置文件结果的贡献如此之大,但是从下面的评论中我想我不得不相信它不会分配托管堆内存,但是因为它很慢,所以它倾向于是由其他线程上的其他事件“随机”GC 的函数,因为该进程确实使用服务器模式 gc。

    也许这表明这个紧密循环往往与其他地方的分配快乐代码并发。

    最佳答案

    默认情况下,当您使用 string 时 key ,string.GetHashCode()用来。这种方法不会在堆上分配任何内存,而且应该很快。

    但是由于您使用的是忽略大小写,CultureAwareComparer.GetHashCode()改为使用。该方法调用(从您的配置文件结果中可以看出)CompareInfo.GetHashCodeOfString() ,它依次调用非托管函数 InternalGetGlobalizedHashCode() .这两个托管方法都没有进行任何堆分配(如您在反编译器中查看它们时所看到的)。我说不出什么InternalGetGlobalizedHashCode()确实如此,但由于它是非托管的,我怀疑它会在托管堆上进行任何分配。在任何情况下,它都必须比默认的哈希码计算复杂得多,特别是因为它具有文化意识并且必须牢记诸如 Turkish İ 之类的问题。 .

    这意味着您可能有一些其他代码在堆上分配内存,这会导致垃圾收集。

    如果您要获得最佳性能,则应避免“忽略大小写”,尤其是其文化感知变体。

    关于C# 字典性能 : Default string Comparer's GetHashCode() allocates memory in violation of guidelines, 从而破坏性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7247863/

    有关C# 字典性能 : Default string Comparer's GetHashCode() allocates memory in violation of guidelines, 从而破坏性能?的更多相关文章

    1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

      我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

    2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    3. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

      我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

    4. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

      在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

    5. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

      我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

    6. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

      我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

    7. ruby-on-rails - 新 Rails 项目 : 'bundle install' can't install rails in gemfile - 2

      我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="

    8. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

      关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

    9. ruby-on-rails - Rails 中的 NoMethodError::MailersController#preview undefined method `activation_token=' for nil:NilClass - 2

      似乎无法为此找到有效的答案。我正在阅读Rails教程的第10章第10.1.2节,但似乎无法使邮件程序预览正常工作。我发现处理错误的所有答案都与教程的不同部分相关,我假设我犯的错误正盯着我的脸。我已经完成并将教程中的代码复制/粘贴到相关文件中,但到目前为止,我还看不出我输入的内容与教程中的内容有什么区别。到目前为止,建议是在函数定义中添加或删除参数user,但这并没有解决问题。触发错误的url是http://localhost:3000/rails/mailers/user_mailer/account_activation.http://localhost:3000/rails/mai

    10. c# - 如何在 ruby​​ 中调用 C# dll? - 2

      如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

    随机推荐