sigmaN 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Нет, физически там один поток и один стек. Хотелось бы посмотреть исходники такого сервера. Это в опэнсоурсе есть? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Хотелось бы посмотреть исходники такого сервера. Это в опэнсоурсе есть? Конечо. При чем написанного на языке Javascript - полностью динамический язык, со сборкой мусора. И это работает в разы быстрее, и в десятки а то и сотню раз меньше памяти и во столько же десятков(а то и сотен) раз больше способно обрабатывать клиентов в секунду, чем сервер на C в классической многопоточной модели:) https://nodejs.org/dist/latest-v4.x/docs/api/http.html const http = require('http'); const net = require('net'); const url = require('url'); // Create an HTTP tunneling proxy var proxy = http.createServer( (req, res) => { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('okay'); }); proxy.on('connect', (req, cltSocket, head) => { // connect to an origin server var srvUrl = url.parse(`http://${req.url}`); var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => { cltSocket.write('HTTP/1.1 200 Connection Established\r\n' + 'Proxy-agent: Node.js-Proxy\r\n' + '\r\n'); srvSocket.write(head); srvSocket.pipe(cltSocket); cltSocket.pipe(srvSocket); }); }); // now that proxy is running proxy.listen(1337, '127.0.0.1', () => { // make a request to a tunneling proxy var options = { port: 1337, hostname: '127.0.0.1', method: 'CONNECT', path: 'www.google.com:80' }; var req = http.request(options); req.end(); req.on('connect', (res, socket, head) => { console.log('got connected!'); // make a request over an HTTP tunnel socket.write('GET / HTTP/1.1\r\n' + 'Host: www.google.com:80\r\n' + 'Connection: close\r\n' + '\r\n'); socket.on('data', (chunk) => { console.log(chunk.toString()); }); socket.on('end', () => { proxy.close(); }); }); }); При чем это еще довольно сложный код, но надеюсь будет понятно как он работает. Если я приведу более простой - то без опыта разработки в подобном стиле точно не поймете Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Слезть с шины, и что делать? Висеть в задаче без дела, и сам не гам и никому не дам? Или отдать управление другой, пусть менее приоритетной, задаче? Как? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
501-й 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Приветствую! Модель SST хорошо работает до того момента, когда с одним и тем же ресурсом нужно работать из потоков с разным приоритетом. Реальный пример: на шине висят пультик и второй МК, связь с которым должна завершиться в течении 300 мкс (каждые 3 мс). Или объединять логику пультика (которая в разных проектах одна и та же) с логикой связи со вторым МК, или разносить по разным потокам с их синхронизацией. Во втором случае при добавлении абонента на шину первые два потока вообще менять не надо. А SST? Илья Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Слезть с шины, и что делать? Висеть в задаче без дела, и сам не гам и никому не дам? Или отдать управление другой, пусть менее приоритетной, задаче? Как? Слесть - значит сказать драйверу, что мы с шины слезли. У нас не должна голова болеть что там с задачами и что будет дальше - этим занимается планировщик и частично - компилятор. Приведу полный код самой процедуры(если ее можно так назвать) стирания. Он немного сложный, поскольку не только шина может быть занята в это время, но и сама флешка. Даже наоборот - шина может быть свободна, а Flash-микросхема в это время будет выполнять внутри себя операцию стирания, а любую другую команду в лучшем случаи отвергнет, а в худшем - заглючит. То есть нам нужны 2 задачи - первая, которая выполнится когда флешка освободится, а вторая - когда шина. // функция занятия шины void Df::setCallback_and_CS(const delegate<void()>& cbk){ // устанавливаем обработчик прерывания DMA Dma::setChannel_onXfrc(spi->dmaChannelRx(), cbk); // устанавливаем chip select DFCS_n_pin::clear(); } // ----- Mass Erase ------ // Описываем задачу class DfMassEraseTask{ public: DfMassEraseTask(Df* df, const delegate<void()>& cbk, SST::TPriority cbk_priority): df(df), cbk(cbk), cbk_priority(cbk_priority) {} // сама функция задачи. будет выполнена, как только Flash станет свободна void operator()(){ // DF_TASK_PRIORITY // Создаем задачу и добавляем в очередь шины SPI bool r = df->spi->enqueueTask([this](){ // SSP_TASK_PRIORITY // занимаем шину df->setCallback_and_CS([this](){ // Handler mode // команда WREN успешно подана, временно снимаем chip-select (так требует документция на Flash) DFCS_n_pin::set(); __nop(); __nop(); // опять устанавливаем CS df->setCallback_and_CS([this](){ // команда ERASE закончилась, слазим с шины DFCS_n_pin::set(); // сигнализируем драйвер шины, что мы с шины слезли. После этого шина может быть испльзована кем-то другим df->spi->taskCompleted(); // Запускаем таймер, который время от времени будет проверять - закончилась операция стирания или нет df->timer.start(11, [this](){ // DF_TASK_PRIORITY // таймер сработал - запускаем проверку df->waitWip(this); }); }); // подаем команду ERASE df->small_buffer[0] = Df::CMD_MASS_ERASE; bool r = df->spi->DmaWriteRead(df->small_buffer, df->small_buffer, 1); if(!r){ // тоже никогда сюда не попадем printf("Df::DfMassEraseTask error: SPI is busy! It must not happen, it's a bug!\n"); } }); // подаем WREN команду через SPI-DMA - для разблокировки записи флеш df->small_buffer[0] = Df::CMD_WREN; bool r = df->spi->DmaWriteRead(df->small_buffer, df->small_buffer, 4); if(!r){ // сюда мы никогда не попадем, а если попали - значит где-то баг в реализации драйвера SPI // поскольку шина по определению должна уже быть свободна printf("Df::DfMassEraseTask error: SPI is busy - bug!\n"); } }); // вдруг очередь переполнена if(!r){ printf("Df::DfMassEraseTask error: spi fifo full\n"); } } public: Df* const df; delegate<void()> cbk; SST::TPriority cbk_priority; }; // функция стирания FLASH bool Df::MassErase( const delegate<void()>& cbk, SST::TPriority cbk_priority = DF_TASK_PRIORITY) { // создаем задачу и добавляем в очередь FLASH bool r = task_queue.enqueueTask( DfMassEraseTask(this, cbk, cbk_priority) ); if(!r){ printf("Df::MassErase error: task fifo full\n"); } // и выходим return r; } // процедура проверки WIP - write/eras in progress void Df::waitWip(DfWriteTask_base* t){ // Thread mode // Создаем задачу и добавляем в очередь шины SPI bool r = spi->enqueueTask([t](){ // Шина свободна - занимаем ее t->df->setCallback_and_CS([t](){ // Handler mode // команда подана - снимаем CS DFCS_n_pin::set(); // окончательно слазим с шины t->df->spi->taskCompleted(); // проверяем if(t->df->small_buffer[2]&1){ // retry // если операция не закончилась(флешка все еще стирается) - опять запускаем таймер t->df->timer.start(11, [t](){ // DF_TASK_PRIORITY t->df->waitWip(t); }); }else{ // если закончилась // сигнализируем пользователя, что все прошло успешно SST::postMessage(t->cbk_priority, t->cbk); // завершаем задачу - теперь воспользоваться flash-кой сможет кто-то другой (кто стоит в очереди) t->df->task_queue.taskCompleted(); } }); // подаем команду через шину(DMA) t->df->small_buffer[0] = CMD_RDSR; bool r = t->df->spi->DmaWriteRead( t->df->small_buffer, t->df->small_buffer, 3); if(!r){ printf("Df::waitWip error: SPI is busy - bug!\n"); } }); // вдруг очередь SPI переполнена if(!r){ printf("Df::waitWip error: spi fifo full\n"); } } Согласен, код довольно сложный. Но кто-то сможет привести более простой? Приведите - и я расскажу какие в вашем коде будут проблемы ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Конечо. При чем написанного на языке Javascript - полностью динамический язык, со сборкой мусора. И это работает в разы быстрее, и в десятки а то и сотню раз меньше памяти и во столько же десятков(а то и сотен) раз больше способно обрабатывать клиентов в секунду, чем сервер на C в классической многопоточной модели Это шутка щас была да? Спасибо, поржал. Так, чисто чтоб вы понимали как внутри JavaScript движок напрягается, чтоб вы тут свои onSomething события обрабатывали ) http://v8project.blogspot.com/ Пруфлинк бы на сравнение быстродействия серверов на JavaScript vs традиционный Сишный ))))) А то может мы тут действительно отстали от жизни совсем. Кстати вам точно будет интересно. Советую сразу окно не закрывать, чувак там дальше показывает реальную магию https://youtu.be/gawmdhCNy-A Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Приветствую! Модель SST хорошо работает до того момента, когда с одним и тем же ресурсом нужно работать из потоков с разным приоритетом. Реальный пример: на шине висят пультик и второй МК, связь с которым должна завершиться в течении 300 мкс (каждые 3 мс). Или объединять логику пультика (которая в разных проектах одна и та же) с логикой связи со вторым МК, или разносить по разным потокам с их синхронизацией. Во втором случае при добавлении абонента на шину первые два потока вообще менять не надо. А SST? Нет, можно с одним и тем же ресурсом работать абсолютно с любого уровня приоритета. Но если шина уже занята более низкоприоритетной задачей, тогда ничего не остается, как добавляться в очередь. Мы не можем прервать, скажем операцию записи в Flash, потому что это может привести к порчи старницы или всего блока/сектора. Но очередь у нас приоритетная - и если приоритет нашей задачи самый высокий он станет в самое начало очереди и как только шина освободится - задача будет выполнена. Так что с шиной можно работать даже из прерываний и одновременно из самых низкоприоритетных потоков(хоть Idle) - какая RTOS даст Вам такую возможность? Если Вы попытаетесь залочить мютекс из прерывания - это либо приведет просто к глюку и крешу всей системы, либо(если ОС написана корректно) - прерывание может быть заблокировано в ожидании этого мютекса - со всеми вытекающими из этого проблемами Это шутка щас была да? Спасибо, поржал. Так, чисто чтоб вы понимали как внутри JavaScript движок напрягается, чтоб вы тут свои onSomething события обрабатывали ) http://v8project.blogspot.com/ Пруфлинк бы на сравнение быстродействия серверов на JavaScript vs традиционный Сишный ))))) А то может мы тут действительно отстали от жизни совсем. Значит Вы не разобрались. Пруфлинк Вам не поможет - давайте сделаем по другому. Я даю Вам 2 исходника - один сишный классический многопоточный, второй на javascript. Вы у себя запускаете, даете реальную нагрузку и смотрите, когда ресурсы системы закончатся при классической многопоточной модели на С, а когда в событийной на Яваскрипте, Ну и в процессе посмотрите, сколько будут занимать памяти оба под реальной нагрузкой(скажем хотя бы 100-200 одновременных коннектов) Для этого Вам понадобятся 2 компа - на одном сервер, на втором клиент. Только клиент должен быть гораздо мощнее сервера, чтобы он был в состоянии дать ему реальную нагрузку. NodeJS надеюсь установите без особого бубна, компилятор C думаю тоже ;) Так, чисто чтоб вы понимали как внутри JavaScript движок напрягается, чтоб вы тут свои onSomething события обрабатывали ) http://v8project.blogspot.com/ В том то и дело, что надо один раз напрячься и сделать, а потом пользоваться сколько угодно раз. Спасибо гуглу за их прекрасный движок и разработчикам NodeJS за то, что сделали из этого движка замечательный мощный, быстрый и удобный инструмент Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Прям с удовольствием потестирую ))))) Особенно создам ситуацию, когда оба сервера получают от клиента запрос требующий интенсивной обработки и буду весело наблюбдать как ваш JavaScript сервер перестанет обслуживать остальных клиентов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба На самом деле мы наверное действительно отстали от жизни. Сейчас цена железа стремится к нулю, а труд программистов такой тенденции не имеет. Посмотрите на тот же Андроид. Та же задача на голом С потребовала бы 400 Мгц (да тот же WinMobile вспомним). Но сейчас не спроста средний проц имеет 8 ядер под 2 ГГц, выходит дешевле и писать проще. Ладно, сие есть лирика, но динозавром выглядеть не хочется. Подозреваю что на SST можно решить ровно теже задачи, что и на обычной ОСи, и чаще всего это будет экономичнее и быстрее. Все же Javascript для эмбеддед старого доброго не слишком показательная и типичная задача. Ну реально смешно опрашивать кнопку в отдельном громоздком потоке в бесконечном цикле со всеми жирными объектами синхронизации. Мне представляется оптимальным некий гибрид обоих подходов к многозадачности. Ну как бы с идеей SST крутится всякая мелкая и не очень логика, а традиционный подход продолжает работать одновременно для не очень связных сложных задач, например веб-сервер крутится, GUI и что еще. На верхнем уровне это три разных задачи для традиционного планировщика, а внутри каждой - подход в духе SST. Может я не уловил сути и написал сейчас бред, тогда сорри. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Все же Javascript для эмбеддед старого доброго не слишком показательная и типичная задача. Javascript очень даже уместен в embedded. Прям с удовольствием потестирую ))))) Отлично, готовлю код. Особенно создам ситуацию, когда оба сервера получают от клиента запрос требующий интенсивной обработки и буду весело наблюбдать как ваш JavaScript сервер перестанет обслуживать остальных клиентов. Мы сейчас говорим об оверхеде на треды, а не о интенсивных математических задачах. О них поговорим позже, и там тоже много чего интересного. JavaScript не предназначен для интенсивных математических вычислений, для этого есть другие прекрасные языки, которые свободно могут работать в паре с Javascript. Так что давайте для начала протестируем оверхед - сервер на C и на JS будет просто принимать коннект и отправлять клиенту какой-нибудь ответ скажем по таймеру, 10 ответов в секунду. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arhiv6 14 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба brag, на сколько я понял, в обычном SST пока задача X не выполнена, менее приоритетные задачи блокированы. В таком случае, если эта задача X заняла ресурс - ту же шину SPI, мы никак не можем отдать управление менее приоритетным процессам и ядро простаивает. Если не сложно, можете подробнее описать, как правильно избавиться от этого ограничения? На сколько я понял, у Вас задача делится на несколько независимых (X1, X2) и они работают по событиям: X1 заняла шину и закончила работу, по событию освобождения шины вызвалась задача X2. Так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Ну как бы с идеей SST крутится всякая мелкая и не очень логика, а традиционный подход продолжает работать одновременно для не очень связных сложных задач, например веб-сервер крутится, GUI и что еще. На верхнем уровне это три разных задачи для традиционного планировщика, а внутри каждой - подход в духе SST. Может я не уловил сути и написал сейчас бред, тогда сорри. Наоборот, веб-сервер и GUI - это типичные задачи для SST и классические потоки здесь только создают проблемы. Да, их можно реализовать на классических потоках, но рано или поздно там появятся ActiveObjet-ы, а это значит, что треды пора выбрасывать в мусорку и переходить на более простой SST. в котором все является этими самыми Active Objectamи Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sigmaN 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Ладно бы товарищ просто говорил что ребят, так проще и времени программиста меньше уходит. Все переходим на JS. Никто б с ним не спорил. Но тут он совсем уже пошел по беспределу, заявив Нет, физически там один поток и один стек. При чем написанного на языке Javascript - полностью динамический язык, со сборкой мусора. И это работает в разы быстрее, и в десятки а то и сотню раз меньше памяти и во столько же десятков(а то и сотен) раз больше способно обрабатывать клиентов в секунду, чем сервер на C в классической многопоточной модели После такого надо бы и пруфы в студию. Потому как JS то и Multi-threading поддерживает так то. Но у нас всё в один стек в один поток и в десятки и сотни раз круче сервер получается ))))))) Мы сейчас говорим об оверхеде на треды, а не о интенсивных математических задачах. О них поговорим позже, и там тоже много чего интересного. JavaScript не предназначен для интенсивных математических вычислений, для этого есть другие прекрасные языки, которые свободно могут работать в паре с Javascript. Так что давайте для начала протестируем оверхед - сервер на C и на JS будет просто принимать коннект и отправлять клиенту какой-нибудь ответ скажем по таймеру, 10 ответов в секунду. Давайте вы наконец осознаете, что классический сервер на то и создает потоки/процессы под кажого клиента, чтобы их обслуживать ПАРАЛЛЕЛЬНО. Параллелизм этот обеспечивается в данном случае таск шедулером операционной системы. О каком овэрхеде на трэды мы говорм, если у вас трэд один и стек тоже ))))) Нет трэдов нет оверхедов. Я уже писал, что сравнивать потребление ресурсов нужно у двух систем обеспечивающих одинаковый функционал. Это мы наконец поймем или нет? У меня создается впечатление, что у вас когда-то не заладилось с многопоточным программирвоанием и вы ушли в секту синглтрэад-одностековщиков ))))))))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба Но у нас всё в один стек в один поток и в десятки и сотни раз круче сервер получается ))))))) Вполне возможно, что так и будет. Потому что при большом наплыве клиентов накладные расходы на создание процесса на каждого клиента будут очень велики. Поэтому и в сях сейчас развивают асинхронное обслуживание сети. (async.io) Процессоры сейчас быстрые, сети толстые, так что проще быстренько обслужить клиента, не создавая для него отдельного процесса, и перейти к следующему. Насчёт жабаскрипта в эмбеддед я пока тоже не понял:) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 8 сентября, 2016 Опубликовано 8 сентября, 2016 · Жалоба brag, на сколько я понял, в обычном SST пока задача X не выполнена, менее приоритетные задачи блокированы. Верно! В таком случае, если эта задача X заняла ресурс - ту же шину SPI, мы никак не можем отдать управление менее приоритетным процессам и ядро простаивает. А это не совсем верно. Если задача постоянно работает с шиной через дрыгание ногами - непрерывно туда что-то передает, тогда да, все задачи с приоритетом таким же или ниже блокированы. А если задача использует DMA или просто прерывания, тогда эта задача будет только обрабатывать эти прерывания, а остальное время будет отдано другим. Если не сложно, можете подробнее описать, как правильно избавиться от этого ограничения? На сколько я понял, у Вас задача делится на несколько независимых (X1, X2) и они работают по событиям: X1 заняла шину и закончила работу, по событию освобождения шины вызвалась задача X2. Так? Тут немножко стоит ввести терминологию. Я то понимаю и мне это естественно, но другим не очень. И так, терминология: 1. Событие(event) - это некоторое абстрактное понятие. Каждое событие имеет приоритет. Прерывание - это тоже событие. 2. Очередь событий(Event Queue) - это такая очередь, в которую можно добавлять события. При чем эти события сортируются в этой очереди в порядке: а) - приоритета б) - поступления Тут есть некоторая оговорка - прерывание - это тоже событие, но размещением их в очереди занимаемся не мы, а процессор. 3. Обработчик события(Event Handler) - это функция связанная с конкретным событием, которая будет выполнена, как только будет для этого время. 4. Планировщик событий - достает события из очереди и выполняет для них соответствующие обработчики. При чем, если какой-то обработчик уже работает - он будет прерван обработчиком более приоритетного события. Планировщик состоит из 2х частей: а) процессора, его контроллера прерываний который занимается планировкой событий приоритета выше или равного IRQ_MIN_PRIORITY. этот приоритет всегда выше приоритета обычных событий(user mode) б) кусок кода на 200 строк, который занимается планировкой событий приоритета ниже IRQ_MIN_PRIORITY - то есть обычных пользовательских событий 5. Задача(Task) - это исполняемый обьект. Она тоже имеет свой приоритет. Задача состоит из: а) обработчика события запуска задачи (обычная функция, физически у меня в С++ это operator() - почитайте про него) б) любого количества обработчиков других событий. То есть задача может добавлять любые собития в очередь, а так же их обрабатывать. в) любого количества внутренних переменных - это называется состояние задачи 6. Очередь задач - это очередь, в которую помещаются задачи в порядке их приоритета, затем в порядке попадания в очередь. С этим все ясно? Но у нас всё в один стек в один поток и в десятки и сотни раз круче сервер получается ))))))) Так Вы тестировать сервак будете, делать для Вас(и остальных) код? или будете продолжать дальше глумиться, не понимая предмета? Вполне возможно, что так и будет. Потому что при большом наплыве клиентов накладные расходы на создание процесса на каждого клиента будут очень велики. Поэтому и в сях сейчас развивают асинхронное обслуживание сети. (async.io) Процессоры сейчас быстрые, сети толстые, так что проще быстренько обслужить клиента, не создавая для него отдельного процесса, и перейти к следующему. Поздравляю, Вы поняли о чем идет речь ;) Насчёт жабаскрипта в эмбеддед я пока тоже не понялsm.gif http://embeddednodejs.com/chapters.html Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться