Я создаю расширение для Firefox, которое позволяет использовать Standard ML (SML) в качестве клиентского языка программирования в Firefox. Это работает следующим образом:
- Расширение запускает процесс PolyML (компилятор SML с интерактивной оболочкой верхнего уровня).
- Затем устанавливается связь через сокет между расширением и процессом PolyML.
- Код SML считывается с веб-страницы и отправляется через сокеты в процесс PolyML для оценки.
- Затем этот код может использовать предоставленную мной библиотеку для работы с DOM.
Вот как реализована библиотека DOM:
- Скажем, кто-то выполняет функцию SML DOM.getElementById
- Этот запрос перенаправляется через сокеты в расширение, где расширение выполняет функцию JavaScript getElementById на странице и отправляет результат обратно в процесс PolyML через сокеты.
Мой вопрос заключается в том, теоретически, какие ограничения с точки зрения производительности я должен ожидать здесь, когда дело доходит до связи через сокет?
Я сделал очень приблизительное профилирование, и кажется, что, используя этот интерфейс между расширением и PolyML, я могу отправить приблизительно 2500 сообщений в секунду со средним размером 70 байт/сообщение.
Чтобы поместить это в больший контекст, предположим, что я хочу нарисовать анимацию в браузере, используя элемент Canvas. Если я хочу получить 20 кадров в секунду, это означает, что мне нужно отрисовывать каждый кадр за 0,05 секунды, что означает, что я могу отправить только около 125 сообщений за кадр. Эти сообщения соответствуют вызовам функций JavaScript. Например, приведенный ниже код рисует путь и выполняет 9 вызовов функций JavaScript, которые соответствуют 9 сообщениям в сокетной связи.
val _ = Canvas.beginPath context; val _ = Canvas.setFillStyle context fillColor; val _ = Canvas.setStrokeStyle context fillColor; val _ = Canvas.setLineWidth context size; val _ = Canvas.moveTo context posx posy; val _ = Canvas.lineTo context posx_new posy_new; val _ = Canvas.stroke context; val _ = Canvas.arc context posx_new posy_new (size/2.0) 0.0 6.28 true; val _ = Canvas.fill context;
JavaScript, очевидно, имеет гораздо лучшую производительность, я полагаю, что вы могли бы сделать тысячи (сотни) вызовов функций Canvas/DOM за эти 0,05 секунды для рисования кадра.
Итак, я думаю, мой вопрос в том, есть ли у вас опыт использования связи через сокеты для очень быстрого обмена сообщениями. Я хотел бы знать, кажется ли правильным 2500 небольших сообщений в секунду (в данном случае, что соответствует 150 кбайтам в секунду) или я делаю что-то очень неправильно.
Например, есть подозрение, что реализация сокета в firefox (в частности, его использование через интерфейс JavaScript https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIServerSocket) не очень подходит для такого быстрого взаимодействия. Например, чтение из сокета выполняется с помощью механизма цикла обработки событий. То есть я полагаюсь на Firefox... чтобы уведомить меня о доступности входящих сообщений сокета, и иногда между отправкой сообщения и его получением возникает большая (например, 250 мс) задержка (хотя, похоже, это происходит только тогда, когда Firefox занят выполнением другие вещи, и меня больше интересуют .. теоретические .. пределы связи через сокет)
Какие-нибудь идеи, какие-нибудь мысли, какие-нибудь недостатки, которые вы видите? Как вы думаете, было бы лучше использовать другие механизмы IPC, например. каналы, реализующие мою коммуникацию из компонента C++ XPCOM, а не из JavaScript, интерфейса внешней функции для C (который есть как в JavaScript, так и в PolyML)?
(Проект находится по адресу https://assembla.com/wiki/show/polymlext, если кто-то интересно)