Подтвердить что ты не робот

Почему удаление элементов занимает больше времени, чем добавление элементов?

У меня есть таблица с большим количеством строк (например, 10.000).
(Примечание: я понимаю, что нет смысла иметь большую таблицу, но я бы хотел понять поведение ниже). Когда я получаю новые данные, я хочу сначала очистить строки. Как ни странно, очистка таблицы занимает гораздо больше времени, чем создание строк с нуля. Очистка строк таблицы с помощью html("") или простой JS innerHTML = "" занимает 1,5 минуты, что намного больше, чем создание самих строк, что занимает меньше секунды.

Итак, мой вопрос:
- Почему удаление элементов занимает больше времени, чем их добавление? Что происходит "за кулисами"?
(Обратите внимание, что мой вопрос - это Почему, я не ищу возможные обходные пути).

UPDATE

Я заметил, что в строке и ячейках таблицы есть применяемые к ним плавающие определения, и когда я удаляю float, таблица опустошается в экземпляре.
Мне все равно хотелось бы понять , почему float делает удаление строк намного медленнее.
Здесь скрипка: https://jsfiddle.net/maaikeb/t5pduuue/
В Chrome требуется 25 секунд, чтобы очистить таблицу, и только 23 ms, чтобы добавить его в DOM.

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

jQuery пустой очень медленный
jQuery empty очень медленный
Каков наилучший способ удалить строку таблицы с помощью jQuery? Удаление строк таблицы в javascript
jquery - самый быстрый способ удалить все строки из очень большой таблицы

4b9b3361

Ответ 1

Если вы спросите, почему опустошение таблицы должно занимать 1000 раз дольше, чем добавлять ее, ну, это просто не должно: это ошибка.

Вы можете найти важные различия в производительности в зависимости от браузера, его версии, версии jQuery или ОС, но 25s против 23ms слишком много. Кажется, вы куда-то нажали на операцию O(N^2). Менее чем те люди открывают билеты, и разработчики браузера признают их.

В любом случае, удаление элементов не всегда быстрее, чем их добавление. Наша интуиция говорит, что уничтожение должно быть быстрее, чем создавать, но это не обязательно верно, когда дело касается манипуляции с DOM. И jQuery, и браузеру необходимо сделать дополнительную работу, чтобы извлечь элементы.

Если вы посмотрите на текущую (3.2.1) реализацию jQuery append() function, вы увидите, что это в основном то есть использовать собственный метод JS appendChild(). С другой стороны, Функция jQuery empty() (html() использует empty()) должна перебирать все внутренние элементы и заботиться о них удаление связанных данных (например, событий) с каждым из внутренних элементов для предотвращения утечек памяти.

И, если вы используете только ванильный JS, браузеру по-прежнему нужно проверять большое количество вещей при удалении элементов. Если вы хотите войти в внутреннюю часть браузера, вы можете проверить этот Firefox.

Не имеет значения, если вы идете на removeChild(), innerHtml или textContent(), браузеру всегда нужно пересчитывать стили и макет: проверьте этот в Chromium.

Подобные ошибки распространены. Если вы ищете в Chromium проблемы с ключевыми словами "removeChild" и "slow", вы получите длинный список . Иногда они приходят и уходят из-за исправлений, вводящих регрессии, например, в этот случай с использованием плавающих элементов. Этот другой вариант может быть особенно интересен для вас, поскольку он доказывает, что некоторые ошибки не связаны с методом, который вы выбираете для удаления элементов, и потому что, как и в вашем случае, оно появляется, когда к этим элементам применяются сложные правила CSS (предполагая, что браузер вызвал оплату).

Мне не удалось воспроизвести вашу проблему ни в Firefox, ни в Chrome, поэтому я не могу указать точную причину в течение 25 секунд или 1,5 минут, но это действительно кажется ошибкой, исправленной в более поздних версиях. Если у вас все еще есть одна и та же старая версия и ее можно воспроизвести, можно проверить, помогает ли удаление элементов в обратном порядке (начиная с lastChild). Возможно, вы избежите перерасчета положения всех плавающих братьев и сестер после того, как вы удалили.

В следующий раз, возможно, вы захотите открыть билет и следить за тем, как они обнаруживают ошибку и исправляют ее. Это удовлетворит ваше любопытство, и вы сможете много узнать о внутренних функциях браузера!

Ответ 2

Я предполагаю, что у вас плохая производительность в IE.

Я бы сказал, что, поскольку метод $.empty вызывает removeChild в цикле для каждого удаленного элемента в таблице, и этот метод всегда имел плохую производительность в IE - см. эта статья для краткого исследования с некоторыми сравнениями производительности и разрешениями.

Независимо от того, что вы делаете с большим DOM, вы будете иметь плохую производительность в IE. Эта статья об appendChild в большой DOM в IE является примером того, как сообщество по-прежнему одурманивается этим простым фактом.:)

Ответ 3

Вместо того, чтобы циклически удалить всю DOM и снова выполнить повторную визуализацию, вы можете использовать функции hide() и show(). Что быстро и полезно для производительности, так как получение скрытого столбца также очень просто. Пожалуйста, найдите снотворную полезную.

//did based on checkbox here update to ur requirement hide() callback remains same.

$("input:checkbox:not(:checked)").each(function() {
    var column = "table ." + $(this).attr("name");
    $(column).hide();
});

$("input:checkbox").click(function(){
    var column = "table ." + $(this).attr("name");
    $(column).toggle();
});
td, th {
    padding: 6px;
    border: 1px solid black;
}

th {
    background-color: #f0eae2;
    font-weight: bold;
}

table {
    border: 1px solid black;
}
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<p><input type="checkbox" name="first_name" checked="checked"> First Name 
  <input type="checkbox" name="last_name"> Last Name 
  <input type="checkbox" name="email" checked="checked"> Email</p>

<table id="report">
<thead>
<tr>
 <th class="first_name">First Name</th>
 <th class="last_name">Last Name</th>
 <th class="email">Email</th>
</tr>
</thead>
<tbody>
<tr>
 <td class="first_name">Larry</td>
 <td class="last_name">Hughes</td>
 <td class="email">[email protected]</td>
</tr>
<tr>
 <td class="first_name">Mike</td>
 <td class="last_name">Tyson</td>
 <td class="email">[email protected]</td>
</tr>
</tbody>

Ответ 4

Вы можете очистить таблицу, присвоив ее внутреннему HTML значение пустой строки. Затем он не будет проходить через каждый из элементов строки, чтобы найти заголовок, tbody или строку, чтобы удалить его. Это будет быстрее, чем ваш текущий подход.

$( "# yourtableid" ) HTML ( "");.