Тест производительности трёх способов вставки в сортированный массив на JavaScript




Задача: имея на входе отсортированный массив чисел, добавить одно число, не ломая сортировки. Использовать браузерный JavaScript.

Предположение: внутренний sort массива может выигрывать интерпретируемый код сортировщика до какого-то размера массива.

Что я сделал. Реализовал три алгоритма решения этой задачи и запилил пост с результатами проверки производительности и самим тестом, так что вы сами можете его запустить.

Тесты запускаются в async режиме чтобы позволить Google Charts отрендерить результаты и предотвратить подвисание браузера. Синхронный режим дал бы более точные результаты, впрочем и в асинхронном они достаточно показательны.

Каждый метод запускается несколько раз на одинаковых стартовых массивах. На следующем цикле проверки производительности размер стартового массива удваивается, пока не дойдёт до лимита размера массива.

Библиотека проверки производительности учитывает только время по часам. И хотя линейный способ выигрывает на небольших массивах (до 64 элементов у меня), он более затратен в смысле процессорного времени.

Попробуйте сами запустить runTest(size) в консоли. Имейте в виду, что график может поломаться, если запустите с числом меньшим, чем максимальное на графике.

Можете установить лимит размера массива самостоятельно – это maxSize параметр в url. Например, для 65536 используйте эту ссылку.

Результаты: Внутренний Array.sort хуже логарифмической и даже линейной вставки во всех случаях. Логарифмический поиск меньше нагружает процессор, что неудивительно. Используйте логарифмический!

Код методов

1
2
3
4
5
6
7
8
9
10
11
          /*
           *  A simplest method that comes at the first sight.
           *  O(1) JavaScript interpreted insert and then the sort
           *  that is probably implemented as a precompiled method
           *  (or not?), but should take at least O(n*ln(n))
           */

            Array.prototype.addSorted1 = function(element){
                this.push(element);
                this.sort();
                return this;
            }

vs

1
2
3
4
5
6
7
8
9
          /*
           *  An O(n) JavaScript interpreted new element inserter
           */

            Array.prototype.addSorted2 =  function(element){
                for(var i=0;i<;this.length && this[i] < element;i++){
                }
                this.splice(i,0,element);
                return this;
            }

vs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
          /*
           *  An O(ln(n)) JavaScript interpreted new element inserter
           */

            Array.prototype.addSorted3 = function(element){
                var i=0;
                var j=this.length;
                var h;
                var c=false;
                if (element>this[j]){
                    this.push(element);
                    return this;
                }
                if (element<this[i]){
                    this.splice(i,0,element);
                    return this;
                }
                while(c==false){
                    h=~~((i+j)/2); //a faster h=Math.floor((i+j)/2);
                    if (element>this[h]){
                        i=h;
                    } else {
                        j=h;
                    }
                    if (j-i<=1){
                        this.splice(j,0,element);
                        c=true;
                    }
                }
                return this;
            };

Тест производительности

После запуска теста подождите минуту, две… или посмотрите ошибки в консоли 🙂

Журнал: