Вызвав на основе слова или фразы, вводимые в текстовое поле


Я работаю на простой цикл, когда пользователь вводит текст в TextBox при вводе определенных слов или фраз, XYZ-это срабатывает. У меня мой код работает, как нужно, но я ищу способ улучшить / оптимизировать.

$("#input_test").on("keyup",function(){
    var common = false;

    var inputVal = $(this).val().toLowerCase().replace(/[^a-zA-Z ]/g, "");

    var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];


        var common = triggerWords.some(function(v){
           return inputVal.indexOf(v) !== -1;
        });

        if(common){
            $('#showme').show(300);
        }else{
            $('#showme').hide(300);
        }

});

Рабочая JSFiddle



119
1
задан 3 апреля 2018 в 03:04 Источник Поделиться
Комментарии
1 ответ

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


У меня мой код работает, как нужно, но я ищу способ улучшить / оптимизировать.

Если вы хотите улучшить результат, есть несколько вещей вы можете сделать.

Тестирование

Первая вещь заключается в том, что вы можете запустить тесты и посмотреть, как стиль кода и логики может повлиять на производительность. Тестирования JavaScript-кода немного сложнее. Вы не можете просто запустить функции. Вы должны убедиться, что вы не обмануты оптимизатора

Я добавил базовые JavaScript и тестер производительности на дно, чтобы подчеркнуть следующие моменты.

Медленно итераторы

Массив итерации функций, таких как Array.some обычно медленнее, чем писать стандартное for, for of или while петли. Причина в том, что функции создают массу дополнительных накладных каждый раз, когда они звонят. Им нужна своя память, специальные структуры для удержания текущей области, и значения закрытия. Все это добавляется в кучу JavaScript и называют функции "контекст".

На вершине, что фактическая функция Array.some должен сделать некоторые проверки, чтобы убедиться, что аргументы вы передаете верны и могут быть использованы. Все это увеличивает время выполнения функции.

Для петель быстрее

С помощью for...of петли избегает всего, что накладные расходы и в данном примере составляет около 60% быстрее (на Хром)

var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
for(const word of triggerWords ){
if(inputVal.indexOf(word) {
$("#showme).show(300);
return; // all done exit the key up event
}
}
$("#showme).hide(300);

Родной державой!

Но проблема по-прежнему итерации. Используя Javascript, чтобы проверить каждую строку в свою очередь, никогда не будет использовать истинную мощь современного процессора. Но есть способ поиска сделано с использованием чистого машинного кода.

RegExp сделаю тест в долю времени.

Построение регулярного выражения из массив string дорого, поэтому не используйте этот метод, если в строку поиска (triggerWords) изменения каждого теста. Но если поиск будет то же каждый раз, вы можете построить regExp на старте и вы получите около 1000% прирост производительности.

// create at start;
var triggerWords = ['hello there','world', 'hello world', 'how do I turn this on', 'general kenobi'];
const reg = new RegExp(triggerWords.join("|"),"gi")

// inside the key event
if(reg.test(inputVal)){
$("#showme).show(300);
} else {
$("#showme).hide(300);
}

Стоимость библиотеки

Самым простым способом повышения производительности является падение библиотеки.

Без jQuery код выглядит.

const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) => {
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) ) {
showme.classList.remove('hide');
}else {
showme.classList.add('hide');
}
});

И добавить hide класс в CSS.

 .hide { display : none; }

Следующий фрагмент кода показывает, что он все собрал, скопировал из своего скрипку (страницы, требующие более 1Mbyte JavaScript для запуска) в общей сложности меньше, чем 1000bytes для всех код, CSS и разметки



const wordSearch = /hello there|world|hello world|how do I turn this on|general kenobi/gi;
inputTest.addEventListener("keyup", (event) => {
if( wordSearch.test(inputTest.value.replace(/[^a-z ]/gi,"")) ) {
showme.classList.remove('hide');
}else {
showme.classList.add('hide');
}
});

#showme{
padding-top:15px;
}
.muted{
padding-top:15px;
font-size:12px;
color:#ccc;
}
.hide {
display : none;
}

