Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #31 (permalink)  
Старый 03.01.2023, 13:14
Аватар для webgraph
Профессор
Отправить личное сообщение для webgraph Посмотреть профиль Найти все сообщения от webgraph
 
Регистрация: 14.11.2014
Сообщений: 186

Сообщение от voraa
ошибочка у меня вышла. Недоглядел
Сначала не удавалось догнать что за ошибочка XD, А потом стало понятно — random. Кстати после этого тесты стали более детерминированными — перестановка местами перестала влиять на результаты. Ибо до этого в массиве было миллион NaN — JS наверняка был в шоке от такого.
Ответить с цитированием
  #32 (permalink)  
Старый 03.01.2023, 14:06
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,754

Сделал тесты с массивами отсортированным и несортированным.
Для поиска в сортированном массиве использовал функцию, которую предлагал ранее, немного изменив ее.
Число элементов сделал 100_000, что бы не ждать часами.
const genKeys = (n) => {
	const keys = []
	while (n--) {
		const nkey = Math.round(Math.random()*100_000);
		const key = (''+nkey).padStart(6, '0');
		keys.push(key)
	}
	return keys;
}

// Поиск значения val в отсортированном массиве arr
// возвращает {ind, has} 
// has == true, если элемент есть и ind - индекс элемента
// has == false, если элемента нет и ind - индекс большего элемента
const findBinIndex =(arr, val) => {
	if (arr.length == 0) return {ind: 0, has:false}
    let nb=0, ne=arr.length-1;
    if (val<=arr[0]) return {ind:0, has:val==arr[0]};
    if (val > arr[ne]) return {ind: ne+1, has: false};
    if (val == arr[ne]) return {ind: ne, has: true};
    let index;
    while (true) {
        index = ((ne + nb) / 2) | 0;
        if (arr[index] <= val)
            nb = index;
        else
            ne = index;
             
        if (ne - nb == 1) {
            if (val<=arr[nb]) return {ind:nb,has:val==arr[nb]};
            if (val > arr[ne]) return {ind:ne+1, has: false};
            if (val == arr[ne]) return {ind:ne, has: true};
            return {ind: ne, has:false};
        }
    }
}


const N = 100_000;
let t0;

// Генерация ключей для заполнения
const keys = genKeys(N);
const obj = {};
const set = new Set();
const arr = [];
const arrns = [];
let key;

// Проверка и добавление для Set
t0 = performance.now();
for (let i=0; i<N; i++) {
	key = keys[i];
	if (!set.has(key)) set.add(key);
}
const tsetset = performance.now() - t0;  

// Проверка и добавление для объекта
t0 = performance.now();
for (let i=0; i<N; i++) {
	key = keys[i];
	if (!(key in obj))	obj[key] = true;
}
const tsetobj = performance.now() - t0;

// Проверка и добавление для массива
t0 = performance.now();
for (let i=0; i<N; i++) {
	key = keys[i];
	const res = findBinIndex(arr, key)
	if (!res.has)	arr.splice(res.ind, 0, key)
}
const tsetarr = performance.now() - t0;

// Проверка и добавление для несортированного массива
t0 = performance.now();
for (let i=0; i<N; i++) {
	key = keys[i];
	const ind =  arrns.indexOf(key);
	if (ind<0)	arrns.push(key)
}
const tsetarrns = performance.now() - t0;

  
// Проверка и удаление для Set
t0 = performance.now();
for (let i=0; i<N; i++) {
	key = keys[i];
	if (set.has(key)) set.delete (key);
}
const tdelset = performance.now() - t0;  

// Проверка и удаление для объекта
t0 = performance.now();
for (let i=0; i<N; i++) {
	key = keys[i];
	if (key in obj) delete obj[key];
}
const tdelobj = performance.now() - t0; 

// Проверка и удаление для  массива
t0 = performance.now();
for (let i=0; i<N; i++) {
	key = keys[i];
	const res = findBinIndex(arr, key);
	if (res.has)	arr.splice(res.ind, 1);
}
const tdelarr = performance.now() - t0; 

// Проверка и удаление для несортированного массива
t0 = performance.now();
for (let i=0; i<N; i++) {
	key = keys[i];
	const ind = arrns.indexOf(key);
	if (!ind>=0) arrns.splice(ind, 1);
}
const tdelarrns = performance.now() - t0;
     

console.log('Проверка и добавление для объекта', tsetobj.toFixed(0))
console.log('Проверка и добавление для Set', tsetset.toFixed(0))
console.log('Проверка и добавление для массива', tsetarr.toFixed(0))
console.log('Проверка и добавление для несорт. массива', tsetarrns.toFixed(0))
console.log('Проверка и удаление для объекта', tdelobj.toFixed(0))
console.log('Проверка и удаление для Set', tdelset.toFixed(0))
console.log('Проверка и удаление для массива', tdelarr.toFixed(0))
console.log('Проверка и удаление для несорт. массива', tdelarrns.toFixed(0))


Результаты такие
Цитата:
Проверка и добавление для объекта 62
Проверка и добавление для Set 23
Проверка и добавление для массива 1443
Проверка и добавление для несорт. массива 181184
Проверка и удаление для объекта 26
Проверка и удаление для Set 23
Проверка и удаление для массива 4620
Проверка и удаление для несорт. массива 28313
Какой то парадокс. Безумно долго идет заполнение неотсортированного массива. В разы дольше, чем удаление из него же. Не могу понять почему.

Последний раз редактировалось voraa, 03.01.2023 в 14:15.
Ответить с цитированием
  #33 (permalink)  
