Java中小的不可变对象的缓存策略? [英] Caching strategy for small immutable objects in Java?

查看:103
本文介绍了Java中小的不可变对象的缓存策略?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应用程序,该应用程序创建了大量小的,不可变的Java对象。例如:

I am developing an app that creates a large number of small, immutable Java objects. An example might be:

public class Point {
  final int x;
  final int y;
  final int z;
  .....
}

在很多情况下Point需要参考相同的(x,y,z)位置。

Where it is likely that many instances of Point will need to refer to the same (x,y,z) location.

在应用程序的生存期内尝试缓存和重用此类对象在什么程度上有意义?有什么特殊的技巧可以处理这种情况?

To what extent does it make sense to try to cache and re-use such objects during the lifetime of the application? Any special tricks to handle this kind of situation?

推荐答案

您可能遇到的问题是使对象池足够轻量比仅创建对象便宜。您希望池足够大,以达到较高的命中率。

The problem you are likely to have is making the object pool light weight enough to be cheaper than just creating the objects. You want to the pool to be large enough that you get a fairly high hit rate.

根据我的经验,您可能在微基准测试方面遇到问题。当您在微基准测试中重复创建单个对象类型时,与在真实/复杂应用程序中创建各种对象相比,获得的结果要好得多。

In my experience, you are likely to have problems micro-benchmarking this. When you are creating a single object type repeatedly in a micro-benchmark, you get much better results than when creating a variety of objects in a real/complex application.

许多对象池方法的问题是它们:a)需要一个关键对象,这比创建一个简单的对象要花多少钱或更多,b)涉及一些同步/锁定,这又可能与创建一个对象一样多; c)需要一个额外的对象对象添加到缓存中时(例如Map.Entry),这意味着您的命中率必须要好得多,缓存才值得。

The problem with many object pool aproaches is that they a) require a key object, which costs as much or more than creating a simple object, b) involve some synchromization/locking which again can cost as much as creating an object c) require an extra object when adding to the cache (e.g. a Map.Entry), meaning your hit rate has to be much better for the cache to be worth while.

最轻的重量,但我知道愚蠢的缓存策略是使用带有哈希码的数组。

The most light weight, but dumb caching strategy I know is to use an array with a hashcode.

例如

private static final int N_POINTS = 10191; // or some large prime.
private static final Point[] POINTS = new Point[N_POINTS];

public static Point of(int x, int y, int z) {
    int h = hash(x,y,z); // a simple hash function of x,y,z
    int index = (h & 0x7fffffff) % N_POINTS;
    Point p = POINTS[index];
    if (p != null && p.x == x && p.y == y && p.z == z)
       return p;
    return POINTS[index] = new Point(x,y,z);
}

注意:该数组不是线程安全的,但是由于Point是不可变的,没关系缓存是在尽力而为的基础上进行的,并且自然采用了非常简单的驱逐策略来限制其大小。

Note: the array is not thread safe, but since the Point is immutable, this doesn't matter. The cache works on a best effort basis, and is naturally limited in size with a very simple eviction strategy.

出于测试目的,您可以添加命中/未命中计数器来确定数据集的缓存有效性。

For testing purposes, you can add hit/miss counters to determine the caches effectiveness for you data set.

这篇关于Java中小的不可变对象的缓存策略?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