<p>
Enter a word or phrase to search:
</p>
Search: <input id ="inputTest" type="text" placeholder="Word / Phrase">
<div id="showme" class="hide">
<iframe src="https://giphy.com/embed/Nx0rz3jtxtEre" width="240" height="120" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>
</div>
<div class="muted">Indexed words / phrases:
<ul>
<li>hello there</li>
<li>world</li>
<li>hello</li>
<li>hello world</li>
<li>how do I turn this on</li>
<li>general kenobi</li>
</ul>
</div>


Пример сравнения производительности.

На фрагменте испытаний 3 методы поиска Array.some, for..of и regExp

Он использует худшем случае и выполняет тесты многих 1000 раз. Заказ тест наугад, чтобы остановить оптимизатор поворота одного метода над другим, и результат каждого поиска двинул на глобальную переменную, чтобы остановить оптимизатору просто удалив внутреннюю полностью петли

Давайте тестовый запуск пока время начинают стабилизироваться, то перейдите на страницу сравнить результаты производительности.



/*===========================================================================
Set up test data.
One big array with

===========================================================================*/
const rand = (max) => Math.random() * max | 0;
const innerLoopCount = 1000;
var c = "aabbaa";
var b = "skjht kjhlvuh svrtgkj abcdef ghijklmn opqrst uvwxyz1 234567890 ";
var a = [];
for(i = 0; i < 10; i ++){ a.push(b.substr(rand(b.length -10), rand(8) + 2)) };
var reg = new RegExp(a.join("|"),"gi");
document.addEventListener("click",() => stop = true )
var stop = false;

var soak = 0; // this is to prevent optimiser removing test code. It soaks up entropy generated by the functions :P
function testA(){
var i = 0, found;
const now = performance.now()
while(i++ < innerLoopCount){
var found = a.some(function(word) {
return c.indexOf(word) > -1;
})

soak += found ? 1:0;
}
return performance.now() - now
}
function testB(){
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount){
found = false;
for(const word of a){
if(c.indexOf(word) > -1) {
found = true;
break;
}
}
soak += found ? 1:0;
}
return performance.now() - now;
}
function testC(){
const now = performance.now()
var i = 0, found;
while(i++ < innerLoopCount){

found = reg.test(c);
//for(const word of a){
// if(c.indexOf(word) > -1) {
// found = true;
// break;
// }
// }
soak += found ? 1:0;
}
return performance.now() - now;
}

const tests = [
{ count : 0, time : 0, run : testA, status : statusElementA, name : " 'Array.some' : "},
{ count : 0, time : 0, run : testB, status : statusElementB, name : " 'for...of' : "},
{ count : 0, time : 0, run : testC, status : statusElementC, name : " 'regExp' : "},
];
function testing() {
var testsCount = tests.length;

for(var i = 0;i < 100; i ++){
var selTest = tests[Math.random() * testsCount | 0];
selTest.time += selTest.run();
selTest.count += 1;
}
for(const test of tests){
test.mean = test.time / test.count;
test.status.textContent = `${test.name} mean ${test.mean.toFixed(3)}ms over ${test.count} cycles.`;
}
if(!stop){

setTimeout(testing,100);
}else{
tests.sort((a,b) => a.mean - b.mean);
const slowest = tests[tests.length -1].mean;
var win = " <span class='winner'>Fastest</span>";
let test;
for(test of tests){
test.status.textContent += (test.mean / slowest * 100).toFixed(1) + "%"
if( win ) {
test.status.innerHTML += win;
test.status.className = "champ";
win = undefined;
}
}
test.status.innerHTML += " <span class='looser'>Slowest</span>"
test.status.className = "lost";
}
}
setTimeout(testing,100);


body {
font-family : arial;
font size : large;
text-align : center;
}
h4 {
font-size : small;
}
.winner {
color : green;

}
.looser {
color : red;
}
.champ {
background : #CFC;
font-weight : 700;

transition: all 0.5s ease-out;
}
.lost {
background : #FCC;
transition: all 0.5s ease-out;
}


<h3>Javascript Array.some V for...of V regExp</h3>
<h4>Click on the page to stop testing.</h4>
<div id="statusElementA"></div>
<div id="statusElementB"></div>
<div id="statusElementC"></div>



1
ответ дан 4 апреля 2018 в 12:04 Источник Поделиться