Увы, здесь всё работает корректно. От последовательности данных ничего не зависит. Если вы так увлеклись, то можете сгенерировать тестовые данные на 1000 записей и убедится в этом.
Вопрос в том, как решить вашу задачу, не добавляя памяти.
Допустим всё увеличилось в 10 раз. Было 3 списка по миллиарду. Стало 3 списка по 10 миллиардов. А ресурсы остались те-же самые (тот самый одинокий комп).
Такая задача решается достаточно просто.
В существующей программе надо дописать процедуру подкачки (она не видится слишком сложной). И последовательно по миллиарду записей подкачивать данные в оба массива. После каждой подкачки прогоняется файл связей (каждый раз все 10 миллиардов). Всё работает точно так, как реализовано сейчас. Всего 100 итераций подкачки. Для улучшения быстродействия я бы поставил SSD. За ночь, вероятно, подсчёт бы выполнился.
Я имею в виду, что ваше решение хорошо работает до тех пор, пока идентификаторы числовые. (Идентификаторы стали не числовые) Что вы будете делать в этом случае?
Сложнее, но порядок действий примерно такой:
Допустим, имеем не числовые идентификаторы, а GUID-ы. И имеем готовые ссылочно-целостные данные.
Для решения надо подготовить хеш-таблицы, где GUID однозначно сопоставляется с числом (это самая затратная по времени операция, её следует продумать). Затем решаем задачу уже известным способом.
Далее, либо оставляем числовые идентификаторы, или делаем обратное сопоставление.
У вас задача на обработку «больших объемов данных», и вы ее решаете, загружая все данные в память? А когда памяти не хватило — просто ее добавили?
Если задача может быть решена простым добавлением памяти — в этом нет ничего плохого, это хорошо. Значит в запасе есть ещё один простой механизм решения.
Внезапно у вас идентификаторы перестали быть числовыми, и что теперь?
Внезапно тип индентификатора измениться не может (бывает конечно, но о-очень редко, как правило из-за взаимного недопонимания с Заказчиком).
Есть алгоритмы посложнее, но побыстрее
Здесь вы меня заинтриговали. Что вы имеете в виду?
Вы правы, публикация как раз об этом. Показан подход работы с данными.
Просто с первого захода хочется сразу залезть куда-нибудь в Oracle или Hadoop, которые, кстати, в данном случае, мало чем могут помочь. А до второго или третьего захода не всякий Заказчик дотерпит. Хотя правильное решение может быть очень простым, чтобы выйти на него нужно время.
Количество запланированных заходов — это и есть — плановая трудоёмкость.
Скажите честно — а сколько оплаченных попыток на исследования закладываете в проект вы, когда хотите получить выгодный контракт?
Такова структура данных. И она однозначно определяет связь многие-ко-многим.
Это означает, что один муравей может проживать (быть прописанным, как у людей) в нескольких домах, и наоборот, несколько муравьёв может проживать в одном доме.
К сожалению, в автоматически подготовленных тестовых данных, это не учтено, так как решалась тестовая задача на объём данных. Но программа подготовки результатов это конечно же учитывает.
Конкуренция таймеров — это ещё одна интересная тема. В приложении могут конкурировать, например, setInterval и requestAnimationFrame. А ещё, как минимум, прерывания мыши, клавиатуры, изменения в DOM. Поэтому, такое комплексное поведение, лучше рассматривать отдельно.
В данной реализации псевдонагрузка введена:
Для примерной оценки стабильности работы заданного таймера под нагрузкой.
Для сравнения браузеров (одним достаточно 10 миллионов циклов, другие переваривают миллиард).
Для наглядного ответа на ваш комментарий я создал ещё один проект (самому стало интересно) и ввёл конкурентный таймер setInterval (функция APELSERG.MAIN.StartTimer2), который работает для любого выбранного режима. В конкурентный таймер я поместил псевдонагрузку, а из основного таймера — её убрал.
Общие нагрузочные характеристики не улучшились (хорошо видно, если дать нагрузку побольше). А красное сливается с белым — это правильно, так как период ожидания основного таймера стал приближаться к периоду его полного цикла.
Функциональной ошибки нет. Функция MyTimer должна вызываться один раз для старта setInterval (в исходном коде это хорошо видно — функция APELSERG.MAIN.Timer).
Согласен, что правильнее было бы её назвать, например, StartMyTimer.
Надо признать, что большинство замечаний, даже издевательских, это правда — описанный подход не является новой технологией (об этом честно сказано в первом абзаце).
Использую этот подход пару-тройку лет, но в интернете целостного описания или примера не нашёл. А выгода есть. Как сказал классик «Не эстетично, зато просто, дёшево и практично». Так появилась эта публикация.
Заметки на полях:
Это не SPA, хотя внешне очень похоже. Есть SPA-верся, но проще и полезнее эта, например иногда хочется Shift+Ссылка.
Это не замена AngularJS. Если надо — Angular легко уживается внутри.
Это не велосипед. Велосипед не может состоять из одной функции в пять строк. А суть всего подхода — в применении функции разбора URL.
По-поводу табличной вёрстки. Демо не имеет отношения к дизайну, его цель — показать наглядный и целостный пример.
По-поводу Notepad. Профит применения дефолтных текстовых редакторов:
Всегда и везде под рукой, быстро открываются, не глючат, не устанавливаются по пол дня.
За всё время для этого проекта не потребовалось ничего сложнее (это правда).
Допустим всё увеличилось в 10 раз. Было 3 списка по миллиарду. Стало 3 списка по 10 миллиардов. А ресурсы остались те-же самые (тот самый одинокий комп).
Такая задача решается достаточно просто.
В существующей программе надо дописать процедуру подкачки (она не видится слишком сложной). И последовательно по миллиарду записей подкачивать данные в оба массива. После каждой подкачки прогоняется файл связей (каждый раз все 10 миллиардов). Всё работает точно так, как реализовано сейчас. Всего 100 итераций подкачки. Для улучшения быстродействия я бы поставил SSD. За ночь, вероятно, подсчёт бы выполнился.
Сложнее, но порядок действий примерно такой:
Допустим, имеем не числовые идентификаторы, а GUID-ы. И имеем готовые ссылочно-целостные данные.
Для решения надо подготовить хеш-таблицы, где GUID однозначно сопоставляется с числом (это самая затратная по времени операция, её следует продумать). Затем решаем задачу уже известным способом.
Далее, либо оставляем числовые идентификаторы, или делаем обратное сопоставление.
Если задача может быть решена простым добавлением памяти — в этом нет ничего плохого, это хорошо. Значит в запасе есть ещё один простой механизм решения.
Внезапно тип индентификатора измениться не может (бывает конечно, но о-очень редко, как правило из-за взаимного недопонимания с Заказчиком).
Здесь вы меня заинтриговали. Что вы имеете в виду?
Просто с первого захода хочется сразу залезть куда-нибудь в Oracle или Hadoop, которые, кстати, в данном случае, мало чем могут помочь. А до второго или третьего захода не всякий Заказчик дотерпит. Хотя правильное решение может быть очень простым, чтобы выйти на него нужно время.
Количество запланированных заходов — это и есть — плановая трудоёмкость.
Скажите честно — а сколько оплаченных попыток на исследования закладываете в проект вы, когда хотите получить выгодный контракт?
Это означает, что один муравей может проживать (быть прописанным, как у людей) в нескольких домах, и наоборот, несколько муравьёв может проживать в одном доме.
К сожалению, в автоматически подготовленных тестовых данных, это не учтено, так как решалась тестовая задача на объём данных. Но программа подготовки результатов это конечно же учитывает.
В данной реализации псевдонагрузка введена:
Для наглядного ответа на ваш комментарий я создал ещё один проект (самому стало интересно) и ввёл конкурентный таймер setInterval (функция APELSERG.MAIN.StartTimer2), который работает для любого выбранного режима. В конкурентный таймер я поместил псевдонагрузку, а из основного таймера — её убрал.
Общие нагрузочные характеристики не улучшились (хорошо видно, если дать нагрузку побольше). А красное сливается с белым — это правильно, так как период ожидания основного таймера стал приближаться к периоду его полного цикла.
Код с конкурентным таймером на GitHub.
Демо с конкурентным таймером на GitHub.
Согласен, что правильнее было бы её назвать, например, StartMyTimer.
Надо признать, что большинство замечаний, даже издевательских, это правда — описанный подход не является новой технологией (об этом честно сказано в первом абзаце).
Использую этот подход пару-тройку лет, но в интернете целостного описания или примера не нашёл. А выгода есть. Как сказал классик «Не эстетично, зато просто, дёшево и практично». Так появилась эта публикация.
Заметки на полях: