Rev. 2.73

HTML :

<script type="text/javascript" src="prototype.js"></script> 
<script type="text/javascript" src="Sly.js"></script> 

Javascript :

// Overriding CSS Selector Engine.
Sly.handlers = Selector.handlers;
Sly.prototype.findElements = Sly.prototype.search;
Sly.findElement = function(elements, expression, index) {
  if (Object.isNumber(expression)) {
    index = expression; expression = false;
  }
  return Sly(expression || '*').filter(elements)[index || 0];
};
Sly.findChildElements = function(element, expressions) {
  var result = Sly(expressions.join(',')).search(element);
  return Prototype.BrowserFeatures.ElementExtensions ?
    result : result.filter(Element.extend);
};
Selector = Sly;

Prototype의 성능이 다른 프레임웍들에 비해 떨어지는 주된 원인 중 하나는 DOM 셀렉터(Selector) 엔진에 있는 것으로 판단하고 위와 같은 코드를 작성하여 Prototype의 셀렉터 엔진을 더욱 성능이 좋은 Sly로 교체하는데 성공하였습니다. 그리고 SlickSpeed를 이용하여 실험하였는데, 그 결과가 매우 만족스럽습니다. 오옷! jQuery 와 비등비등하거나 더 빠르군요! 특히, 파이어폭스 3.0에서는 날아 다닙니다. 푸하핫!

My SlickSpeed Result :

  • Internet Explorer 8 : 2.5x faster
  • Internet Explorer 7 : 1.4x faster
  • Internet Explorer 6 : 1.6x faster
  • Mozilla Firefox 3.5 : 1.7x faster
  • Mozilla Firefox 3.0 : 8.7x faster
  • Mozilla Firefox 2.0 : 6.2x faster
  • Google Chrome 2.0 : 1.4x faster
  • Google Chrome 1.0 : 1.2x faster
  • Apple Safari 4.0 : 1.9x faster
  • Apple Safari 3.2 : 1.5x faster
  • Opera 9.6 : 4.7x faster

Comments

