首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >频率图哈希映射中的LongAdder与整数

频率图哈希映射中的LongAdder与整数
EN

Stack Overflow用户
提问于 2021-01-27 21:14:23
回答 1查看 125关注 0票数 0

我正在使用HashMap在单线程环境中构造一个频率映射。键是弦,它的频率需要跟踪。

如果我使用HashMap,则每个增量都需要一个新的整数。

对于这个用例,LongAdder会表现得更好吗,因为我可以简单地调用can ()吗?一些基本的测试表明,LongAdder确实表现得稍微好一些,但我不知道为什么。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-27 23:09:24

测试以确定增量积分类型的相对性能。

代码语言:javascript
复制
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Function;

public class LongAdderTest {
    
    public static void main(String[] args) {
        new LongAdderTest().start();
    }
    
    public void start() {
        int N = 100_000_000;
        int warmup = 3;
        String[] testNames = { "LongAdder", "Long", "Integer", "long",
                "int", "Object", "int[]", "long[]" };
        List<Function<Integer, Long>> tests = List.of(
                this::longAdderTest, this::longWrapperTest,
                this::integerWrapperTest, this::primitiveLongTest,
                this::primitiveIntTest, this::objectTest,
                this::intArrayTest, this::longArrayTest);
        
        int i = 0;
        for (Function<Integer, Long> test : tests) {
            runTest(test, warmup, N, testNames[i++]);
        }
    }
    
    public void runTest(Function<Integer, Long> test, int warmup,
            int iterations, String testName) {
        // warmup cycle
        for (int i = 0; i < warmup; i++) {
            long v = test.apply(iterations);
            if (v != iterations) {
                System.out
                        .println("Unexpected result - return = " + v);
            }
        }
        long start = System.nanoTime();
        long val = test.apply(iterations);
        System.out.printf("%-10s : %12f  %d%n", testName,
                (System.nanoTime() - start) / 1_000_000., val);
    }
    
    public long longAdderTest(int iter) {
        LongAdder val = new LongAdder();
        Map<String, LongAdder> freq = new HashMap<>();
        freq.put("A", val);
        for (int i = 0; i < iter; i++) {
            freq.get("A").increment();
        }
        return freq.get("A").longValue();
    }
    
    public long longWrapperTest(int iter) {
        Long val = 0L;
        Map<String, Long> freq = new HashMap<>();
        freq.put("A", val);
        for (int i = 0; i < iter; i++) {
            freq.computeIfPresent("A", (k, v) -> v + 1);
        }
        return freq.get("A");
    }
    
    public long integerWrapperTest(int iter) {
        Integer val = 0;
        Map<String, Integer> freq = new HashMap<>();
        freq.put("A", val);
        for (int i = 0; i < iter; i++) {
            freq.computeIfPresent("A", (k, v) -> v + 1);
        }
        return freq.get("A");
    }
    
    public long primitiveLongTest(int iter) {
        Map<String, Long> freq = new HashMap<>();
        long val = 0;
        freq.put("A", val);
        for (int i = 0; i < iter; i++) {
            freq.computeIfPresent("A", (k, v) -> v + 1);
        }
        return freq.get("A");
    }
    
    public long primitiveIntTest(int iter) {
        Map<String, Integer> freq = new HashMap<>();
        int val = 0;
        freq.put("A", val);
        for (int i = 0; i < iter; i++) {
            freq.computeIfPresent("A", (k, v) -> v + 1);
        }
        return freq.get("A");
    }
    
    public long intArrayTest(int iter) {
        Map<String, int[]> freq = new HashMap<>();
        int[] val = { 0 };
        freq.put("A", val);
        for (int i = 0; i < iter; i++) {
            freq.get("A")[0] += 1;
        }
        return freq.get("A")[0];
    }
    
    public long longArrayTest(int iter) {
        Map<String, long[]> freq = new HashMap<>();
        long[] val = { 0L };
        freq.put("A", val);
        for (int i = 0; i < iter; i++) {
            freq.get("A")[0] += 1;
        }
        return freq.get("A")[0];
        
    }
    
    public long objectTest(int iter) {
        MyLongIncrement longObject = new MyLongIncrement(0);
        Map<String, MyLongIncrement> freq = new HashMap<>();
        freq.put("A", longObject);
        for (int i = 0; i < iter; i++) {
            freq.get("A").increment();
        }
        return freq.get("A").get();
    }
    
    static class MyLongIncrement {
        long val;
        
        public MyLongIncrement(long v) {
            this.val = v;
        }
        
        public long get() {
            return val;
        }
        
        public void increment() {
            val += 1l;
        }
    }
}

试运行。

代码语言:javascript
复制
LongAdder  :  4166.724472  100000000
Long       :  2929.021352  100000000
Integer    :  5487.358323  100000000
long       :  2993.538570  100000000
int        :  2505.171838  100000000
Object     :  1032.322116  100000000
int[]      :  1132.710126  100000000
long[]     :  1107.633331  100000000

详细信息

使用Map的

  • 使值更接近。
  • ,但似乎在最后三种类型的基础上进行增量可能是最好的,因为值本身不需要在地图中更新。对于LongAdder来说也是一样,但是同步代码可能是一个因素(或者测试设计器),因为它的性能不那么出色。但是,可能有许多因素,包括我访问map值的方法.

我想我受够了。希望它能对这个问题有所启发。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65927505

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档