我在我的多线程代码中使用 AtomicLong 的 incrementAndGet 方法来测量我们的一些客户端代码的性能。
@Override
public void run() {
long start = System.nanoTime();
attributes = client.getAttributes(columnsList);
long end = System.nanoTime() - start;
final AtomicLong before = select.putIfAbsent(end / 1000000L, new AtomicLong(1L));
if (before != null) {
before.incrementAndGet();
}
}
在上面的代码中,我试图测量多少时间-
client.getAttributes(columnsList);
正在服用。
据我所知,incrementAndGet 方法将以原子方式将当前值递增 1。 这意味着每个线程可能会等待其他线程递增该值。我是对的吗? 这意味着它会被阻止吗?
这还会影响我衡量任何方法性能的方式吗?这意味着它还会为该测量增加一些额外的时间吗?
为什么我问这个是因为我正在尝试对我们的大部分客户端代码和服务器端代码进行基准测试,如果我需要测量每种方法花费的时间,那么我就是这样做的-
无论我想测量什么代码,我通常将下面一行放在该方法的正上方
long start = System.nanoTime();
这两行在相同的方法之后但使用不同的 ConcurrentHashMap
long end = System.nanoTime() - start;
final AtomicLong before = select.putIfAbsent(end / 1000000L, new AtomicLong(1L));
if (before != null) {
before.incrementAndGet();
}
因此,如果我正在使用 incrementAndGet 方法,如果它为我的性能测量增加了额外的时间,那么我可能无法获得准确的结果?
更新:-
这是下面的方法,我在 eclipse 的 incrementAndGet 上执行 F3 时得到的。
所以这里有一个synchronized block 。这意味着每个线程都会在这里等待其他线程。这是一个阻塞调用。
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final synchronized long incrementAndGet() { //IBM-perf_AtomicLong
++value; //IBM-perf_AtomicLong
return value; //IBM-perf_AtomicLong
}
啊哈。我刚刚检查了我的 JVM,我正在运行 IBM JVM 与 SUN JVM 进行比较。因为我在一家公司工作,所以我无法改变这件事。
那么有什么方法可以避免这种基于锁的解决方案来衡量任何方法的性能/基准?请记住,我正在运行 IBM JVM。
感谢您的帮助。
最佳答案
别担心。除非您正在编写类似外汇平台之类的东西,否则这种微小的延迟无关紧要。为了给您一个想法,我们将以纳秒的数量级进行讨论,而在应用程序代码中我们通常以毫秒为单位进行讨论。此外,JVM 的锁也得到了显着改善。如果争用较少(这是常态),基于锁的解决方案和非阻塞解决方案之间的性能差异将很小。
令人惊讶的是,IBM JVM 使用 AtomicLong 锁。我认为所有主要实现都使用非阻塞 CAS。下面是使用 CAS 的常见实现:
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final long incrementAndGet() {
for (;;) {
long current = get();
long next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
对跟进评论的回应:
作为一个非常粗略的经验法则,如果您当前的端到端响应时间(或响应时间要求)超过 30 毫秒,我真的不会担心这一点,因为增加 long 所花费的时间都在纳秒范围内.我几乎可以肯定您会找到其他可以优化的地方,从而为您带来更多改进(例如毫秒)。
但是,您可以只复制 AtomicLong 的 Sun JVM 实现以使用非阻塞实现来代替使用,因为 IBM VM 也应该有 CAS 操作。如果您预期中度到高度争用(大量线程),这只会导致显着改进。如果您不这样做,我认为锁定解决方案的性能几乎可以与当前的改进锁定实现(如果我记得的话,可以从 JDK6 获得)相同。
事实上,如果您有非常高的竞争,锁可以比非阻塞解决方案执行得更好。所以理想情况下你必须使用两个实现并比较结果......这就是为什么我认为你不应该打扰的原因,因为在那个时候,你可以在其他地方做出一些性能改进,让你在文学上获得超过 1通过解决这里问题可以获得的改进的百万倍。
关于java - AtomicLong 的 incrementAndGet 方法在内部如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15992745/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco