与番石榴缓存在Android上糟糕表现 [英] Bad performance with Guava Cache on Android

查看:191
本文介绍了与番石榴缓存在Android上糟糕表现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用装载谷歌番石榴LoadingCache位图在Android应用程序。在应用程序我运行一个绘图线程,用于绘制的位图缓存到画布。如果一个特定的位图不是在缓存中,它不会绘制使得没有负载永远不会阻止该图螺纹

We use a loading Google Guava LoadingCache for bitmaps in an Android application. In the application I am running a drawing Thread, that paints the bitmaps in the cache to a Canvas. If a specific bitmap is not in the cache, it does not get drawn so that no loading will ever block the drawing Thread.

然而,这幅画引起视觉口吃和每秒速率帧不是我们怎么会喜欢它。我钉下来到缓存中的 getIf present()方法。这本身就需要的应用程序超过20%的总的CPU时间。在 getIf present() LocalCache $ Segment.get()花费的时间超过80%:

However, the painting results in visual stuttering and the frames per second rate is not how we would like it. I nailed it down to the getIfPresent() method of the cache. That alone takes over 20% of the applications total CPU time. In getIfPresent() LocalCache$Segment.get() takes over 80% of the time:

记住,这是一个已经present位图的只是一个查询。这里绝对不会发生在得到一个负载()。我想会有的的get()簿记开销的LRU队列决定哪些驱逐发生,如果段已满。但是,这是规模的慢至少一个数量级有什么键入查找 LRU-LinkedHashmap.get()会给我。

Bear in mind, this is only a lookup of an already present bitmap. There will never happen a load in get(). I figured there would be a bookkeeping overhead in get() for the LRU queue that decides which eviction takes place if the segment is full. But this is at least an order of magnitude slower of what a Key-Lookup in LRU-LinkedHashmap.get() would give me.

我们使用缓存得到快速查找一个元素是否在高速缓存中,如果该查找是缓慢的,有在其高速缓存没有意义的。我也试过 GETALL present(一) asMap(),但它给了相同的性能。

We use a cache to get fast lookups if an element is in the cache, if the lookup is slow, there is no point in caching it. I also tried getAllPresent(a) and asMap() but it gives equal performance.

库的版本是:番石榴11.0.1.jar

LoadingCache定义如下:

LoadingCache is defined as follows:

LoadingCache<TileKey, Bitmap> tiles = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader<TileKey,Bitmap>() {
            @Override
            public Bitmap load(TileKey tileKey) {
            System.out.println("Loading in " + Thread.currentThread().getName() + " "
                + tileKey.x + "-" + tileKey.y);

            final File[][] tileFiles = surfaceState.mapFile.getBuilding()
                .getFloors().get(tileKey.floorid)
                .getBackground(tileKey.zoomid).getTileFiles();
            String tilePath = tileFiles[tileKey.y][tileKey.x].getAbsolutePath();

            Options options = new BitmapFactory.Options();
            options.inPreferredConfig = Bitmap.Config.RGB_565;

            return BitmapFactory.decodeFile(tilePath, options);
            }
        });

我的问题是:

  • 请我用错了?
  • 是它的实现unsutible Android版
  • 在我错过了一个配置选项?
  • 这是一个已知的问题与正在被制作的缓存?

更新:

在约100帧画的CacheStats是:

After about 100 frames painted the CacheStats are:

I/System.out( 6989): CacheStats{hitCount=11992, missCount=97,
loadSuccessCount=77, loadExceptionCount=0, totalLoadTime=1402984624, evictionCount=0}

之后missCount保持basicly一样hitCount增量。在这种情况下,高速缓冲存储器是足够大的载荷发生疏,但getIf present缓慢nontheless

After that missCount stays basicly the same as hitCount increments. In this case the cache is big enough for loads to happen sparsely, but getIfPresent is slow nontheless.

推荐答案

CacheBuilder 是专为服务器端缓存,其中并发性是首要关注的问题。因此,权衡,以换取更好的多线程特性单线程和内存开销。 Android开发者应该使用 LruCache 的LinkedHashMap 或类似的地方单线程性能和存储器是主要的顾虑。在未来有可能是一个concurrencyLevel = 0时,表示一个轻便,非并发缓存是必需的。

CacheBuilder was designed for server-side caching, where concurrency was a primary concern. It therefore trades off single-threaded and memory overhead in exchange for better multi-threaded behavior. Android developers should use LruCache, LinkedHashMap, or similar where single-threaded performance and memory are the primary concerns. In the future there may be a concurrencyLevel=0 to indicate that a lightweight, non-concurrent cache is required.

这篇关于与番石榴缓存在Android上糟糕表现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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