PJS를 이용해서 프로젝트를 진행하던중에 이상한 현상을 발견하게되었습니다.
게시판 페이징을 하면서 페이지번호 Element에 Event.observer를 할당하여 사용하고, Event가 필요없어지면 Event.stopObserving을 하는데, 여기서 메모리 누수가 발생하고 있었습니다.
일반적으로 생각하는건 아래와 같습니다.
1. 이벤트 설정 (Event.observe)
2. 이벤트 발생 (click...)
3. 이벤트 해지 (Event.stopObserving)
4. 이벤트 메모리 해지
하지만 4번이 제대로 되지 않는 현상이 발생하여 추적에 추적을 하였습니다(파이어버그 이용)
그랬더니 문제가 발생한 지점을 발견 이렇게 포스트하게 되었군요..ㅋㅋ
이벤트를 등록할때는 분명 _observeAndCache을 이용, observers 오브젝트에 이벤트관련 내용을 기록합니다. 허나, 이벤트를 삭제하는 stopObserving에서는 단순하게 이벤트를 삭제할뿐 observers 오브젝트에 기록한 이벤트 내용은 삭제하지 않고 계속 쌓아두고 오브젝트의 크기만을 늘리고 있었습니다.
물론 소스상에 unloadCache라는 것이 있어 observers 을 날려주고 있지만 이것을 기억하십시요.
unloadCache는 unload이벤트가 발생할때만 실행됩니다. 그러므로 Ajax를 통해 데이터를 받아오고 동적으로 이벤트를 Element에 설정했다면 unload이벤트는 발생하지도 않고 observers의 크기는 날로 커져만 갑니다. 이를 Prototype JS측에서는 알고 있는지 모르겠군요.
일단 제가 수정한 PrototypeJS의 소스는 아래와 같습니다.
//Fix to prototype's Event bug : Must decrease to Evnet.observers.length -> Memory leak
//Added by blankus [www.blankus.net] 2007 - 07 - 13
decreaseCache : function(elementId){
if (!Event.observers) return;
var tmp = [];
for (var i = 0, length = Event.observers.length; i < length; i++) {
//해당아이디의 이벤트를 삭제할때 observers의 내용에서도 해당아이디로 등록된 내용을 찾고,
//만약 같은 내용이 있다면 그것만을 제외하고 새로운 오브젝트에 담아 새로운 Event.observers를 생성
if(Event.observers[i][0]!=null && elementId != Event.observers[i][0].id) tmp.push(Event.observers[i]);
}
Event.observers = tmp;
}
stopObserving: function(element, name, observer, useCapture) {
element = $(element);
useCapture = useCapture || false;
if (name == 'keypress' &&
(Prototype.Browser.WebKit || element.attachEvent))
name = 'keydown';
if (element.removeEventListener) {
element.removeEventListener(name, observer, useCapture);
} else if (element.detachEvent) {
try {
element.detachEvent('on' + name, observer);
} catch (e) {}
}
//Added by blankus 2007 - 07 - 13
try{
this.decreaseCache(element.id);
}catch(e){}
}
posted by blakus
이 글의 트랙백 주소 :: http://www.blankus.net/trackback/20
.
2007/07/26 12:09
.
PJS를 이용해서 프로젝트를 진행하던중에 이상한 현상을 발견하게되었습니다.게시판 페이징을 하면서 페이지번호 Element에 Event.observer를 할당하여 사용하고, Event가 필요없어지면 Event.stopObservi...