Problem Description:
A memory leak problem was discovered during a search, as shown in the figure:
Searched 15 times, the memory increased from 15MB to 18MB, which is quite serious.
Troubleshooting
After debugging and analysis, the approximate location of the problem was finally located:
function searchData() {
console.log('search');
var sc = {};
// 获取类名为fui-form下的所有mini控件,遍历将搜索条件形成下面的格式
// {
// "控件id":"控件值"
// }
mini.getChildControls(document.getElementsByClassName('fui-form')[0]).forEach(function (item) {
sc[item.id] = item.getValue();
});
console.log('搜索条件' + JSON.stringify(sc, 0, 4));
grid.load();
}
Comment out everything except grid.load()
. Search 0 times, 1 time, and 10 times. The results are as follows:
It can be seen that the memory does not grow as the number of memory searches increases, and there is no memory leak problem.
Then I thought it was a problem with console
, and commented out the two console
. The results are as follows (still searched 0 times, 1 time, and 10 times):
The problem remains. It can be seen that it is not a problem with the console. In fact, it is impossible to think about it. However, during the investigation, it was basically a case of emergency treatment.
The following can basically locate the problem caused by this paragraph.
var sc = {};
mini.getChildControls(document.getElementsByClassName('fui-form')[0]).forEach(function (item) {
sc[item.id] = item.getValue();
});
For analysis, the above can be split into two parts: obtaining the control array and traversing the organizational data
var sc = {};
var controls = mini.getChildControls(document.getElementsByClassName('fui-form')[0]);
controls.forEach(function (item) {
sc[item.id] = item.getValue();
});
After splitting the acquisition and traversal, and then testing, the problem no longer exists, as shown in the figure:
Final Question
Two ways to get the control and traverse it in the function
Writing method one:
// 获取并遍历
mini.getChildControls(document.getElementsByClassName('fui-form')[0]).forEach(function (item) {
sc[item.id] = item.getValue();
});
Writing method two:
// 获取控件
var controls = mini.getChildControls(document.getElementsByClassName('fui-form')[0]);
// 遍历
controls.forEach(function (item) {
sc[item.id] = item.getValue();
});
Why is there a memory leak in the first way, but not in the second way?
It is not necessarily a memory leak, it may be that gc has not recycled. In the first way of writing, the statement has not ended, and all doms need to be kept referenced. In the second point, the previous statement has ended, and it is possible that gc has recycled dom. Node, simply based on the number and time of your tests, you cannot determine whether the first way of writing is true and the dom will not be recycled in the end.
You should compare the data of 15.9 and 15.6. There is a comparison in the upper left corner of the table, which is the summary part in your picture. Compare what is more in 15.9 and 15.6. Click to see the yellow part, which represents Continuing references. If the memory still does not decrease after running it multiple times, it can be judged as a memory leak.