Summarize the problems encountered in the front-end sequencing _javascript skills

Source: Internet
Author: User
Tags array length array sort javascript array microsoft edge

It seems that the front-end circle has been widely circulated a misunderstanding: the front-end does not use algorithmic knowledge. For a long time, we may have been influenced by this claim. Until the previous encounter with a product demand, looking back, found that this is not the case.

Front-end sorting

Front-End sort of scene

The front end passes the sort condition as a request parameter to the back end, which returns the sort result to the front end as a request response, a common design. But for some products it's not that useful.

Imagine a scenario: when you're using a gourmet app, you'll often switch the ordering, sort by price, and sort by the score in a minute.

In actual production, due to the cost of server and other factors, when the single data query becomes the overall performance bottleneck, also consider by the sort in front of the completion of the way to optimize performance.

Sorting algorithm

Feel this is not necessary to introduce, as a basic computer science algorithm, the description is directly copied Wikipedia .

The existence of this paragraph is purely for the purpose of (cou) (zi) (SHU).

Sort of JavaScript

When it comes to the front-end ordering, naturally the first thing you'll think of is JavaScript's native interface Array.prototype.sort .

This interface ECMAScript 1st Edition is present from the beginning. Let's look at what the description of the latest specification is about it.

Array.prototype.sort specification

Array.prototype.sort(compareFn)

Copy Code code as follows:

The elements of this array are sorted. The sort is isn't necessarily stable (that's, elements that compare equal don't necessarily remain in their ). If Comparefn is isn't undefined, it should be a function of that accepts two arguments x and Y and returns a negative value if x < Y, zero if x = y, or a positive value if x > Y.

Obviously, the specification does not limit sort the internal implementation of the sort algorithm. Even the implementation of the interface does not need to be a stable sort . This is critical, and will be dealt with many times next.

In such a context, the front-end sort of thing actually depends on the specific implementation of each browser. So, what is the current mainstream browser about sorting? Next, we compare Chrome,Firefox , and Microsoft Edgeto each other.

The implementation in Chrome

The Chrome JavaScript engine is V8. Because it is open source, you can see the source code directly.

The entire array.js is implemented in JavaScript language. The Sorting Method section is obviously much more complex than the quick sort you've seen before, but it's clear that the core algorithm is still a quick sort. The reason for the complexity of the algorithm is that V8 has done a lot of optimizations for performance considerations. (then it will start to say)

The implementation in Firefox

There is no way to determine what the array sort algorithm the Firefox JavaScript engine is about to use. [3]

According to the existing information, the merge sort is implemented within the Spidermoney.

The implementation in Microsoft edge

Microsoft Edge's JavaScript engine Chakra's core code has been open source in GitHub in early 2016.

By looking at the source code can be found that the Chakra array sorting algorithm is also a quick sort. And compared to V8, it simply achieves a pure, fast sort, with no trace of performance optimizations in V8.

Problems with JavaScript array sorting

As we all know, fast ordering is an unstable sort algorithm, and merging sort is a stable sort algorithm. Because of the differences in the algorithm selection of different engines, which lead to the front-end relying on the Array.prototype.sort interface to implement the JavaScript code, in the browser the actual execution of the sorting effect is inconsistent.

The difference in order stability requires a specific scenario trigger to have a problem, and in many cases, an unstable sort does not have an impact.

If the actual project development, the order of the array does not have the stability of the demand, then actually see here, the difference between the implementation of the browser is not so important.

But if the order of the project requirements must be stable, then the existence of these differences will not meet the demand. We need to do some extra work on this.

As an example:

A city's Motor vehicle license auction system, the final bid for the rules are:

1. Reverse order BY Price;

2. The same price is sorted according to the bid ranking (i.e. price submission time).

If the sort is done at the front end, the winning bidder displayed in the fast-sequencing browser is likely to be out of line with the expected

Explore the difference behind

Before we find a solution, it is necessary to explore the cause of the problem first.

Why Chrome uses a quick sort

In fact, this situation existed from the very beginning.

The Chrome beta was released on September 2, 2008, but soon after it was released, the array ordering implementation of the #90 bug feedback V8 by developers to the Chromium Development Group was not a stable sort.

This bug issue the time span of the discussion. Until November 10, 2015, there were still developers who commented on the V8 array sort implementation issue.

At the same time we noted that the issue had been closed. However, it was reopened by the development team member in June 2013 as a reference for the ECMAScript Next specification discussion.

And Es-discuss's final conclusion is this.

Copy Code code as follows:

It does not change. Stable is a subset of unstable. And vice versa, every unstable algorithm returns a stable result for some inputs. Mark ' s point are that requiring "always unstable" has no meaning, no matter what language.
/andreas

