缓存非常小的对象有什么用吗?

时间:2014-09-10 18:25:11

标签: java android caching

TaggedLogger只有一个字符串字段 - tag

public class TaggedLogger {

    private final String tag;

    public static TaggedLogger forInstance(Object instance) {
        return new TaggedLogger(getTagOfInstance(instance));
    }

    public static String getTagOfInstance(Object instance) {
        return getTagOfClass(instance.getClass());
    }

    public static TaggedLogger forClass(Class<?> someClass) {
        return new TaggedLogger(getTagOfClass(someClass));
    }

    public static String getTagOfClass(Class<?> someClass) {
        return someClass.getName();
    }

    public static TaggedLogger withTag(String tag) {
        return new TaggedLogger(tag);
    }

    private TaggedLogger(String tag) {
        this.tag = tag;
    }

    public void debug(Object obj) {
        Log.d(getTag(), String.valueOf(obj));
    }

    public String getTag() {
        return tag;
    }

    public void exception(String message) {
        Log.e(getTag(), String.valueOf(message));
    }

    public void exception(Throwable exception) {
        Log.e(getTag(), String.valueOf(exception.getMessage()), exception);
    }

    public void exception(Throwable exception, String additionalMessage) {
        Log.e(getTag(), String.valueOf(exception.getMessage()), exception);
        Log.e(getTag(), String.valueOf(additionalMessage));
    }

    public void info(Object obj) {
        Log.i(getTag(), String.valueOf(obj.toString()));
    }

}

TaggedLoggers用于缓存(或创建新的并放入缓存)TaggedLogger个实例:

public class TaggedLoggers {

    public static final TaggedLogger GLOBAL = getCachedWithTag("GLOBAL");

    private static final Map<String,TaggedLogger> cache = new HashMap<String, TaggedLogger>();

    public static TaggedLogger getCachedForInstance(Object obj) {
        return getCachedWithTag(TaggedLogger.getTagOfInstance(obj));
    }

    public static TaggedLogger getCachedForClass(Class<?> someClass) {
        return getCachedWithTag(TaggedLogger.getTagOfClass(someClass));
    }

    public static TaggedLogger getCachedWithTag(String tag) {
        TaggedLogger logger = cache.get(tag);
        if (logger == null) {
            logger = TaggedLogger.withTag(tag);
            cache.put(tag, logger);
        }
        return logger;
    }

}

TaggedLoggers班有什么用?

实际上我经常使用TaggedLogger来使用参数作为标记进行记录。即:

public class FragmentUtils {
    public static void showMessage(Fragment fragment, String message, int toastDuration) {
        TaggedLoggers.getCachedForInstance(fragment).debug(message);
        Context context = fragment.getActivity();
        if (context == null) {
            return;
        }
        Toast toast = Toast.makeText(context, message, toastDuration);
        toast.show();
    }
}

因此,缓存TaggedLogger实例实际上可以帮助我避免许多不必要的实例。

但是,我应该这样做吗?

2 个答案:

答案 0 :(得分:0)

创建和垃圾收集TaggedLogger几乎是免费的,因此缓存它们没有实际好处,但由于TaggedLoggers使用HashMap而不是ConcurrentHashMap如果两个线程试图同时调大地图的大小,那么如果从多个线程调用,那么很难调试问题,包括无限循环。

它几乎没有任何好处,会产生额外的复杂性,并可能产生问题。

另请参阅:A Beautiful Race Condition

答案 1 :(得分:0)

现有实例的缓存可以帮助很多或者可以杀死性能。

创建新实例时,您必须考虑两个因素:

  1. 设置实例本身的时间,即分配ram,初始化字段并执行构造函数
  2. 在实例无法再访问后,垃圾收集器清理所需的时间
  3. 以前在较旧的JVM上花了很多时间,而不是垃圾收集器已经改进,通常创建和丢弃小实例并不像以前那样是一个大问题,但仍然有它的成本。不知道究竟有多少Android JVM被优化了。

    在这种情况下,它取决于您创建和丢弃这些实例的频率,您经常说这些实例。

    当重新使用它们时,你必须考虑两个因素:

    1. 查找现有实例的时间,即地图查找
    2. 充满实际未使用的实例的ram
    3. 因此,在这种情况下,它取决于您拥有多少个不同的实例。如果你有成千上万的TaggedLogger,那么查看地图并将所有内容保留在ram中可能会比创建和丢弃更多地损害性能。

      如果TaggedLoggers大约是100,那么可能更好的缓存,如果它们进入数千,那么可能更好地实例化并扔掉。

      但是,我会问你是否需要TaggerLogger。如果你总是有标签String,你不能简单地调用logger方法或者只在它前面有一个(可能是静态的)façade,而不是只包含你已经拥有的信息(标签字符串)的实例吗?