文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

我们一起聊聊对象与 Map 转换性能优化方案

2024-11-28 16:05

关注
Person person = new Person();
person.setAge(18);
person.setOpenid("123456");
person.setName("一安");
person.setSubName("公众号");

System.out.println(bean2Map(person));

public static Map bean2Map(Object object) {
    ObjectMapper objectMapper = new ObjectMapper();
    return objectMapper.convertValue(object, new TypeReference>() {
    });
}

改造

首先,我们将使用 Java Microbenchmark Harness (JMH) 对这段代码进行基准测试,以便大家对其性能有一个直观的了解。

图片图片

上图是一个典型的JMH程序执行的内容。通过开启多个进程,多个线程,首先执行预热,然后执行迭代,最后汇总所有的测试数据进行分析。在执行前后,还可以根据粒度处理一些前置和后置操作。

JMH 是 Java 语言的微基准测试框架,用于准确、可靠地测量和评估Java代码的性能。它是由OpenJDK团队开发的,专门针对Java应用程序的性能测试和基准测试。通过JMH 可以对多个方法的性能进行定量分析。比如,当要知道执行一个函数需要多少时间,或者当对一个算法有多种不同实现时,需要选取性能最好的那个。

依赖引入



    org.openjdk.jmh
    jmh-core
    1.35




    org.openjdk.jmh
    jmh-generator-annprocess
    1.35

注解说明

BenchmarkMode

名称

解释

单位

Mode.Throughput

operations per unit of time.(单位时间执行的次数)

ops/time

Mode.AverageTime

average time per per operation(每个方法执行的平均时间)

time/op

Mode.SampleTime

samples the time for each operation.(每个方法执行的时间)

time

Mode.SingleShotTime

measures the time for a single operation.(单个的执行时间)


All

all the benchmark modes. (上面所有都执行一次)


OutputTimeUnit

统计的时间单位

Warmup、Measurement

名称

解释

iterations

预热次数

time

预热时间

timeUnit

预热时间单位

batchSize

同时预热

State

名称

解释

Benchmark

所有测试共享线程。做多线程的时候使用

Group

每一组中共享线程

Thread

每一个方法或者类共享线程

Fork

进行次数,如果 fork 数是2的话,则 JMH 会 fork 出两个进程来进行测试

Benchmark

表示该方法是需要进行 benchmark 的对象,用法和 JUnit 的 @Test 类似

测试验证

@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Fork(1)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 3, time = 1)
public class JsonJMHTest {


    @Benchmark
    public static Map bean2Map() {
        Person person = new Person();
        person.setAge(18);
        person.setOpenid("123456");
        person.setName("一安");
        person.setSubName("公众号");

        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.convertValue(person, new TypeReference>() {
        });
    }

    @Benchmark
    public static  T map2Bean() {
        Map map = new HashMap();
        map.put("age", 18);
        map.put("openid", "123456");
        map.put("name", "一安");
        map.put("subName", "公众号");

        ObjectMapper objectMapper = new ObjectMapper();
        return (T) objectMapper.convertValue(map, Person.class);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(JsonJMHTest.class.getSimpleName())
                .build();
        new Runner(opt).run();
    }

测试结果:

# Fork: 1 of 1
# Warmup Iteration   1: 4121.577 ops/s
# Warmup Iteration   2: 10599.791 ops/s
# Warmup Iteration   3: 1945.716 ops/s
# Warmup Iteration   4: 7284.198 ops/s
# Warmup Iteration   5: 8161.620 ops/s
Iteration   1: 841.544 ops/s
Iteration   2: 25483.108 ops/s
Iteration   3: 70902.482 ops/s


Result "org.example.JsonJMHTest.map2Bean":
  32409.045 ±(99.9%) 648386.677 ops/s [Average]
  (min, avg, max) = (841.544, 32409.045, 70902.482), stdev = 35540.262
  CI (99.9%): [≈ 0, 680795.722] (assumes normal distribution)


# Run complete. Total time: 00:00:22

REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.

Benchmark              Mode  Cnt      Score        Error  Units
JsonJMHTest.bean2Map  thrpt    3  80269.397 ±  61739.014  ops/s
JsonJMHTest.map2Bean  thrpt    3  32409.045 ± 648386.677  ops/s

通过测试结果可以看出,在实现对象转map时每秒可以完成8万多次,而实现map转对象转每秒仅可完成3.2万次。

如何优化

我们都知道在创建工具类时,应将其设计为单例模式,保证在整个系统中仅有一个实例,从而避免因频繁创建对象而带来的成本。

@Getter
public enum ObjectMapperInstance {
    INSTANCE;
    private final ObjectMapper objectMapper = new ObjectMapper();
    ObjectMapperInstance() {
    }
}

枚举类型的单例实现天然线程安全,并且可以抵御反射攻击。

再次测试验证

# Fork: 1 of 1
# Warmup Iteration   1: 916836.618 ops/s
# Warmup Iteration   2: 2057459.265 ops/s
# Warmup Iteration   3: 1992614.947 ops/s
# Warmup Iteration   4: 524763.395 ops/s
# Warmup Iteration   5: 2463816.439 ops/s
Iteration   1: 2570659.849 ops/s
Iteration   2: 2557669.589 ops/s
Iteration   3: 2548610.266 ops/s


Result "org.example.JsonJMHTest.map2Bean":
  2558979.901 ±(99.9%) 202195.856 ops/s [Average]
  (min, avg, max) = (2548610.266, 2558979.901, 2570659.849), stdev = 11083.037
  CI (99.9%): [2356784.046, 2761175.757] (assumes normal distribution)


# Run complete. Total time: 00:00:30

REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
experiments, perform baseline and negative tests that provide experimental control, make sure
the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
Do not assume the numbers tell you what you want them to tell.

Benchmark              Mode  Cnt        Score          Error  Units
JsonJMHTest.bean2Map  thrpt    3  1107857.325 ± 19284117.404  ops/s
JsonJMHTest.map2Bean  thrpt    3  2558979.901 ±   202195.856  ops/s

通过将 ObjectMapper 设计为单例模式,我们可以显著提升性能。在整个项目中只需创建一个 ObjectMapper 实例,避免了每次使用时重新创建对象所带来的开销。这种方法不仅提高了性能,还简化了代码管理和减少了内存消耗。

同样的原则可以应用于其他工具类或频繁使用的对象。例如,数据库连接池、缓存客户端、日志记录器等,都可以通过单例模式来优化性能和资源管理。确保这些组件在整个应用生命周期内只创建一次,可以最大化其效用并减少不必要的资源消耗。

总之,将频繁使用的工具类设计为单例模式是一种良好的编程实践,它不仅提升了性能,还增强了代码的可维护性和可读性。

来源:一安未来内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