Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug反馈: 在pro8.8上存在内存溢出的日志 #497

Open
xzhlksh opened this issue Jul 14, 2021 · 11 comments
Open

Bug反馈: 在pro8.8上存在内存溢出的日志 #497

xzhlksh opened this issue Jul 14, 2021 · 11 comments
Labels
Accepted 🌱 受理 Maintainer may be busy resolving or fixing the labeled issues Doubt 🛡️ 疑惑 Any doubts about this repository Reinforcement ✨ 强化 Issues for higher quality of being compatible

Comments

@xzhlksh
Copy link

xzhlksh commented Jul 14, 2021

问题描述
在AJ Pro8上有看到内存溢出的日志,虽说暂时不会真的挂掉,但是总看着闹心。不知道根据日志能不能少溢出一点?

日志截图
1626275419245

软件硬件信息
操作系统: Android 11 MIUI 12.5
设备型号: 小米10Pro
Auto.js版本: Pro8.8
项目版本: 2.1.5

其他
另外,不知道为什么,我的机子上无论是411还是pro8,都只能点亮屏幕而不能解锁。隔壁的蚂蚁森林脚本却能解锁

@xzhlksh xzhlksh added the Bug 🐞 故障 Confirmed bugs or reports that are very likely to be bugs label Jul 14, 2021
@SuperMonster003
Copy link
Owner

暂时无法解决
因为项目需要手动进行截图回收
所以必须复制一份
否则 Auto.js 默认会回收上一次的截图 (除非间隔很短被判断为相同截图)
你可以看一下发生泄漏的代码位置
其实跟在后面就能看到手动回收的代码

但警告日志暂时没有办法去除或 suppress 掉
更不能通过try/catch代码块捕获

此 issue 将标记为 '无法完成'

@SuperMonster003 SuperMonster003 added Doubt 🛡️ 疑惑 Any doubts about this repository Helpless 🥀 无法完成 Issues can not be solved by the maintainer (Issues will be closed within one month) Accepted 🌱 受理 Maintainer may be busy resolving or fixing the labeled issues Reinforcement ✨ 强化 Issues for higher quality of being compatible and removed Bug 🐞 故障 Confirmed bugs or reports that are very likely to be bugs Helpless 🥀 无法完成 Issues can not be solved by the maintainer (Issues will be closed within one month) labels Jul 16, 2021
@SuperMonster003
Copy link
Owner

目前已找到可能的解决方案
将在下一版解决上述问题

@jobinli
Copy link

jobinli commented Jul 23, 2021

内存泄漏似乎挺严重的。我测试了下,打开autojs后占用是300+M的,运行两次后去到了900+

@xzhlksh
Copy link
Author

xzhlksh commented Aug 6, 2021

那我找aj的作者再问问,多谢回复

@xzhlksh
Copy link
Author

xzhlksh commented Aug 7, 2021

我看了一下内存泄露的位置,貌似ext_image模块里面的capt函数里的 _copy局部变量因为不是captureScreen方法存放image,并且要被return,所以没有办法对该变量进行手动内存回收?

这个问题我尝试在ext_image开头用let声明了一个全局变量并赋值为null,然后在capt()函数中把所有_copy替换为该全局变量。同时每次进入capt()函数以后都先判断这个全局变量是否为null(或者判断是否为ImageWrapper),如果非null(或者为ImageWrapper)则执行一次recycle内存回收,再执行原有语句和逻辑。另外在this.reclaim之后也对_capt执行一次内存回收。

另外_chkByImgTpl()函数中_capt没有执行recycle();
_thdOcr()函数4727行存在_capt = _clip = _stitched = null;语句,也都没有执行recycle()?
我看这两处也报了内存溢出,也都私改了一下加上了recycle()。

这么一通乱操作后,再执行回收能量球的任务时,能正常采集能量,log里也没有内存溢出的日志了,不知道是不是真的不会溢出了。我明天早上高强度持续收能量的时候再测一下私改代码后的效果。

@xzhlksh
Copy link
Author

xzhlksh commented Aug 8, 2021

难受了,ext-image里还有几个lambda函数里也有类似的内存溢出。

大概知道内存溢出的意思了,就是小函数里获取到图片,但是没有释放就直接return。实际执行return操作的时候,内存中并没有释放image资源,只是copy了一份返回给函数调用者。因此在函数调用者里执行recycle只回收了copy,并不能完全避免内存泄露。
解决方案也不是没有,就是给所有return image资源的函数里都分配一个全局变量,把image赋值给这个全局变量再把这个全局return掉,以后每次进函数前对该全局变量做类型判断以后再recycle。最后退出脚本的时候再对这些全局变量最后做一次recycle。

不知道我理解的对不对?毕竟我平时干活只写cpp和py代码,js只能看懂简单语法。。。

@SuperMonster003
Copy link
Owner

v2.1.7 已尝试解决上述内存溢出问题

如问题复现 可继续反馈

关于内存溢出可能的解决方案及此次更新相关的代码改动 将在本周四之后在当前issue下作出答复