Got something to add? You can just leave a comment.

  • THEPAPER THEPAPER

    좋은 방법이네요. 저도 한 번 해 볼 생각으로 해 보니 Prototype으로 구성된 스크립트에서 Class.create() 부분에서 Class를 인식 못하는 문제가 발생 하네요.

    reply edit

  • Class.create와는 연관성이 전혀 없는 코드입니다. Sly쪽 코드도 살펴 보았으나 Class를 건드리는 코드는 없던데요?

    reply edit

  • THEPAPER THEPAPER

    아... 저도 이상하다 싶어서 다시 보니 jQuery와 Prototype을 같이 쓰는 경우이다 보니 이런 현상이 나는듯 하네요. 대략적으로,

    <script type="text/javascript" charset="utf-8" src="Prototype/1.6.0.3/prototype.js"></script>
    <script type="text/javascript" charset="utf-8" src="Sly/1.0rc1/Sly.js"></script>
    <script type="text/javascript" charset="utf-8" src="jQuery/1.3.2/jquery.js"></script>
    <script type="text/javascript" charset="utf-8">
    //<![CDATA[
    var $J = jQuery.noConflict();
    //]]>
    </script>

    이런 상황에서 위 코드를 사용하니 Class가 정의되지 않았다고 나옵니다.

    reply edit

  • /examples/prototype-sly-jquery.html

    위 코드를 확인해 보세요.

    reply edit

  • pRix pRix

    Prototype의 Selector ($$) 사용시 단순히 셀렉터만 수행되는게 아니라
    가져온 모든 Element에 Prototype의 확장 메서드 (Element 객채의 메서드)들이 복사되며 그로인해서
    $('div')[0].hide() 라던가 $('div').invoke('hide') 같은 명령이 사용가능합니다.
    위의 방법처럼 Sly를 사용하여 Selector객채를 오버라이드 한다면 SlickSpeed에서는 테스트가 가능하나
    실제 사용하는데는 문제가가 있다고 생각되네요.

    reply edit

  • 이 코드는 실제로 이 블로그에 적용되어 사용되고 있으며 약 5일간의 테스트를 거치는 동안 아무런 문제를 발견하지 못하고 있습니다. 저 역시 말씀하신 부분아 걱정되는 부분이었습니다만, IE7을 포함한 이하의 브라우저에서 Element메서드 확장을 위한 Element.extend는 위 코드만으로도 잘 소화하고 있는 것으로 보입니다. Element#method를 테스트해 보시려면 http://taskspeed.firejune.com 에서 확인해 보세요. taskspeed에 사용되는 prototype.js 역시 sly의 css엔진을 사용하고 있는 것입니다.

    reply edit

  • pRix pRix

    아하 Sly의 filter를 사용하여 extend를 사용하도록 되었군요. 이부분 코드를 제가 놓쳤네요 ㅎㅎ
    invoke등의 배열매서드는 Array.prototype으로 확장되니 문제가 없을 것 같고 기존방법보다
    확실히 효율이 더 좋을 것 같습니다!
    괜한 딴지를 건 느낌에 죄송스럽네요 엉엉 ㅡ_ㅜ

    그리고 도움이 됐으면 하는 마음에 코드를 열심히 보다보니 발견한건데
    extend의 결정조건문을 브라우져 체크보다는
    Prototype.BrowserFeatures.ElementExtensions 의 블린값을 이용해보는게 어떨까요?

    reply edit

  • 딴지라니요, 덕분에 더 좋은 코드를 얻을 수 있었는 걸요! 간만에 수준있는 대화를 나눈 느낌입니다. 알려주신데로 수정하도록 하겠습니다. 사실 저는 루프 한번 줄여보려고 Sly에 Eelement#extend를 직접 때려넣고 쓰고 있답니다.

    reply edit

  • THEPAPER THEPAPER

    아... 답변 정말 감사드립니다. 문제는 엉뚱한 곳에 있었네요.

    <script type="text/javascript" charset="utf-8" src="Prototype/1.6.0.3/prototype.js"></script>
    <script type="text/javascript" charset="utf-8" src="Sly/1.0rc1/Sly.js"></script>
    <script type="text/javascript" charset="utf-8" src="jQuery/1.3.2/jquery.js"></script>
    <script type="text/javascript" charset="utf-8">
    //<![CDATA[
    var $J = jQuery.noConflict();
    Sly.handlers = Selector.handlers;
    Sly.prototype.findElements = Sly.prototype.search;
    Sly.findElement = function(elements, expression, index) {
    if (Object.isNumber(expression)) {
    index = expression; expression = false;
    }
    return Sly(expression || '*').filter(elements)[index || 0];
    };
    Sly.findChildElements = function(element, expressions) {
    var result = Sly(expressions.join(',')).search(element);
    return Prototype.BrowserFeatures.ElementExtensions ?
    result : result.filter(Element.extend);
    };
    Selector = Sly;
    //]]>
    </script>

    이 이후에
    <script type="text/javascript" charset="utf-8" src="_CORE/global.js"></script>
    이렇게 되어 있다보니 브라우저가 로딩하는 과정에서 에러가 나는 것이더군요.

    그래서 일단,

    var $J = jQuery.noConflict();
    Sly.handlers = Selector.handlers;
    Sly.prototype.findElements = Sly.prototype.search;
    Sly.findElement = function(elements, expression, index) {
    if (Object.isNumber(expression)) {
    index = expression; expression = false;
    }
    return Sly(expression || '*').filter(elements)[index || 0];
    };
    Sly.findChildElements = function(element, expressions) {
    var result = Sly(expressions.join(',')).search(element);
    return Prototype.BrowserFeatures.ElementExtensions ?
    result : result.filter(Element.extend);
    };
    Selector = Sly;

    이 부분 전체를 global.js에 포함시켜버렸습니다.

    reply edit

  • 오옷! 저의 코드를 활용해 주시는군요. ㅠ.ㅠ

    reply edit

  • THEPAPER THEPAPER

    이렇게나 좋은 방법을 공개해 주셨는데 잘 써먹어여죠! 정말 감사드립니당~
    주석에 출처도 잘~ 써 놨습니다. :)

    reply edit

Your Reaction Time!

captcha

avatar