Старый 03.01.2023, 14:12
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,590

Для объекта лучше Object.create(null) использовать. Тогда с Set более-менее сравняется.)

А по массивам - там столько скрытых оптимизаций на уровне движка, что без курения сырцов я бы не стал ничего заявлять.
__________________
29375, 35
Ответить с цитированием
  #34 (permalink)  
Старый 03.01.2023, 14:38
Аватар для webgraph
Профессор
Отправить личное сообщение для webgraph Посмотреть профиль Найти все сообщения от webgraph
 
Регистрация: 14.11.2014
Сообщений: 186

Сообщение от voraa
Какой то парадокс
И не говори...


Если искать число в строковом obj/set, то побеждает Object.
Если искать строку в строковом obj/set, то побеждает Set.
Если искать число в числовом obj/set, то побеждает Object.
Если искать строку в числовом obj/set, то побеждает Object.

Победа означает +- x2 производительность. Причём у Object производительность бывает выше до 80%

НО! Если искать очень большое число (сильно выходящее за границы элементов массивов) среди строкового или числового obj/set, то obj сильно начинает проигрывать!...

//

Последний раз редактировалось webgraph, 03.01.2023 в 15:34.
Ответить с цитированием
  #35 (permalink)  
Старый 03.01.2023, 14:53
Аватар для webgraph
Профессор
Отправить личное сообщение для webgraph Посмотреть профиль Найти все сообщения от webgraph
 
Регистрация: 14.11.2014
Сообщений: 186

voraa,

Раз тебя так заинтриговали массивы, может стоит поробовать интерполирующий поиск?

function InterpolationSearch(t,A)          // t - искомый элемент,
{                                          // A - упорядоченный массив, в котором ищем.
    var mid, low = 0, high = A.length-1;

    while (A[low] < t && A[high] > t)
    {  mid = low + Math.floor( ((t-A[low])*(high-low))/(A[high]-A[low]) );
       if (A[mid] < t) low = mid+1;
       else if (A[mid] > t) high = mid-1;
       else return mid;
    }

    if (A[low] === t) return low;           // На выходе индекс искомого элемента.
    else if (A[high] === t) return high;    // Если искомого элемента нет в массиве, то -1.
    else return -1;
}


Интерполирующий поиск похож на то, как мы ищем контакт в адресной книге (бумажной). Например, если нам надо найти Ваню, то наврядли мы будет открывать конец или середину книги (как это делается в бинарном поиске) — мы откроем на первых страницах.

//

P.S. у него скорость тоже низкая по сравнению с Set или Map

Последний раз редактировалось webgraph, 03.01.2023 в 15:13.
Ответить с цитированием
  #36 (permalink)  
Старый 03.01.2023, 15:00
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,590

webgraph, из-за безумия хозяев стандарта числовые ключи в объекте сортируются и кладутся в начало, что скорее всего и отражается как-то на разнице.
__________________
29375, 35
Ответить с цитированием
  #37 (permalink)  
Старый 03.01.2023, 15:03
Аватар для webgraph
Профессор
Отправить личное сообщение для webgraph Посмотреть профиль Найти все сообщения от webgraph
 
Регистрация: 14.11.2014
Сообщений: 186

Сообщение от Aetae
отражается как-то на разнице
"Как-то"? "Как-то" - это когда +- 10% выше производительность. А когда это доходит до 80%, то это уже не "как-то". Это уже ОГОГО
Ответить с цитированием
  #38 (permalink)  
Старый 03.01.2023, 15:18
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,754

Сообщение от Aetae
из-за безумия хозяев стандарта числовые ключи в объекте сортируются и кладутся в начало
Устройство движка вещь непредсказуемая.
У меня нет твердой уверенности, что они так кладутся и хранятся.
Вот выбираются они так - сначала числовые, потом строковые в порядке добавления.
К тому же оптимизации всякие. Файрфокс на неотсортированном массиве показывает гораздо лучшие результаты, чем Хром.
Ответить с цитированием
  #39 (permalink)  
Старый 03.01.2023, 15:25
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,754

Сообщение от webgraph
Интерполирующий поиск похож на то, как мы ищем контакт в адресной книге (бумажной). Например, если нам надо найти Ваню, то наврядли мы будет открывать конец или середину книги (как это делается в бинарном поиске) — мы откроем на первых страницах.
Вот только как реализовать это
mid = low + Math.floor( ((t-A[low])*(high-low))/(A[high]-A[low]) )

для строк?
Ответить с цитированием
  #40 (permalink)  
Старый 03.01.2023, 15:35
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,754

Сообщение от webgraph
Если искать число в строковом obj/set, то побеждает Object.
.....
Если искать число в числовом obj/set, то побеждает Object.
У объектов нет чисел. Они все равно преобразуются в строки. Свойством может быть только строка или Symbol.
Сообщение от Aetae
Для объекта лучше Object.create(null) использовать.
Попробовал - эффекта не дало.

Последний раз редактировалось voraa, 03.01.2023 в 15:56.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
При нажатии на тег <pre> добавить элемент в массив и вывести его vanyabb Angular.js 4 03.04.2017 15:46
Как в шаблоне диррективы узнать массив это или строка? delias Angular.js 1 18.03.2014 07:33
Как вы относитесь к наркоманам? Maxmaxmaximus7 Оффтопик 7 05.02.2014 13:29
Как узнать родительский элемент? alex_han Events/DOM/Window 6 06.12.2013 23:01
Как добавить тег в каждый элемент списка? elias jQuery 4 15.08.2010 15:19