Loading ...
Sorry, an error occurred while loading the content.

slice method appears slower in loops than incrementally listing array indexes

Expand Messages
  • Cheney, Edward A SSG RES USAR
    Group, I am trying to figure out why slice appears to be slower when executed upon a large string than merely pointing to a group of indexes. My presumption
    Message 1 of 5 , Sep 3, 2010
    View Source
    • 0 Attachment
      Group,

      I am trying to figure out why slice appears to be slower when executed upon a large string than merely pointing to a group of indexes. My presumption is that slice should be faster, but in my tests it is definitely slower. Here are some code examples:

      var a, i, x = "some large string of greater than 150kb", y = x.split(''), z = y.length;
      for (i = 0, i < z; i += 1) {
      if (y[i] + y[i + 1].toLowerCase() + y[i + 2].toLowerCase() + y[i + 3].toLowerCase() + y[i + 4].toLowerCase() + y[i + 5].toLowerCase() + y[i + 6].toLowerCase() === "<style") {
      a = "some value";
      }
      }
      for (i = 0, i < z; i += 1) {
      if (x.slice(i, i + 7) === "<style") {
      a = "some value";
      }
      }

      The second loop is much easier to read and I presume it would be faster because it is searching an index of a string, but it is only performing that search once per iteration of the loop. The first loop is ugly to look at, but appears faster in Firefox and Opera, which is surprising because it is performing 7 different look ups into an array per loop iteration. It is further surprising considering that large data segments would presumed to be more memory efficient as a joined string opposed to associating each character with an array index. The larger the tested string the more disparaging the results become.

      My question is why is the second loop, the pretty one, slower than the first loop? Even more strange I have found an exception to this test where the second loop becomes faster than the first loop only if the value of Z is subject to change per loop iteration, but the difference of speed in this exception is less than the difference of speed evident in the stated examples.

      Thanks,

      Austin
      http://prettydiff.com/
    • Marcel Duran
      Hi Austin, It s hard to tell why it s slower/faster without checking the algorithm implemented for slice on different engines. I did some background research
      Message 2 of 5 , Sep 3, 2010
      View Source
      • 0 Attachment
        Hi Austin,

        It's hard to tell why it's slower/faster without checking the algorithm
        implemented for slice on different engines. I did some background research
        on implementations of String.indexOf (
        http://www.javascriptrules.com/2009/08/12/string-searching-algorithms-in-javascript-engines/),
        you probably need to do something similar to understand why, unfortunately
        you won't be able to check those closed-source engines.

        BTW, looking at your example, have you considered regular expression or even
        String.indexOf, you could save some time by not splitting a long string into
        array.

        Regarding your tests, could you share it with the list? Maybe create a new
        test suite on http://jsperf.com/


        <http://jsperf.com/>Best,

        Marcel

        On Fri, Sep 3, 2010 at 1:35 PM, Cheney, Edward A SSG RES USAR <
        austin.cheney@...> wrote:

        >
        >
        > Group,
        >
        > I am trying to figure out why slice appears to be slower when executed upon
        > a large string than merely pointing to a group of indexes. My presumption is
        > that slice should be faster, but in my tests it is definitely slower. Here
        > are some code examples:
        >
        > var a, i, x = "some large string of greater than 150kb", y = x.split(''), z
        > = y.length;
        > for (i = 0, i < z; i += 1) {
        > if (y[i] + y[i + 1].toLowerCase() + y[i + 2].toLowerCase() + y[i +
        > 3].toLowerCase() + y[i + 4].toLowerCase() + y[i + 5].toLowerCase() + y[i +
        > 6].toLowerCase() === "<style") {
        > a = "some value";
        > }
        > }
        > for (i = 0, i < z; i += 1) {
        > if (x.slice(i, i + 7) === "<style") {
        > a = "some value";
        > }
        > }
        >
        > The second loop is much easier to read and I presume it would be faster
        > because it is searching an index of a string, but it is only performing that
        > search once per iteration of the loop. The first loop is ugly to look at,
        > but appears faster in Firefox and Opera, which is surprising because it is
        > performing 7 different look ups into an array per loop iteration. It is
        > further surprising considering that large data segments would presumed to be
        > more memory efficient as a joined string opposed to associating each
        > character with an array index. The larger the tested string the more
        > disparaging the results become.
        >
        > My question is why is the second loop, the pretty one, slower than the
        > first loop? Even more strange I have found an exception to this test where
        > the second loop becomes faster than the first loop only if the value of Z is
        > subject to change per loop iteration, but the difference of speed in this
        > exception is less than the difference of speed evident in the stated
        > examples.
        >
        > Thanks,
        >
        > Austin
        > http://prettydiff.com/
        >
        >



        --
        Marcel Duran


        [Non-text portions of this message have been removed]
      • Cheney, Edward A SSG RES USAR
        Marcel, I did consider those. The limitation of indexOf method is that it can only be used once without altering your source data, and regular expression
        Message 3 of 5 , Sep 3, 2010
        View Source
        • 0 Attachment
          Marcel,

          I did consider those. The limitation of indexOf method is that it can only be used once without altering your source data, and regular expression would certainly be faster, but there is no native method for using a regular expression to return a list of indexes.

          As far as which tests I was using I was altering the type_define function of the markup_beauty function to obtain both tests. I used the it function of the markupmin function to discover the exception situation. Both of those scripts are components of a Pretty Diff tool I maintain at prettydiff.com

          http://prettydiff.com/markup_beauty.js
          http://prettydiff.com/markupmin.js

          Thanks,
          Austin
        • Marcel Duran
          What if you use regular expression with String.replace, you have a list of index plus you can alter the source data. Ex: var re = /
          Message 4 of 5 , Sep 4, 2010
          View Source
          • 0 Attachment
            What if you use regular expression with String.replace, you have a list of
            index plus you can alter the source data. Ex:

            var re = /<style/gi,
            str = 'foobar<style foo>foobar</style>foobar<script
            bar>foobar</script><STYLE foo>foobar</STYLE>foobar',
            res = str.replace(re, function (match, index, source) {
            print(index); // 6 then 64
            return '*' + match + '*';
            });

            print(res); // foobar*<style* foo>foobar</style>foobar<script
            bar>foobar</script>*<STYLE* foo>foobar</STYLE>foobar


            Best,

            Marcel


            On Fri, Sep 3, 2010 at 7:55 PM, Cheney, Edward A SSG RES USAR <
            austin.cheney@...> wrote:

            >
            >
            > Marcel,
            >
            > I did consider those. The limitation of indexOf method is that it can only
            > be used once without altering your source data, and regular expression would
            > certainly be faster, but there is no native method for using a regular
            > expression to return a list of indexes.
            >
            > As far as which tests I was using I was altering the type_define function
            > of the markup_beauty function to obtain both tests. I used the it function
            > of the markupmin function to discover the exception situation. Both of those
            > scripts are components of a Pretty Diff tool I maintain at prettydiff.com
            >
            > http://prettydiff.com/markup_beauty.js
            > http://prettydiff.com/markupmin.js
            >
            > Thanks,
            > Austin
            >
            >



            --
            Marcel Duran


            [Non-text portions of this message have been removed]
          • sandyhead25
            Marcel, String replace would certainly be faster, because such instructions pass to the same code base on which the JavaScript interpreter sits. String
            Message 5 of 5 , Sep 5, 2010
            View Source
            • 0 Attachment
              Marcel,

              String replace would certainly be faster, because such instructions pass to the same code base on which the JavaScript interpreter sits. String replace does not provide an index for its global matches so as to allow multiple instructions to execute on each match or pull each match into an empty array. In not for such conditions I would certainly use the replace method.

              It should be noted that while it is possible to pass a function with arguments into the replace method one should never do so. This essentially creates a whole through the interpreter to the underling code base. That means that if you can inject code into one of the function arguments you can pass that code through the JavaScript interpreter to possibly compromise the executing software. I would gladly sacrifice a measurable amount of performance as a general best practice to prevent potential code injection.

              Thanks,

              Austin
              http://prettydiff.com/
            Your message has been successfully submitted and would be delivered to recipients shortly.