@xzhlksh
Copy link
Author

xzhlksh commented Aug 22, 2021

感觉这几版以后,没再遇到内存溢出导致收能量挂掉的问题了

@SuperMonster003
Copy link
Owner

SuperMonster003 commented Aug 27, 2021

images.captureScreen() 创建一个 ImageWrapper
这个 ImageWrapper 会在下一次调用 captureScreen 时被自动回收

images.requestScreenCapture();
let capt_1 = images.captureScreen();
console.log(capt_1.getHeight()); // a certain number
let capt_2 = images.captureScreen();
console.log(capt_2.getHeight()); // a certain number
console.log(capt_1.getHeight()); // exception with "image has been recycled"

项目主要在两个地方需要破除上述限制

  1. 排行榜页面样本池
  2. 森林页面样本池

两个样本池都需要在一定时间内获取多个屏幕截图
用于差异比较或样本分析

早期项目采用了 images.copy() 的方式

images.requestScreenCapture();
let capt_1 = images.copy(images.captureScreen());
console.log(capt_1.getHeight()); // a certain number
let capt_2 = images.copy(images.captureScreen());
console.log(capt_2.getHeight()); // a certain number
console.log(capt_1.getHeight()); // a certain number

这样避免 ImageWrapper 实例被自动回收
但必须在使用完毕后手动回收 否则会造成内存泄漏

capt_1.recycle();
capt_2.recycle();

早期项目采用了所有 imagesx.capt() 都返回 images.copy() 后的对象
造成大量使用 imagesx.capt() 后的代码中不可避免存在忘记手动回收的问题
同时也浪费了很多系统资源 (主要在于 Bitmap 的创建开销)

Pro 的内存泄漏跟踪会显示详细的 stack
根据 stack 可以跟踪到需要添加手动回收的地方
因此一开始的优化方向就是补充所有可能遗漏的 capt.recycle()
但这样并没有解决资源开销问题

images.captureScreen() 的自动回收其实可以很好地解决资源开销
因此优化方向改为只有在必要的时候使用 images.copy()
很多 images 方法接受一个或多个 ImageWrapper 作为参数
例如

function matchTemplate(img: ImageWrapper$, template: ImageWrapper$, options?: {
    threshold?: number,
    weakThreshold?: number,
    level?: number,
    region?: [X?, Y?, Width?, Height?],
    max?: number,
}): Autojs.MatchingResult;

通常 img 会传入屏幕截图
template 会传入 clip 或 从本地等处读取的图片 或 由 base64 编码转换的图片等
此时 img 不必手动回收 也不必关心何时会回收
但要注意 template 通常需要手动回收
同样的方法还包括以下几种

function findImage(img: ImageWrapper$, template: ImageWrapper$, options?: {
    threshold?: number, weakThreshold?: number, level?: number,
    region?: [X?, Y?, Width?, Height?]}): org.opencv.core.Point;

function findImageInRegion(image: ImageWrapper$, template: ImageWrapper$, x?: X, y?: Y,
    width?: Width, height?: Height, threshold?: number): org.opencv.core.Point;

function concat(img1: ImageWrapper$, img2: ImageWrapper$,
    direction?: "LEFT" | "RIGHT" | "TOP" | "BOTTOM"): ImageWrapper$;

另外如果脚本提前停止或异常终止
项目中的手动回收代码没有来得及运行
也会造成内存泄漏
此时 Auto.js 不会立即提示泄漏
而会在下次运行脚本时提示
容易引起是当前运行脚本时出现内存泄漏的错觉

下一版项目将采用 images 对象池的方案
跟踪记录每一个需要手动回收的 ImageWrapper 实例
在用户按下音量键或脚本正常结束之前对对象池的实例做遍历回收
从而减少上述现象的发生概率

最后来一个简单的小 puzzle
为什么下面的代码不能成功运行
如果想判断 0.5 秒内屏幕截图是否发生变化
应该怎样修改代码

images.requestScreenCapture();
let _capt = images.captureScreen();
let _template = (sleep(500), images.captureScreen());
console.log(images.matchTemplate(_capt, _template).matches.length === 0);

@fan0629
Copy link

fan0629 commented Sep 5, 2021

1630812038981
1630812697050
1630813307116

貌似还是会有内存泄漏的问题,重启进程后Runtime Heap和Process Heap都是3%左右,每运行一次就增加一点,直到内存溢出Auto.js卡死,这里大概运行了50次。 # @SuperMonster003

软件硬件信息
操作系统: Android 11 MIUI 12.5
设备型号: 红米k20 pro
Auto.js版本: 4.1.1 Alpha2
项目版本: 2.1.10

@xzhlksh
Copy link
Author

xzhlksh commented Sep 12, 2021

同楼上,2.1.10版本内存溢出又回来了。。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted 🌱 受理 Maintainer may be busy resolving or fixing the labeled issues Doubt 🛡️ 疑惑 Any doubts about this repository Reinforcement ✨ 强化 Issues for higher quality of being compatible
Projects
None yet
Development

No branches or pull requests

4 participants