safari(iOS12)에서 "Total canvas memory use exceeds the maximum limit"가 나오는 경우의 대처법
전치
phina.js에서 상당히 큰 이미지를 대량으로 처리하는 응용 프로그램을 만들고 있었지만, iOS12의 safari에서 테스트했을 때,
"Total canvas memory use exceeds the maximum limit(288MB)"
라는 경고가 이미지를 읽을 때 발생합니다.
이 경고가 발생하고 나서 getContext('2d')를 실행하면 반드시 null가 돌려주어, 그 이후 canvas로부터 context의 취득을 할 수 없게 되어 버립니다.
288MB의 부분은 기종에 따라서는 255MB라고 하는 것 같습니다(iPhone X는 288MB)
번역하면 "총 캔버스 메모리 사용량이 상한을 초과하고 있습니다"라는 것.
검색해 보면, stackoverflow 에서 외인씨가 같은 현상으로 곤란하고 있었습니다.
친절한 일에 테스트 코드까지 붙여주고 있습니다.
아래 코드가 그것입니다 (일부 변경 중)
let ctxs = []
let counter = 0
// create a 1MB image
const createImage = () => {
const size = 512
const canvas = document.createElement('canvas')
canvas.height = size
canvas.width = size
const ctx = canvas.getContext('2d')
ctx.strokeRect(0, 0, size, size)
return canvas
}
const createImages = n => {
// create n * 1MB images
for(let i = 0; i < n; i++ ){
const canvas = createImage()
ctxs.push(canvas)
}
console.log(`done for ${ctxs.length} MB`)
}
512x512에서 1MB입니다. 처음 알았습니다.
이 코드를 safari의 디버그 콘솔에 붙여 테스트 할 수 있습니다.
시도해 createImages(288)를 실행한 다음 createImages(1)을 실행하면
역시 같은 경고와 에러가・・・
조사해 보면
iOS11 이전에는 2151MB까지 확보가 된 것 같습니다 (손님의 iPhone7 (iOS11) 조사)
그것이 iOS12부터는 288MB.
좀 더 조사해 보면, WebKit의 리포지토리에 기술이 있어, iOS12로부터 canvas의 최대 사용량이 RAM 사이즈의 1/4로 축소된 모양입니다.
htps : // 기주 b. m / u b t / u b t / th t / 5d5b478917c685 e 50d1032-cf761 또는 53fc8f1b74 # ぢ fb411cd4839 4bc17b00570536
불필요한 일이 끝나고
애초에 iOS11까지는 2분의 1이 아닌 것 같아요.
처음에는 safari의 버그가 아닐까 생각하고 방치 향후의 업데이트로 고쳐지지 않을까라고 생각했는데, 소망이 얇을 것 같아서, 이 메모리량으로 해줄 수 밖에 없습니다.
우선, 지금까지 사용해서는 그대로 하고 있던 캔버스를 해방해 메모리를 절약해 갑시다.
그렇다면 풀어주세요.
브라우저에서는 메모리의 해방을 수동으로 할 수 없기 때문에, delete 명령등으로 오브젝트의 참조를 끊고, 나머지는 신의 보이지 않는 손(GC)에 의지할 수밖에 없습니다.
더 이상 필요하지 않은 캔버스를 삭제 캔버스로 삭제해보십시오.
const deleteImages = () => {
for( let i = 0; i < ctxs.length; i++ ){
delete ctxs[i];
}
ctxs = [];
}
이것으로 괜찮습니다 ...
GC가 움직인다고 말했구나. 그건 거짓말이다.
delete해도, null를 대입해도, 참조는 끊어지고 있는데, canvas의 총 메모리로서는 카운트된 채로의 모양입니다.
어떻게 할까 생각하고 괴로워하고 혼잡하게 시도한 것이 다음의 방법입니다.
const deleteImages = () => {
for( let i = 0; i < ctxs.length; i++ ){
ctxs[i].width = 0;
ctxs[i].height = 0;
delete ctxs[i];
}
ctxs = [];
}
delete 전에 canvas의 width와 height를 0으로 한 것.
이것으로 좋은 것일까, 라고 생각하는 것 같은 해결 방법.
아마 캔버스에만 한정된 이야기라면 delete도 필요 없잖아.
해결했지만
우선의 방법이므로, 이것이 올바르게 안전한 방법이라고는 생각되지 않습니다.
stackoverflow로 곤란했던 외인씨에게도 전했는데, 이 방법으로 문제의 해결을 할 수 있었던 모양으로, 아무튼 잘못되어 있지 않은 것 같습니다.
뭔가 알고 있는 친절한 분이 있으면, 코멘트로 가르쳐 주면 매우 고맙습니다.
Reference
이 문제에 관하여(safari(iOS12)에서 "Total canvas memory use exceeds the maximum limit"가 나오는 경우의 대처법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/minimo/items/b724c6793f45aca5e6f5
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
let ctxs = []
let counter = 0
// create a 1MB image
const createImage = () => {
const size = 512
const canvas = document.createElement('canvas')
canvas.height = size
canvas.width = size
const ctx = canvas.getContext('2d')
ctx.strokeRect(0, 0, size, size)
return canvas
}
const createImages = n => {
// create n * 1MB images
for(let i = 0; i < n; i++ ){
const canvas = createImage()
ctxs.push(canvas)
}
console.log(`done for ${ctxs.length} MB`)
}
const deleteImages = () => {
for( let i = 0; i < ctxs.length; i++ ){
delete ctxs[i];
}
ctxs = [];
}
const deleteImages = () => {
for( let i = 0; i < ctxs.length; i++ ){
ctxs[i].width = 0;
ctxs[i].height = 0;
delete ctxs[i];
}
ctxs = [];
}
Reference
이 문제에 관하여(safari(iOS12)에서 "Total canvas memory use exceeds the maximum limit"가 나오는 경우의 대처법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/minimo/items/b724c6793f45aca5e6f5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)