As described in the finalized ECMAScript 2015 specification, as referred to in the preceding paragraph of this article.

The characteristics of the Times

At the beginning of the release of Imho,chrome, it was reported that the problem might have special characteristics of the times.

As already mentioned, the first version of Chrome was released in September 2008. According to StatCounter's statistics, the two browsers with the highest market share in that period were IE (at that time only IE6 and IE7) and Firefox, with market share reaching 67.16% and 25.77% respectively. In other words, two browsers add up to a market share of more than 90%.

According to a different browser ranking algorithm stability statistics show that two more than 90% of the market share of browsers are using a stable array ordering. So it is reasonable for the developers to question the first Chrome release.

Conform to the specification

From the process of the bug issue discussion, you can probably understand some of the considerations that the development team members use to quickly sort the engine implementations.

One of them is that the engine must comply with the ECMAScript specification. Because the specification does not seek the description of the stable sort, they think that the implementation of the V8 is in full compliance with the specification.

Performance considerations

In addition, they argue that an important consideration in V8 design is the performance of the engine.

The quick sort compares to the merge sort and performs better in overall performance:

Higher computational efficiency. Fast sorting faster than other sorting algorithms of the same time complexity in the actual computer execution environment (without hitting the worst combination)
Lower cost of space. The former has only O (㏒n) space complexity, compared to the latter O (n) space complexity at run time less memory consumption
Performance optimization of V8 in array sorting algorithm

Since V8 is very fancy about engine performance, what does it do in array ordering?

By reading the source code, or a superficial study of some fur.

Mixed Insert Sort
Fast sorting is the idea of divide-and-conquer, which decomposes large arrays and recursively down the layers. However, if the recursion depth is too large, the memory resource consumption in order to maintain the recursive call stack will be very large. Poor optimization can even result in stack overflow.

The current implementation of V8 is to set a threshold to use the insertion sort for the lowest 10 decimal groups and the following length.

Depending on the code comment and the description in Wikipedia, the average time complexity of the insertion Order is O (n²) to the fast sorted O (n㏒n). However, in a running environment, the efficiency of a decimal group using insert sorting is higher than a quick sort, which is no longer expanded.

V8 code Example

var QuickSort = function QuickSort (A, from, to) {
  ...
  while (true) {
    //insertion the sort is faster to short arrays.
    if (To-from <=) {
      Insertionsort (a, from, to);
      return;
    }
    ......
  }
  ......
};

Three-digit access

As is known, the fast-ordered Achilles heel lies in the fact that the worst array combination will degrade the algorithm.

The core of the fast sorting algorithm is to select a datum (pivot) to decompose the compared exchange arrays into two number areas for subsequent recursion. Just imagine if the first or last element is always selected for an ordered array each time a datum element is selected, then each time a number of regions are empty, the number of recursive layers reaches N, and the time complexity of the algorithm is then degraded to O (n²). So the choice of pivot is very important.

V8 uses the three-digit ( median-of-three ) Optimization: In addition to the first and last two elements to select an additional element to participate in the benchmark element of competition.

The third element's selection strategy is roughly:

When the array length is less than or equal to 1000, select the element at the binary position as the target element.
When the array length exceeds 1000, every 200-215 (not fixed, followed by the length of the array) select an element to determine a number of candidate elements first. The candidate elements are then sorted one at a time, and the resulting median value is used as the target element
Finally, the median value of three elements is taken as pivot.

V8 code Example

var getthirdindex = function (A, from, to) {
  var t_array = new Internalarray ();
  Use both ' and ' to ' determine the pivot candidates.
  var increment = + ((to-from) &);
  var j = 0;
  from + + 1;
  to-= 1;
  for (var i = from; i < to; i + = increment) {
    T_array[j] = [I, A[i]];
    j + +;
  }
  T_array.sort (function (A, b) {return
    comparefn (a[1], b[1]);
  var third_index = T_array[t_array.length >> 1][0];
  return third_index;
};

var QuickSort = function QuickSort (A, from, to) {
  ...
  while (true) {
    ...
    if (To-from > 1000) {
      Third_index = Getthirdindex (A, from, to);
    } else {
      Third_index = from + ((to-f ROM) >> 1);
    }
  ......
};

Sort in situ

While reviewing the quick sort algorithm, I saw many examples of JavaScript implementations on the Web.

But found that a large part of the code implementation is shown below

var quickSort = function (arr) {
if (arr.length <= 1) {return arr;}
var pivotindex = Math.floor (ARR.LENGTH/2);
var pivot = Arr.splice (pivotindex, 1) [0];
var left = [];
var right = [];
for (var i = 0; i < arr.length i++) {
if (Arr[i] < pivot) {
Left.push (arr[i));
else {
Right.push (arr[i]);
}
return
QuickSort (left). Concat ([pivot], quickSort (right);
};

The main problem with the above code is that you store a recursive child array using the left and right two areas, so it requires an O (n) Extra storage space. Compared with the theoretical average space complexity O (㏒n), the gap is larger.

The extra space overhead also affects the overall speed of the actual runtime. This is one of the reasons why fast sorting can perform more than the other sorting algorithms at the same time complexity level at the actual runtime. Therefore, in general, a better performance of the quick sort will be in situ (in-place) sort of way.

The implementation in the V8 source code is an element exchange of the original array.

Why does Firefox use merge sort

There is also a story behind it.

Firefox actually at the beginning of the release of the array sorting implementation is not a stable sorting algorithm, this piece is available.

The first version of the Firefox (Firebird) Implementation of the array sorting algorithm is heap ordering, which is also an unstable sort algorithm. As a result, someone later submitted a bug to this.

There is a series of discussions within the Mozilla Development Group on this issue.

From the process of discussion we can draw a few points

1. At the same time Mozilla's competitor is IE6, from the above statistical data know IE6 is a stable sort of

The father of 2.JavaScript Brendan Eich think stability is good

3.Firefox is a quick sort before using heap sorting

Based on the premise that the members of the development group tend to achieve a stable ranking algorithm, Firefox3 merge sort as a new implementation of array sequencing.

Resolving the differences in sort stability

That's a lot to say about the differences between browsers for sorting implementations, and some of the more superficial reasons why these differences exist.

But read this, the reader may still have questions: if my project is to rely on a stable sort, then what to do?

Solution

In fact, the idea of solving this problem is relatively simple.

Browsers choose different sorting algorithms for different considerations. There may be some preference for the ultimate performance, some of which tend to provide a good development experience, but there are rules to follow.

From the current known situation, all major browsers (including ie6,7,8) can basically enumerate the implementations of array sorting algorithms:

1. Merge sort/Timsort

2. Quick Sort

So, we will quickly sort through custom transformation, into a stable sort of is it OK?

In general, using an unstable sort against an array of objects affects the results. The results of other types of arrays themselves using a stable sort or an unstable sort are equal. The programme is therefore broadly as follows:

The array to be sorted is preprocessed, the natural order attribute is added for each object to be sorted, and the object's other properties are not conflicted.
The custom sort comparison method is comparefn and always takes the natural order as the second judgment dimension when it is equal to the predecessor judgment.

In the face of the implementation of merge sort such as the algorithm itself is stable, the additional natural order comparison does not change the order results, so the scheme compatibility is better.

But it involves modifying the array to be sorted and needing to open up additional space for storing the natural order attributes, and it is conceivable that V8 such engines should not be used in a similar way. However, as a developer customization of the sorting scheme is feasible.

Scenario code example

' Use strict ';

Const INDEX = Symbol (' index ');

function Getcomparer (Compare) {return
  function (left, right) {Let's
    = compare (left, right);

    return result = = 0? Left[index]-right[index]: result;}
  ;

function sort (array, compare) {
  array = Array.map (
    item, index) => {
      if (typeof item = = ' object ') {
   item[index] = INDEX;
      }

      return item;
    }
  );

  Return Array.Sort (Getcomparer (Compare));
}

The above is just a simple example of the transformation of the algorithm to meet the stability ranking.

The reason is simple, because the actual production environment as an array input data structure jumbled, need to judge according to the actual situation needs to carry out a more diverse sorting before type detection.

Marking

1. The front end is now a relatively broad concept. The front end of this article refers to the environment of JavaScript as a programming language with the browser as the carrier

2. This article is not intended to involve algorithm as a whole, I would like to use a common sorting algorithm as the cut-in point

3. When confirming the algorithm of the Firefox array sort implementation, we found a sort related bug of Spidermoney. The general meaning is that some people in the discussion suggested replacing the merge sort with the Timsort algorithm with better performance in extreme situations, but Mozilla's engineers said that because of the license authorization problem in the Timsort algorithm, there was no way to use the algorithm directly in Mozilla's software. Waiting for a follow-up reply

Summarize

The above is everyone in the front-end ranking problems encountered in the summary and solutions, in recent years more and more projects are to the rich client application direction change, the front-end in the project accounted for larger. As future browser computing power increases, it allows for more complex computations. Along with the change of responsibilities, the shape of the front end may also have some significant changes. Walk the lake, always have a skill alongside body.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.