Safari에서 Indexed DB의 IDBCursor.onsuccess 인수 메모리 문제
개요
Safari에서 Indexed DB를 사용할 때 IDBCursor의 onsuccess 콜백 인수 속성 target.result를 참조하면 null이 아닌 경우 특수 메모리 누수가 발생했습니다.
상기 조건하에서 브라우저 페이지를 리로드했을 경우, javascript 오브젝트가 좀비화해 메모리 영역에 남아 계속한다.
객체는 재로드 횟수에 따라 계속 증가하기 때문에 메모리 압축에 의한 브라우저 페이지 충돌을 일으킬 수 있습니다.
Chrome에서는 이 현상을 확인할 수 없었다.
이 현상은 이미 Apple Bug Reporter를 통해보고되었습니다.
현상을 확인한 환경
검증
검증을 위한 샘플 코드.
// 正常に indexed db が接続できているとする
var transaction = openRequest.result.transaction([storeName], 'readwrite');
var store = transaction.objectStore(storeName);
// 何かレコードを保存していないと、後述のプロパティが null となる
store.put(key, 1);
store.openCursor().onsuccess = function(e) {
// 1. e.target.result が null の場合
// var result = e.target.result;
// 2. e.target.result が null ではない場合
// var result = e.target.result;
// 3. e.target の参照のみ行う
// var target = e.target;
// 4. e.target の参照のみだが関数内で展開
// console.log(e.target);
};
결과
case
결과
1. e.target.result가 null의 경우
리로드로 인한 누출은 발생하지 않음
2. e.target.result가 null가 아닌 경우
재장전으로 누출
3. e.target 참조만 수행
리로드로 인한 누출은 발생하지 않음
4. e.target 참조 만 함수 내에서 확장
재장전으로 누출
고찰
통상의 Web 페이지/서비스라면에 대해서 문제가 되기 어렵지만, 큰 바이너리등을 취급하는 페이지의 경우는 크래쉬의 리스크가 높다.
메모리 해제 수단으로서 페이지의 리로드가 행해지는 경우도 있지만, 이 문제가 발생하는 조건 하에서는 역효과이다.
대응 방법 (잠정)
커서의 용도는 몇 가지 있지만, 모든 레코드를 반복할 가능성이 있는 처리를 실시한다고 가정하면, getAllKeys
및 getAll
가 대체가 된다.getAll
등은 indexeddb2 의 사양이며, 비교적 새로운 버젼의 브라우저로만 서포트되고 있다.
W3C
htps //w w. w3. rg / TR / 어서 dB-2 /
caniuse
htps // 게으세요. 코 m / # 훗아 t = 어서 db2
대응 예 1
var allKeys;
var allValues;
objectStore.getAllKeys().onsuccess = (event) => {
allKeys = event.target.result;
};
objectStore.getAll().onsuccess = (event) => {
allValues = event.target.result;
};
...
for (var i = 0; i < allKeys.length; i++) {
const key = allKeys[i];
const val = allValues[i];
doSomething(key, value);
}
이 대응 문제
// 正常に indexed db が接続できているとする
var transaction = openRequest.result.transaction([storeName], 'readwrite');
var store = transaction.objectStore(storeName);
// 何かレコードを保存していないと、後述のプロパティが null となる
store.put(key, 1);
store.openCursor().onsuccess = function(e) {
// 1. e.target.result が null の場合
// var result = e.target.result;
// 2. e.target.result が null ではない場合
// var result = e.target.result;
// 3. e.target の参照のみ行う
// var target = e.target;
// 4. e.target の参照のみだが関数内で展開
// console.log(e.target);
};
커서의 용도는 몇 가지 있지만, 모든 레코드를 반복할 가능성이 있는 처리를 실시한다고 가정하면,
getAllKeys
및 getAll
가 대체가 된다.getAll
등은 indexeddb2 의 사양이며, 비교적 새로운 버젼의 브라우저로만 서포트되고 있다.W3C
htps //w w. w3. rg / TR / 어서 dB-2 /
caniuse
htps // 게으세요. 코 m / # 훗아 t = 어서 db2
대응 예 1
var allKeys;
var allValues;
objectStore.getAllKeys().onsuccess = (event) => {
allKeys = event.target.result;
};
objectStore.getAll().onsuccess = (event) => {
allValues = event.target.result;
};
...
for (var i = 0; i < allKeys.length; i++) {
const key = allKeys[i];
const val = allValues[i];
doSomething(key, value);
}
이 대응 문제
getAllKeys
및 getAll
의 결과 ( event.target.result
)의 순서가 보장된다고 가정합니다 대응 예 2
var allKeys;
objectStore.getAllKeys().onsuccess = (event) => {
allKeys = event.target.result;
};
...
for (var i = 0; i < allKeys.length; i++) {
const key = allKeys[i];
objectStore.get(key).onsuccess = (event) => {
const value = request.result;
doSomething(key, value);
};
}
이 대응 문제
덤
처음 보았을 때는 끌었다.
window는 좋지만, 그 아래의 ArrayBuffer, AudioBuffer가 위험하다.
Reference
이 문제에 관하여(Safari에서 Indexed DB의 IDBCursor.onsuccess 인수 메모리 문제), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/smith/items/16d48083fe7a7e4b70ee
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Safari에서 Indexed DB의 IDBCursor.onsuccess 인수 메모리 문제), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/smith/items/16d48083fe7a7e4b70ee텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)