Где лучше выполнять арифметические операции? На клиенте или на сервере?
Вроде простой технический вопрос, но превратился в философский. Кого больше грузить: компьютер Клиента, или сервер?
Задачка такая: надо отобразить таблицу из трех колонок и тысячи строк. В первом столбце - число А, во втором - число B, в третьем - С, где C = A+B. Пусть лучше считает javascript, или сервер? Если javascript, то мы уменьшаем нагрузку на сервер, уменьшаем клиентский трафик, но замедляем работу браузера. Если наоборот, то сотня клиентов, подключившись к серверу тоже могут замедлить общий процесс получения данных... Причем формула сложения - это простейший случай. А может быть формула по теореме Пифагора вычисления гипотенузы как квадратного корня из суммы квадратов катетов, а может быть сложная формула, учитывающая с десяток переменных... У кого есть опыт в подобных задачах? Прошу совета. |
По мне так, максимально надо скидывать всю оработку информации клиенту, пусть его машина думает. Клиентов много, а сервер один, ему и без этой ерунды хватает занятий. Если у кого-то что-то тормозит - это его проблемы, пусть покупают компы получше :)
|
Цитата:
Цитата:
Ну и как я уже говорил, формула сложения - это простейший случай. Могут быть формулы вычисления типа: возьми ячейки с 1-й по 10-ю, сложи их содержимое и раздели на сумму ячеек с 11-й по 20-ю..., т.е. групповые операции. |
Цитата:
P.S. Гуглу легче. У него милли...милли...миллиарды $ ;) |
Цитата:
|
Цитата:
|
Цитата:
В первой колонке - Наименование товара. Во второй - Остаток на складе [штук] В третьей - Цена за штуку [$] В четвертую колонку надо положить (посчитать) произведение количества штук по строке на цену товара, т.е. стоимость данного конкретного товара. И так 5000 строк. Ниже всей таблицы надо в ячейке поместить сумму значений всей четвертой колонки, т.е. ответить на вопрос: на какую сумму товара хранится на складе? Где будете всё это считать? Неужели на клиенте? |
Цитата:
http://javascript.ru/blog/Andrej-Par...e-vychisleniya |
Цитата:
Вот ситуация: клиенту приехала 1000-строковая таблица с тремя колонками. В первой колонке - Наименование товара. Во второй колонке - Себестоимость товара. В третью колонку надо посчитать Продажную цену товара, которая, как известно, равна себестоимости товара плюс некий процент от себестоимости товара. Менеджер выставляет этот процент (а может это "скидка" была постоянному клиенту) и желает видеть результат в третьей колонке - это раз. И два - он хочет увидеть общую потенциальную прибыль после продажи товара, т.е., разницу между суммой X и суммой Y. Менеджер может "поиграть" процентом: поставить 15%, 16%,.. 23%,.. Казалось бы что еще проще? Javascript перемножит себестоимости на проценты, сложит за секунду. Но мы решили это делать на сервере! В результате начинается гоняние интернет-трафика туда/сюда и соответствующая бестолковая нагрузка на сервер... P.S. Вы не подумайте, что я шарахаюсь то в одну, то в другую сторону. Я понимаю, что одни задачи лучше решать "тут", а другие "там". Но вот есть ли более-менее строгий критерий, по которому эти задачи можно разделить на там/тут? |
Маэстро, на клиенте, конечно. Если есть возможность снять нагрузку с сервера - её надо снять. Тем более, какая разница - будет человек ждать, пока оно у вас на сервере посчитается, или пока оно посчитается на клиенте. Дальше: вычисления можно сделать "асинхронными" - тогда клиент не будет подвисать, а на время их выполнения поставить весёлую анимацию загрузки.
dmitriymar, в js есть функция toFixed, с её помощью можно вполне сделать вычисления удовлетворяюще точными. Ну и напоследок... Бивас, тест! (с) Внимание, этот код может повесить ваш браузер! <div id="log"></div> <script> var log= document.getElementById("log"); var t1= +(new Date()); for (var a=0, b=0, c; a!==1000; ++a, b+=2) { c= Math.pow(Math.pow(a, 2) + Math.pow(b, 2), 1/2); log.innerHTML+="<br>"+c; }; alert(+(new Date()) - t1); </script> На моём компе - не самом мощном, между прочим - около 5 секунд. И то, такое значение - лишь из-за операций вставки в дом, которые, как известно, весьма тяжёлые. А теперь этот же пример - с оптимизацией: 1) Сначала всё в строку: <div id="log"></div> <script> var log = ""; var t1= +(new Date()); for (var a=0, b=0, c; a!==1000; ++a, b+=2) { c= Math.pow(Math.pow(a, 2) + Math.pow(b, 2), 1/2); log+="<br>"+c; }; document.getElementById("log").innerHTML= log; alert(+(new Date()) - t1); // 10 миллисекунд </script> 2) Сначала всё в documentFragment: <div id="log"></div> <script> var log = document.createDocumentFragment(); var t1= +(new Date()); for (var a=0, b=0, c; a!==1000; ++a, b+=2) { c= Math.pow(Math.pow(a, 2) + Math.pow(b, 2), 1/2); log.appendChild(document.createElement("br")); log.appendChild(document.createTextNode(c)); }; document.getElementById("log").appendChild(log); alert(+(new Date()) - t1); // 10 миллисекунд </script> |
Цитата:
P.S. 100 тыс. строк - не перебор. В товарном справочнике предприятия более 140 тыс. наименований. |
По поводу вычислений - именно на клиенте. Любые вычисления не требующие серьёзной рекурсии выполняются очень быстро. Но надо понимать что именно вычисления, ни в коем случае нельзя дёргать документ до того как всё будет посчитано. Все вычисляемые цифры до окончательного вывода должны содержаться в js и тогда всё булет быстро.
Цитата:
Навесили овер9000 свистоперделок. Приходится на нём js отключенным держать, чтоб по-человечески работал. =( |
Цитата:
Пример. Менеджер хочет знать, на какую сумму товара хранится на складе по разделам: -телевизоры -стиральные машинки -холодильники -CD-плееры - ... итого 30 разделов. В каждом разделе грубо говоря по 1000 наименований. Как будем считать? Сразу думаю, что глупо гнать на клиента 30х1000=30 тыс. строк, чтобы посчитать в JS. В данном случае надо на сервере с помощью SQL-запроса посчитать суммы товаров по разделам, а на клиента отправить только 30 строк, на котором уже можно получить их общую сумму. Поэтому вопрос, поднятый в моей теме я трансформирую уже несколько по-другому: Каков строгий критерий разделения такого рода задач на задачи, решаемые на клиенте и на задачи, решаемые на сервере? |
>Каков строгий критерий
Логика. Какой-то выверенной годами истины в данном вопросе нет.(разве что в каких-нить новых забугорных книжках) |
Цитата:
|
Цитата:
http://javascript.ru/optimize/documentfragment-0 |
Маэстро, сравнивать надо не "1) Сначала всё в строку" и "2) Сначала всё в documentFragment", а с первым примером, 1) и 2) это разные варианты реализации того, как можно добавить в документ элементы одним действием.
|
Цитата:
-Товарищ старшина, а крокодилы летают? -Вы что, рядовой, конечно же нет! -Да? А товарищ полковник, сказал, что летают! -Даа?? Аа... ну да... летают... только низенько низенько... ;) |
Вот во всей этой проблеме я искренне немогу понять, зачем вы таблицу из 5000 строк единовременно клиенту отдаёте. (пост 10)
Что пейджинг c фильтрами уже не моден ? Теперь круто получить HTML'ку этак высотой в 80 экранов ? Если отдавать информацию небольшими блоками, то и проблема с тем где производить расчёты станет неактуальной, так как и на сервере и на клиенте они будут происходить мгновенно. Ну для полного кайфа вынесете расчёты на клиент, на любой машине 100 строк не окажут заметного влияния на производительность. |
Цитата:
DjDiablo, +1. Комп стандартной мощности верстать таблицу > 10000 ячеек будет долго. |
DjDiablo, trikadin,
понимаете... только без обид, ладно? Но вы мыслите устаревшими категориями. Что пейджинг c фильтрами уже не моден? Типа уже не моден. Точнее, исчерпал себя. Точнее, никто ничего не предлагает другого. Есть альтернатива? - Да. Теперь круто получить HTML'ку этак высотой в 80 экранов ? Да, круто. Но это не те 80 экранов, которые выльются в 80 мегабайт трафика. Есть другая технология. Комп стандартной мощности верстать таблицу > 10000 ячеек будет долго. Бесспорно. А 10000 строк? - умрёт вообще. Однако, есть другая технология... ;) Существуют задачи (в частности у предприятия, которое я автоматизирую), в которых менеджеры желают бегло просматривать по 1000-3000 записей из базы данных. Бегло - это значит быстро, не тратя даже пол-секунды на лишние действия. Поэтому стандартный страничный пейджинг уже раздражает. Также раздражает DOM-массив элементов, лежащий в памяти, который изображает из себя таблицу, построенную на html-теге <table>. Если таблица имеет всего 1000 строк х 100 столбцов, то она становится неповоротливой, а в IE почти недвижимой. Раздражает. Такого рода задачи присутствуют в бизнесе под названием логистика, грузооборот, товарооборот. В этих случаях менеджер хочет видеть как суммарные показатели, так и оперативную информацию по каждой позиции детально и всё одновременно. А теперь об альтернативе. Изучив потребности пользователей, я предложил и разработал технологию построения больших таблиц вообще без использования <table>. Если коротко, то суть в том, что моя таблица - это как бы вьюпорт, который ползает по виртуальным "80 экранам" и аджаксом динамически подкачивает с сервера информацию в зависимости от положения скроллера и других управляющих воздействий пользователя. В общем-то я уже об этом писал здесь: http://javascript.ru/forum/project/2...-kontakty.html Пример, который могу показать, здесь: http://gigalit.info |
Да мы вроде не интерфейс обсуждаем.
Речь шла о том что инфу хорошо бы разбить на блоки, при использовании подгрузки по ajax ты это как раз и делаешь. |
Цитата:
|
Маэстро, знаете, обсуждение потихоньку приходит к виду "А я вам докажу, что на сервере лучше!"
Необязательно доказывать, правда) Изначально вы писали: Цитата:
Так что предлагаю определиться, какова в итоге задача, и, исходя из этого, искать продуктивное решение. Кстати, о сумме всей таблицы - я бы на вашем месте завёл отдельное поле в базе данных, в котором бы хранил это значение - чтобы каждый раз не считать. |
Цитата:
Цитата:
Цитата:
|
Цитата:
расчёт трансформаций . расчёты для граф. вывода информации в 3д. цепочки расчётов ................................ |
Раз уж зашёл разговор о местах где можно выполнить расчёты, то я добавлю.
есть как минимум 5 способов,посчитать сумму всех строк 1) посчитать всё при отдаче данных с сервера 2) Посчитать на клиенте, передав туда все данные. 3) Посчитать сумму всех строк при добавлении записи в бд, и сохранить результат куда нубудь. (то что преложил Trikadin) 4) Прокешировать результат суммы строк. То есть, когда сервер возвращает данные он возвращает их из кеша, но если в бд произошли изменения то он считает сумму строк, записывает их в кеш и только потом возвращает результат. Определять необходимость перерасчёта суммы, можно по двум временным меткам. Одна метка, это время последней операции записи, вторая эта время (последней операции записи) которая участвовала в расчёте кеша. Если при операции получения выясняется что время последней операции не совпадает со (временем операции записи) участвующей в последнем расчёте кеша, значит кеш нужнается в перерасчёте. 5) Перманентный расчёт суммы строк. (в 1С эту функцию исполняют регистры) Этот подход проще описать алгоритмом. Допустим нам нужна стоимость всех товаров на складе. У нас есть уже посчитанная в кеше сумма всех товаров, нам необходимо изменить количество памперсов на складе. а) стоимость товаров на складе =стоимость товаров на складе-количество памперсов *на стоимость памперсов. б) Записываем в бд новое количество памперсов. в) Стоимость товаров на складе =стоимость товаров на складе+количество памперсов *на стоимость памперсов. Тоесть я просто отнял старую стоимость всех памперсов а потом прибавил новую. Это гораздо быстрее чем из за пары памперсов суммировать все строки в базе (десятки тысяч). Если подытожить, то максимальное быстродействие обеспечат именно регистры, такие же как в системе 1С. Причём при помощи регистров можно реализовать 99% всех типов расчётов (даже такие как прогноз продаж в следующем периоде). Добавлю что изменение записи в таблице товаров и регистре лучше обьединить в одну транзакцию. нелишним будет и создание утилиты обслуживания, которая используется в случае повреждения бд/ручного вмешательства в бд. Суть работы такой утилиты сводится к перерасчёту всех регистров на основании бд, аналогичный инструмент есть и в 1с. |
Цитата:
Цитата:
Они могут не совпадать и просто потому, что вычислились в разные миллисекунды. |
Цитата:
Цитата:
Цитата:
|
отвечаю пока на #32 топик
Извиняюсь если непонятно выразился, я уточню что имел ввиду в 4м примере. $A- время последнего изменения в таблице товаров $B- время операции основания которая была использована для последного расчёта кэша, $cashe- это типо кэш. вреале вся инфа в переменные предварительно загружается из бд, а в конце в бд сохраняется, но мы это опустим if ($A==$B) echo "Сумма всех товаров: ".$cashe; else { // здесь мы расчитываем новый кэш cashe= ................... $B= $A;// теперь время последней операции считается временем которое мы использовали для последнего расчёта кеша. } Тоесть нам пофиг что было раньше что позже, мы просто сравниваем два значения между собой, и если они отличаются то пересчитываем кэш. Вместо времени можно было и порядковый номер операции использовать. |
Цитата:
|
DjDiablo, да, понял)
Цитата:
|
Маэстро, попробую прокоментировать.
Во первых любой (кроме первых двух) подход при использовании фильтра по названию или к примеру по цене, будет бесполезен. Тут только рассчитывать. для 4) Если речь идёт о выборках по какому то критерию обьеденяющему множество товаров (к примеру по группе товара, или по поставщику, или складу, или ещё чему нибудь подобному), то здесь количество кэшей может быть равно количеству критериев. Но если это поиск по названию, то от кеширования толку ноль, и кешировать каждую запись конечно не нужно. Правда мне сложно представить ситуацию при которой менеджеру вдруг понадобится сумма всех товаров в названии который есть слог "Бла" )). Для 5) Прежде всего работа с таблицей товаров и регистрами товаров, инкапсулируется в одну сущность, и об отдельных запросах в бд говорить уже не корректно. Прямое обращение к бд нарушит целостность базы данных. class nomenklarura { function addItem($name,$price=0){ // начало транзакции // запись в бд товара // пересчёт регистра // конец транзакции } } В данном случае у нас нет иного способа создать ещё один товар кроме как обратится к методу addItem класса nomenklatura. Если нужно создать 100 товаров значит нужно сто раз обратится к методу, либо передать ему массив значений и обработать его в цикле, выполнив все операции как одну транзакцию. А вот что касается проблемы одновременного доступа, то в мускуле проблема параллелизма должна решатся на уровне транзакций ну на худой конец при помощи системной блокировки. Я пожалуй немного подумаю над этим, а потом отпишусь. Кстатии, также было бы интересно позаимствовать механизьм счетов из 1с. Я попозже черкну как. |
Цитата:
Цитата:
По морю ездят контейнера. В нумерации контейнеров жесткое правило: номер должен содержать 4 буквы, потом 7 цифр. Все морские компании (перевозчики) каким-то им неведомым способом кодируют свои контейнера, тем не менее, получается что-то типа: MRKU3566361 MRKU3532370 MRKU1234567 ... Менеджер набирает в фильтре "MRKU"... Ну, дальше Вы поняли ;) |
Давай определимся по какому критерию определять выигрыш. Если даже в половине случае скорость запроса вместо 100мс, занимает 1мс то это уже победа. И ради тех случаев где ускоренее невозможно, не вижу сымысла отказыватся от возможности ускорить хотябы половину.
P.S. Почему морские контейнеры нельзя отправить в отдельную категорию контейнеры ? |
Цитата:
Цитата:
Думаю что Вы знаете, что практически в каждой таблице есть такое емкое поле "Примечание". В него пишут всё. Всё, что можно и не можно. Специфика больших корпораций заключается в том, что автоматизация бизнес-процессов постоянно опаздывает за требованиями времени. Программисты могут сделать доработку через день, через месяц, через год... а менеджеру надо "на вчера"! Менеджеры не знают языка SQL, да и к базе напрямую их не пускают. Но они - народ изобретательный, поэтому используют свой "птичий" язык. Что это значит - сейчас приведу несколько примеров по памяти. 1. Потребовалось в таблице отображать признак "Документ распечатан". Ну типа статуса такого. Пока программисты думали/делали, менеджеры договорились, что в поле примечание будут писать условный сигнал {p} (наверное от слова printed). Что происходит далее? Далее производится поиск документов по полю примечание, в котором есть "{p}" 2. Знаете, что такое колка льда? Не та что для коктейлей. Когда зимой корабль заходит в порт, то ледокол дробит перед ним лед. Это выливается в доп. затраты на перевозку грузов. Когда ввели эти затраты и их надо было учитывать менеджеры тут же начали писать в примечание {лед}. Ну а дальше поиск по "{лед}". 3. Самое внезапное - это наше законодательство. Вдруг ввели некий типа налог, который называется "пошлина евро". Что сделали менеджеры? -Правильно, в примечание пишут {evro}. Конечно, со временем системщики анализируют все эти примечания и раскладывают по признакам, категориям в базе. Однако менеджеры продолжают пользоваться любимым птичьим языком и выборкой по ключевым словам. |
Часовой пояс GMT +3, время: 12:29. |