[Depth] clawed V8 engine source code, I found the front-end algorithm you want (the interviewer to ask the next algorithm, using hate it back!)

Algorithm for front-end engineers is always a layer of mystery, this article by reading the source code V8 with you to explore the Array.prototype.sortalgorithm functions to achieve.

Come, you've heard of and used sorting algorithms are listed first:

  • Quick Sort
  • Bubble Sort
  • Insertion Sort
  • Merge sort
  • Heapsort
  • Shell sort
  • Selection Sort
  • Counting Sort
  • Bucket sort
  • Radix Sort

To answer session, which of the above function uses an algorithm to sort?

If you search on the Internet an article on sort source, it may tell you the array length is less than 10 with insertion sort, otherwise use quick sort.

I began to think so, but when I took the time to answer GitHub verify the discovery is not the case.

First, I did not find the corresponding source code js (The article said that to achieve js logic is written), but since the new V8 version of the source code has been modified in favor V8 Torque. V8 TorqueV8 is designed to develop and create the language, syntax similar TypeScript (once again proved the value of TypeScript), its compiler uses CodeStubAssemblerconverted into a highly efficient assembly code.
Simple to understand is to create an efficient high-level language similar TypeScript the file extension of this language is tq.

We should thank justjavac great God pointing ~

Secondly, when I started reading the source code, and we did not find the code using quick sort, often 10 to determine the value of the array length but could not find.

All the evidence shows that, before the source code is interpreted article may be outdated.

Then the latest version of the V8 with what sort algorithm do?

Interpretation Algorithm

After xx V8 engine version will abandon the quick sort, because it is not a stable sorting algorithm, in the worst case, the time complexity will be downgraded to O (n ^ 2).
Instead of using a hybrid sort of algorithm: TimSort.
This function algorithm originally used in Python language, t strictly speaking it does not belong to any of the 10 or more sorting algorithm belonging to a hybrid ordering algorithm:
a small amount of data used in the subarray insertion sort , then use merge sort will be ordered subarray merge sort, time complexity is O (nlogn).

V8 binding source, specific implementation steps are as follows:

  1. Determining the length of the array, direct return of less than 2, not sorted.
  2. To start the cycle.
  3. Ordered to find a sub-array, which we call "run", length currentRunLength.
  4. Calculating a minimum sequence length combined minRunLength (this value dynamically changes according to the length of the array, between 32 to 64).
  5. Comparative currentRunLength and minRunLength, if currentRunLength> = minRunLength, or using the insertion sort to make up the length of the array minRunLength, will run onto the stack in pendingRuns.
  6. Every time a new stack of any guaranteed run three consecutive run (run0, run1, run2) from the bottom to meet run0> run1 + run2 && run1> run2, not, to be adjusted until it is pressed into satisfied pendingRuns.
  7. If the remaining sub-array is 0, the loop ends.
  8. The combined stack all run, ordering an end.

Source Reading

Source Path

/thrid_party/v8/builtins/array-sort.tq

Call Stack

1386 ArrayPrototypeSort
1403 ArrayTimSort
1369 ArrayTimSortImpl
1260 ComputeMinRunLength // 计算 minRunLength
// while循环 
1262 CountAndMakeRun // 计算当前 run 的长度
1267 BinaryInsertionSort // 用插入排序补足 run 长度
1274 MergeCollapse // 放入 pendingRuns 并根据需要进行调整
// 循环结束 
1281 MergeForceCollapse // 合并 pendingRuns 中所有 run

Core Source

Although some tq language is not the same, but if there is TypeScript basis, then reading it should not be a problem.
Key Source interpret the following three functions:

// 在while循环之前调用,每次排序只调用一次,用来计算 minRunLength
macro ComputeMinRunLength(nArg: Smi): Smi {
  let n: Smi = nArg;
  let r: Smi = 0;

  assert(n >= 0);
  // 不断除以2,得到结果在 32~64 之间
  while (n >= 64) {
    r = r | (n & 1);
    n = n >> 1;
  }

  const minRunLength: Smi = n + r;
  assert(nArg < 64 || (32 <= minRunLength && minRunLength <= 64));
  return minRunLength;
}
// 计算第一个 run 的长度
macro CountAndMakeRun(implicit context: Context, sortState: SortState)(
    lowArg: Smi, high: Smi): Smi {
  assert(lowArg < high);
  // 这里保存的才是我们传入的数组数据
  const workArray = sortState.workArray;

  const low: Smi = lowArg + 1;
  if (low == high) return 1;

  let runLength: Smi = 2;

  const elementLow = UnsafeCast<JSAny>(workArray.objects[low]);
  const elementLowPred = UnsafeCast<JSAny>(workArray.objects[low - 1]);
  // 调用比对函数来比对数据
  let order = sortState.Compare(elementLow, elementLowPred);

  const isDescending: bool = order < 0 ? true : false;

  let previousElement: JSAny = elementLow;
  // 遍历子数组并计算 run 的长度
  for (let idx: Smi = low + 1; idx < high; ++idx) {
    const currentElement = UnsafeCast<JSAny>(workArray.objects[idx]);
    order = sortState.Compare(currentElement, previousElement);

    if (isDescending) {
      if (order >= 0) break;
    } else {
      if (order < 0) break;
    }

    previousElement = currentElement;
    ++runLength;
  }

  if (isDescending) {
    ReverseRange(workArray, lowArg, lowArg + runLength);
  }

  return runLength;
}
// 调整 pendingRuns ,使栈长度大于3时,所有 run 都满足 run[n]>run[n+1]+run[n+2] 且 run[n+1]>run2[n+2]
transitioning macro MergeCollapse(context: Context, sortState: SortState) {
    const pendingRuns: FixedArray = sortState.pendingRuns;

    while (GetPendingRunsSize(sortState) > 1) {
      let n: Smi = GetPendingRunsSize(sortState) - 2;

      if (!RunInvariantEstablished(pendingRuns, n + 1) ||
          !RunInvariantEstablished(pendingRuns, n)) {
        if (GetPendingRunLength(pendingRuns, n - 1) <
            GetPendingRunLength(pendingRuns, n + 1)) {
          --n;
        }
        MergeAt(n); // 将第 n 个 run 和第 n+1 个 run 进行合并
      } else if (
          GetPendingRunLength(pendingRuns, n) <=
          GetPendingRunLength(pendingRuns, n + 1)) {
        MergeAt(n); // 将第 n 个 run 和第 n+1 个 run 进行合并
      } else {
        break;
      }
    }
  }

to sum up

The front end of the next job interview when the interviewer asks if you algorithm problem, you can smiled and asked him / her:

Array functions sort of know what algorithm you use? TimSort not to find out?

Of course, if the interviewer therefore do not get the offer may lead to embarrassment and blame of ~

reference:


It recommended by a number of technical experts to help you become advanced weapon with full capacity and global vision engineers - "The Great JavaScript engineer" ready to hit in Jingdong, Dangdang, Taobao major platforms -

Click on the link below immediately embark on the road belongs to you advanced it!

https://u.jd.com/nETVMh

Guess you like

Origin www.cnblogs.com/yalishizhude/p/11462621.html