bilibili / DanmakuFlameMaster

Android开源弹幕引擎·烈焰弹幕使 ~
http://app.bilibili.com/
Apache License 2.0
9.54k stars 2.1k forks source link

CacheManagingDrawTask 释放内存时为什么要wait(30) #389

Open yangzhiqian opened 5 years ago

yangzhiqian commented 5 years ago

hi,最近在研究弹幕库的源码,同时发现弹幕库在弹幕密度比较大的时候,会出现卡顿非常严重的问题。 我这边分析发现卡顿时,缓存线程(CacheManagingDrawTask中的CacheHandler)几乎停止工作,后来发现其中有下面一段感觉比较疑惑的代码:

private void clearTimeOutCaches() { mCaches.forEach(new IDanmakus.DefaultConsumer<BaseDanmaku>() { @Override public int accept(BaseDanmaku val) { if (val.isTimeOut()) { IDrawingCache<?> cache = val.cache; if (mContext.cachingPolicy.periodOfRecycle == CachingPolicy.CACHE_PERIOD_NOT_RECYCLE && cache != null && !cache.hasReferences()) { if (cache.size() / (float) mMaxCacheSize < mContext.cachingPolicy.forceRecyleThreshold) { return ACTION_CONTINUE; } //else 回收尺寸过大的cache } if (!mEndFlag) { synchronized (mDrawingNotify) { try { Log.d("bbbbbbbbbbbbbbbbbb","sleep = "+ 30);//提问者添加的测试log mDrawingNotify.wait(30); } catch (InterruptedException e) { e.printStackTrace(); return ACTION_BREAK; } } } entryRemoved(false, val, null); return ACTION_REMOVE; } else { return ACTION_BREAK; } } }); }

该代码会在缓存空间占用比较大的情况下调用以释放内存空间。 但其中的 mDrawingNotify.wait(30);很是让人疑惑。查看修改记录,该段代码是在2013/12/28号提交的,log显示是为了减少gc的次数。但引入该段代码,会造成弹幕缓存供应比较慢。此时弹幕绘制会直接在canvas上绘制(因为没有对应的缓存),这样的绘制速度远远比原来的绘制慢得多,导致卡顿严重。

我这边实验,在高密度的弹幕情况下,出现“bbbbbbbbbbbbbbbbbb“ log打印时同时出现卡顿。 如果将wait的逻辑去掉,这边发现弹幕在高密度情况下依然比较流畅。

想问一下,当时加上这段逻辑时是出现了怎样的问题(感觉gc影响不是主要问题)。谢谢

yangzhiqian commented 5 years ago

我的想法是把wait那一段去除掉,但担心有其他问题出现,因为当时看是特意加上去的。

RottenOnion commented 3 years ago

我的想法是把wait那一段去除掉,但担心有其他问题出现,因为当时看是特意加上去的。

请问后面后好的解决方案吗?

yangzhiqian commented 3 years ago

我的想法是把wait那一段去除掉,但担心有其他问题出现,因为当时看是特意加上去的。

请问后面后好的解决方案吗?

我提了mr,但没有准入,后面我将代码提到自己的fork仓库,加上这段逻辑。同时,基于之前自学了地点OpenGL的知识,添加了一个底层用OpenGL渲染的功能(绘制在子线程):https://github.com/yangzhiqian/DanmakuFlameMaster