-Поиск по дневнику

Поиск сообщений в rss_rss_hh_new

 -Подписка по e-mail

 

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 51

Habrahabr/New








Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://habrahabr.ru/rss/new/.
Данный дневник сформирован из открытого RSS-источника по адресу http://feeds.feedburner.com/xtmb/hh-new-full, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

Курсы Computer Science клуба, весна 2017, часть вторая

Вторник, 30 Мая 2017 г. 19:36 + в цитатник

Продолжаем выкладывать видеозаписи курсов Computer Science клуба при ПОМИ РАН. Первая часть здесь. В этом подборке четыре курса: «Коммуникационная сложность», «Экспандеры и их применения», «Машинный перевод» и «Избранные главы теории потоков».

Коммуникационная сложность



Лектор:
Николай Константинович Верещагин, профессор МГУ, член Европейской Академии.
Аннотация
Простейшая модель в теории коммуникационной сложности такова. Имеются два участника (компьютера или человека), которые совместно хотят решить некоторую задачу. Ни один из них самостоятельно решить задачу не может (например, у каждого из них недостаточно данных или ресурсов). Поэтому им необходимо общаться. Коммуникационная сложность измеряет минимально возможное количество битов, которым необходимо обменяться участникам, чтобы решить задачу. Время, необходимое для проведения локальных вычислений каждым из участников, не принимается во внимание — в этом принципиальное отличие от теории сложности вычислений. Результаты из коммуникационной сложности имеют очень широкое применение в других областях теоретической информатики.

Материалы и видео курса.

Экспандеры и их применения



Лектор:
Андрей Евгеньевич Ромащенко, научный сотрудник Института проблем передачи информации РАН в Москве и Лаборатории информатики, робототехники и микроэлектроники (LIRMM) в Монпелье.
Аннотация
Экспандеры (расширяющие графы) являются мощным и весьма изощрённым инструментом теоретической информатики и дискретной математики. По-видимому, эффективность экспандеров отчасти объясняется тем, что они (по самому своему определению) позволяют естественно сочетать комбинаторно-геометрические, алгебраические и вероятностные рассуждения. Экспандеры были определены в 1970-х годах. За прошедшие 30 лет они нашли множество красивых применений. Экспандеры используются в различных конструкциях дерандомизации. С помощью экспандеров строятся коды, исправляющие ошибки, и надёжные вычислительные схемы. Техника экспандеров применяется в различных доказательствах теории сложности вычислений (например, в доказательстве знаменитой PCP-теоремы). В данном курсе мы будем интересоваться экспандерами с точки зрения теории алгоритмов. Мы изучим связь комбинаторных и спектральных свойств экспандеров, рассмотрим эффективные алгоритмические методы построения таких графов, а также обсудим различные применения экспандеров. Мы также поговорим о связи экспандеров с другими замечательными классами графов: экстракторами, дисперсерами, компрессорами.

Материалы и видео курса.

Машинный перевод



Лектор:
Дэвид Талбот, ведущий научный сотрудник Google в Великобритании, преподаватель Школы анализа данных.
Аннотация
Первый день курса знакомит слушателей с проблемой машинного обучения с параллельных данных для автоматического перевода. Слушателям будет предложено реализовать простые алгоритмы для выравнивания слов. Второй день курса будет посвящён основам нейронного машинного перевода. Слушатели смогут получить практический опыт работы с простой моделью кодер-декодер. Будут полезны начальные навыки Python и умение компилировать и запускать код с github. Курс читается на английском языке.

Материалы и видео курса.

Избранные главы теории потоков



Лектор:
Максим Александрович Бабенко, доцент Высшей школы экономики, преподаватель Школы анализа данных, сотрудник Яндекс.
Аннотация
Теория потоков, без сомнения, представляет собой один из наиболее хорошо изученных разделов комбинаторной оптимизации, имеющий разнообразные приложения, как теоретические, так и практические. Курс начнется с краткого введения в предмет, в котором мы разберем базовые алгоритмы для задачи о максимальном потоке, а затем быстро перейдем к более современным темам: проталкиванию предпотока и параметрическим потоковым задачам. В заключительной части курса коснемся обобщений понятия потока: изучим простейшие виды мультипотоковых задач, а также поговорим о потоках в кососиметрических и двунаправленных графах. От слушателей предполагается знакомство с базовыми понятиями алгоритмической теории графов.

Материалы и видео курса.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329828/


Метки:  

Вебинар Linux on Azure и подборка материалов Open Source & Microsoft

Вторник, 30 Мая 2017 г. 19:24 + в цитатник


Привет! Завтра мы проводим вебинар «Linux на Microsoft Azure».. Конечно же, я, как докладчик на этом вебинаре, расскажу больше, чем обзор Open Source предложений в облаке. Будет про то, зачем, сколько и как мы тратим на поддержку Open Source как компания, про локальные и гибридные решения, поделив вебинар на две части – для разработчиков и не-разработчиков. Расскажу о внутреннем глобальном сообществе Open Source, успешно действующем в Microsoft, лидером коего являюсь. А ниже, под катом, мы совместными усилиями сделали подборку материалов Open Source + Microsoft. Регистрируйтесь и приходите, в общем, постараемся сделать интересно. :)

Работа с Linux в облаке Azure


Курс Microsoft Virtual Academy на русском языке, который поможет сделать первые шаги в Linux + Azure. Он включает в себя большое число демонстраций и практических рекомендаций.



Он состоит из следующих разделов:
1. Linux в Azure – обзор
В этом модуле рассмотрены основы облачной платформы Azure. Основное внимание сосредоточено на сервисе виртуальных машин, а именно — на запуске Linux виртуальных машин в облаке Azure.

2. Сетевое взаимодействие виртуальных машин Linux в Azure
В этом модуле рассмотрены основные моменты сетевого взаимодействия в Azure, а именно — создание нескольких виртуальных машин для обслуживания веб сайта, горизонтальное масштабирование и так далее.

3. Управление Linux VM в облаке Azure ч.1: Azure Management Portal
В этом модуле рассмотрены основные принципы работы с порталом Azure. Портал Azure — это веб приложение, следовательно, работать с ним можно практически с любого устройства.

4. Управление Linux VM в облаке Azure ч.2: Azure Powershell
В этом модуле рассмотрены команды PowerShell для работы с Azure. В модуле показано как можно установить себе команды PowerShell для работы с Azure и как подключить их к своей Azure подписке.

5. Управление Linux VM в облаке Azure ч.3: Azure Command Line interface
В этом модуле рассмотрены основные принципы работы с утилитами командной строки для Azure. В модуле показано как можно установить себе утилиты командной строки и как подключить их к Azure.

6. Управление Linux VM в облаке Azure ч.4: Инструменты Cerebrata Tools
В этом модуле рассмотрены такие утилиты компании Cerebrata, как Azure Explorer, Azure PowerShell и Azure Management Studio. Все эти инструменты позволяют нам намного комфортнее работать с Azure.

7. Хранение данных в Azure - диски и распределенные файловые системы
В этом модуле рассмотрены все доступные возможности хранения данных Linux виртуальных машин в облаке Azure (Blob хранилище, Azure диски, распределенная файловая система GlusterFS в Azure и так далее).

Построение Linux кластеров в Azure


Русскоязычный курс Microsoft Virtual Academy, посвящённый погружению в работу со множеством виртуальных машин под Linux, размещённых в облаке Azure, и сконфигурированные для совместного решения одной задачи.



Он состоит из следующих разделов:
1. Типы кластеров, кластер балансировки нагрузки
В начале рассматриваются различные типы Linux-кластеров, подходы к их построению и задачи, которые они решают. Обзорно рассматривается архитектура Linux-кластера балансировки нагрузки.

2. Отказоустойчивый и вычислительный кластеры
Теория, вторая часть: отказоустойчивый и вычислительный кластеры. Подробнее об устройстве кластера отказоустойчивости и вычислительного кластера.

3. Настройка кластера отказоустойчивости в облаке
Пример создания кластера отказоустойчивости в IaaS-облаке Azure. Отказоустойчивое хранилище DRBD. Прикладное программное обеспечение: MySQL-сервер.

4. Настройка доступа к кластеру снаружи облака, настройка STONITH
В этой части подробно показано, как выполнить проверку работоспособности кластера в различных режимах; настройку множественного endpoint; настройку STONITH и проверку правильности его работы.


Полезные материалы


Общие сведения об Azure и Linux: базовые сведения об облаке Azure (размеры виртуальных машин, квоты, регионы и так далее) и его взаимодействии с Linux.

Создание виртуальной машины Linux с помощью Azure CLI: в этом руководстве описывается, как с помощью Azure CLI развернуть виртуальную машину под управлением сервера Ubuntu. После развертывания сервера создается подключение по протоколу SSH и устанавливается веб-сервер NGINX.

Сэмплы Azure CLI для виртуальных машин Linux.

Создание виртуальной машины Linux с помощью портала Azure: в этом кратком руководстве содержатся пошаговые инструкции по созданию виртуальной машины и установке веб-сервера на этой виртуальной машине.

Создание виртуальной машины Linux с помощью PowerShell: в этом руководстве описывается, как с помощью модуля Azure PowerShell развернуть виртуальную машину под управлением сервера Ubuntu. После развертывания сервера создается подключение по протоколу SSH и устанавливается веб-сервер NGINX.

Сэмплы PowerShell для виртуальной машины Azure.

Подробный пошаговый туториал по созданию виртуальных машин Linux и управлению ими с помощью Azure CLI.

Справочные материалы


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329832/


Метки:  

Как учится и отвечает на вопросы когнитивная система IBM Watson. Часть 1

Вторник, 30 Мая 2017 г. 18:52 + в цитатник


За последний десяток лет технологии шагнули далеко вперед. Интернет вещей, облачные системы, формы искусственного интеллекта, нейросети и когнитивные технологии. Все это появилось относительно недавно, но все это активно меняет нашу жизнь. IBM прикладывает значительные усилия, чтобы изменения были положительными. Делается все это не удовольствия ради, а с вполне практической целью. Дело в том, что потребности современной науки и бизнеса чрезвычайно велики. И для того, чтобы эти потребности удовлетворять, необходимы новые инструменты. Один из них — IBM Watson, когнитивная платформа, которая способная учиться, выявлять связи между отдельными элементами крупнейшего массива данных, а также взаимодействовать со своим окружением, включая пользователей.

На Habrahabr и Geektimes наша компания не раз рассказывала о том, какую пользу может принести IBM Watson. Но как работает система? В целом, ее возможности основаны на анализе окружающей среды и различных факторов. Благодаря этому платформа способна принимать определенные решения и давать ответы на задаваемые вопросы. Ниже – относительно краткое изложение принципов работы нескольких составляющих работы когнитивной системы. Это обучение, обработка языка и ответы на вопросы.

Как Watson обучается


Ключевые элементы работы когнитивной системы –эмулирование некоторых особенностей мышления человека, которые задействуются во время принятия решения и ответов на вопросы.

Обучение Watson ведется в несколько этапов. Самый первый — это загрузка информации. Разработчики системы пытаются сделать ее пригодной для использования в любых областях науки, техники… да чего угодно.




Все начинается с загрузки релевантной информации по определенной тематике в базу данных Watson. Здесь можно вспомнить Шерлока Холмса и его объяснение эффективности дедуктивного метода и важности релевантных знаний. Холмс, изучая определенный вопрос, «загружал» в память лишь информацию, которая непосредственно касалась этого вопроса. То же и с Watson — когда разработчики принимают решение обучить систему новому предмету, то загружают в память исключительно релевантную информацию, имеющую отношение к тематике обучения. Устаревшие и не слишком релевантные данные выверяются и отсеиваются. Это постоянный процесс.

Затем наступает очередь IBM Watson — начинается предварительная обработка данных с построением индексов и других метаданных, позволяющих более эффективно работать в дальнейшем. Создается «граф знаний» для представления ключевой концепции осваиваемого материала.

По завершению предварительной обработки данных снова начинают работать люди, которые помогают Watson интерпретировать полученные данные. Это делается при помощи машинного обучения, когда эксперт начинает работать с системой в форме вопрос-ответ. Такой метод помогает создавать лингвистические паттерны, относящиеся к изучаемой теме.

Еще один способ обработки и усвоения данных – постоянное взаимодействие Watson с пользователями. Эксперты регулярно оценивают эту активность и помогают Watson совершенствовать свои возможности, отвечать на все более сложные вопросы, обновлять ранее полученную информацию.Цель разработчиков — научить когнитивную систему Watson отвечать на вопросы примерно так, как это делает человек. То есть эмулировать принятие решений человеком. Это нужно как науке, медицине, так и бизнесу.

Речь, фактически, идет о «динамическом обучении», когда Watson становится умнее, получая обратную связь от пользователей и разработчиков, обучаясь на собственных ошибках.

Как Watson работает с естественным языком?


Вне зависимости от того, задается вопрос устно или письменно, системе необходимо уметь анализировать сложные смысловые конструкции, понимая не только смысловую, но и эмоциональную нагрузку текста. Для того, чтобы Watson мог правильно определять смысл текста, разработчики интегрировали в систему вопросно-ответную систему контентной аналитики (Deep Question*Answering, DeepQA). Это основа основ, на этой системе строится работа когнитивной платформы.




Благодаря ей Watson может понимать, что ему говорят, и давать адекватный и релевантный ответ. А ведь для машины понять язык человека чрезвычайно сложно. Многие определения слов и термины нелогичны. Взять то же выражение «сгореть со стыда» — человек прекрасно его понимает (если, конечно, слышал ранее). Для машины это выражение — нонсенс, если эта машина не Watson. Разработчики системы постепенно обучают Watson понимать идиомы, устанавливая лексические связи и строя паттерны, о чем уже говорилось выше.

Кроме всего прочего, система умеет распознавать и эмоциональное наполнение текста. Для этого в 2016 году были добавлены сразу три API: ToneAnalyzer, EmotionAnalysis и VisualRecognition. Обновлен сервис TexttoSpeech (TTS) с получением новых возможностей по эмоциям, а также открыт доступ к API речевого модуля Expressive TTS (работа над ним велась в течение 12 лет). В целом, модули и сервисы, которые помогают системе работать с естественным языком, разрабатываются и добавляются постоянно. Это – одна из составляющих динамического обучения, о чем говорилось выше. Постоянный прогресс, развитие – одна из задач проекта, которая вполне успешно выполняется.


Один из примеров анализа смыслового и эмоционального наполнения письма системой IBM Watson

Watson теперь умеет определять стиль изложения в тексте, идентифицировать эмоции, включая позитивные и негативные, а также распознавать и классифицировать изображения.

Как Watson отвечает на вопросы?


Если упрощенно, то все выглядит следующим образом.

1. Для того, чтобы система могла отвечать на какой-либо вопрос, в ее памяти должны быть релевантные данные. Об этом уже говорилось выше. Эксперты загружают различную информацию в систему, где эти данные индексируются для того, чтобы при необходимости ими можно было воспользоваться.
2. Далее вопросы отсылаются системе в текстовой или голосовой форме.
3. Вопросы анализируются системой, Watson выделяет поисковый запрос и начинает искать необходимую релевантную информацию в своей базе данных. Это можно сравнить с тем, как работает Google.
4. Генерируется ряд гипотез путем анализа фраз, которые с определенной долей вероятности могут содержать нужный ответ. Выполняется глубокое сравнение языка вопроса и языка каждого из возможных вариантов ответов. Формируется база результатов поискового запроса.
5. Каждый результат оценивается определенным образом, получая балл. При этом анализируется, в какой степени ответ релевантен области вопроса.
6. Чем выше балл одного из ответов, тем выше он ранжируется.
7. Если Watson после финального анализа считает своей ответ релевантным и актуальным, он предоставляется пользователю.

Реальный процесс поиска ответа на вопрос гораздо сложнее, поскольку каждая фраза прорабатывается при помощи нескольких алгоритмов, работающих, зачастую, в параллельном режиме. Для Watson разработаны сотни алгоритмов логического вывода. Некоторые из них выполняют поиск совпадающих терминов и синонимов, другие — рассматривают временные и пространственные особенности, а третьи — ищут и анализируют необходимые источники контекстуальной информации.



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

Завершая этот материал, стоит отметить, что статья раскрывает далеко не все интересующие наших читателей вопросы. Пожалуйста, задавайте вопросы в комментариях, а мы будем собирать ответы наших специалистов и публиковать сборные материалы «по мотивам» комментариев. Это, наверное, один из лучших вариантов ответить на действительно интересующие вас вопросы.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329826/


Метки:  

[Перевод] 11 вещей которые я узнал, читая спецификацию flexbox

Вторник, 30 Мая 2017 г. 18:05 + в цитатник

Я всегда считал, что с flexbox довольно легко работать — глоток свежего воздуха после стольких лет float'ов и clearfix'ов.


Правда недавно я обнаружил что борюсь с ним; что-то растягивалось, когда я не думал, что оно должно тянуться. Я поправил здесь, другой элемент сжался. Я починил это, что-то другое ушло за экран. Что во имя Джорджа Буша происходит?


В конце концов, все заработало, но солнце село, а мой процесс был привычной игрой с CSS. Или… как называется та игра, где надо ударить крота, а затем другой крот выпрыгивает и надо ударить и его тоже?


Как бы там ни было, я решил что пора вести себя как взрослый разработчик и выучить flexbox должным образом. Но вместо того, чтобы прочитать 10 очередных блог-постов, я решил отправиться прямиком к исходнику и прочитать The CSS Flexible Box Layout Module Level 1 Spec


Вот хорошие отрывки.



1. Margin обладает особыми силами


Я думал, что если, например, ты хочешь заголовок с логотипом и названием сайта слева, а кнопкой логина справа...



… тебе следует дать названию flex: 1, чтобы прижать остальные элементы к другому концу строки.


Вот почему flexbox — Очень Хорошая Вещь. Простые вещи такие простые.


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


Отличные новости! Вместо этого, ты можешь сказать прямо: «прижми этот элемент вправо», определив margin-left: auto на нужном элементе. Думай об этом как о float: right.


Например, если элемент слева является изображением:



Мне не нужно применять flex к изображению, мне не нужно применять space-between к flex-контейнеру, я просто установлю margin-left: auto на кнопке «Войти» («Sign in»):


.header {
  display: flex;
}
.header .logo {
  /* nothing needed! */
}
.header .sign-in {
  margin-left: auto;
}

Тебе может показаться это некоторым хаком, но нет, это прямо там в обзоре спецификации как способ прижать flex-элемент в конец flexbox'а. У способа даже есть своя глава: "Выравнивание с авто margin'ами".


О, мне также следует здесь упомянуть, что я предполагаю flex-direction: row везде в этом блог-посте, но все применимо также и к row-reverse или column или column-reverse.



2. min-width имеет значение


Возможно, ты думаешь, что несложно заставить все flex-элементы внутри flex-контейнера сжиматься, для того чтобы уместить контент. Наверняка, если ты укажешь flex-shrink: 1 на элементах, они так и будут себя вести, правда?


Может, пример.


Скажем, у тебя есть часть DOM, которая отображает книгу на продажу и кнопку чтобы ее купить.


Любопытная бабочка
Спойлер: бабочка умрет в конце.

Ты разместил все с помощью flexbox и все хорошо.


.book {
  display: flex;
}
.book .description {
  font-size: 30px;
}
.book .buy {
  margin-left: auto;
  width: 80px;
  text-align: center;
  align-self: center;
}

(Поскольку ты хочешь кнопку «Купить» справа — даже для очень коротких названий — ты, будучи умным, указал margin-left: auto)


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


И потом получаешь неприятный сюрприз. Совсем не хорошего рода.


Некий маппет, много о себе возомнивший, написал книгу с длинным словом в названии.



Все сломано!


Если красная граница обозначает ширину смартфона, и ты скрываешь переполнение (overflow: hidden), ты только что потерял свою кнопку «Купить». Твой коэффициент конверсии — как и эго бедного автора — будет страдать.


(Примечание: к счастью, там где я работаю, есть хорошая QA команда, которая наполнила нашу базу данных разнородным текстом, наподобие такого. В частности, именно эта проблема побудила меня прочитать спецификацию.)


Оказывается, такое поведение происходит из-за того, что min-width элемента описания изначально установлена в auto, что в данном случае равняется ширине слова Electroencephalographically (электроэнцелографически). Flex-элементу буквально не разрешается быть уже чем это слово.


Решение? Переопределить эту проблемную минимальную ширину min-width: auto установив min-width: 0, указывая flexbox'у, что этот элемент может быть уже, чем содержимое внутри него.


Теперь за управление текстом внутри элемента отвечаешь ты. Я предлагаю перенести слово. Таким образом, твой CSS будет выглядеть так:


.book {
  display: flex;
}
.book .description {
  font-size: 30px;
  min-width: 0;
  word-wrap: break-word;
}
.book .buy {
  margin-left: auto;
  width: 80px;
  text-align: center;
  align-self: center;
}

Результат будет таким:



Опять же, min-width: 0 не какой-то хак для обхода нелепости, это предлагаемое поведение прямо в спецификации.


В следующей секции, я вернусь к тому, что кнопка «Купить» совсем не 80 пикселей по ширине, как я довольно ясно ей сказал.



3. Авторы flexbox обладают хрустальным шаром


Как вы возможно знаете, свойство flex является краткой записью flex-grow, flex-shrink и flex-basis.


Должен признать, я потратил энное количество минут, гадая-проверяя различные значения для этой тройки, когда пытался заставить элементы тянуться так, как надо мне.


Что я не знал до сей поры, это то, что, в общем случае, я хочу одну из трех комбинаций:


  • Если я хочу, чтобы элемент немного сжимался, когда места недостаточно, но не тянулся шире чем ему надо: flex: 0 1 auto
  • Если мой flex-элемент должен тянуться для заполнения всего доступного пространства, и немного сжиматься если места не хватает: flex: 1 1 auto
  • Если мой элемент не должен менять размеры совсем: flex: 0 0 auto

Надеюсь, что ты пока не на максимальном изумлении — сейчас станет еще поразительнее.


Видишь ли, Бригада Flexbox'а (мне нравится думать, что команда flexbox'а носит кожаные куртки с этой надписью сзади — доступны мужские и женские размеры). Где там было это предложение? Ах да, Бригада Flexbox'а знала, что я хочу эти три комбинации свойств в большинстве случаев. Поэтому они дали им ключевые слова специально для меня.


Первый случай — это значение initial так что ключевое слово не нужно. Для второго случая используется flex: auto, и flex: none замечательно простое решение чтобы элемент не тянулся совсем.


Кто бы мог подуть! (Who woulda thunk it — игра слов, прим. переводчика)


Это как если бы было box-shadow: garish, что по умолчанию равнялось 2px 2px 4px hotpink потому что считалось «полезным значением по умолчанию».


Вернемся к невероятно уродливому книжному примеру. Чтобы сделать ту кнопку «Купить» постоянно толстой для нажатия пальцем...



… мне всего лишь надо задать на ней flex: none:


.book {
  display: flex;
}
.book .description {
  font-size: 30px;
  min-width: 0;
  word-wrap: break-word;
}
.book .buy {
  margin-left: auto;
  flex: none;
  width: 80px;
  text-align: center;
  align-self: center;
}

(Да, я мог бы указать flex: 0 0 80px; и сэкономить строку CSS. Но есть что-то особенное в том, как ясно flex: none демонстрирует намерение кода. Это хорошо для Будущего Дэвида который забудет как это все работает.)



4. Есть такая вещь inline-flex


По правде говоря, я узнал, что есть такая вещь как display: inline-flex несколько месяцев назад. И то, что она создаст инлайновый flex-контейнер, вместо блочного.


Но по моей оценке, 28% людей еще не знали этого, так что… теперь знайте, нижние 28%.



5. vertical-align не влияет на flex-элемент


Возможно это то, что я знал наполовину, но я уверен, что в какой-то момент, когда пытался задать правильное выравнивание, я мог испробовать vertical-align: middle и пожать плечами, когда это не сработало.


Теперь я знаю наверняка, прямо из спецификации, что "вертикальное выравнивание не влияет на flex-элемент" (так же как и float, замечу).



6. Не используй margin или padding в %


Это не просто уровня «лучшая практика», это уровня «совет-от-бабушки», так что просто делай что говорят и не задавай вопросов.


«Авторам следует полностью избегать использования процентов в padding'ах или margin'ах на flex-элементах» — с любовью, спецификация flexbox.


За этим следует моя самая любимая цитата из всех, когда-либо существовавших, спецификаций:


Заметка: это разночтение отстой, но оно в точности отражает текущее состояние мира (нет консенсуса среди реализаций, и нет консенсуса внутри CSSWG)...

Осторожно! Бомбардировка честностью продолжается.



7. Margin'ы соседних элементов не схлопываются


Возможно, ты уже знаешь, что margin'ы иногда объединяются вместе. Ты также можешь знать, что margin'ы не объединяются вместе в некоторых других случаях.


И теперь мы все знаем, что margin'ы соседних flex-элементов никогда не объединяются.



8. z-index работает даже если position: static


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


Однажды в моем доме будет другой человек, который скажет типа «эй, у тебя есть лимонный сок?», а я типа «конечно, в холодильнике», а он «спасибо, приятель. Эй, а надо ли мне указывать position если я хочу задать z-index на flex-элементе?», и тут я такой «не братан, не для flex-элементов».



9. Flex-basis тонкое и важное свойство


Когда твои требования перерастут ключевые слова initial, auto и none, все станет немного сложнее, и теперь, когда я понял flex-basis, забавно, знаешь, я не могу придумать как закончить это предложение. Оставь комментарий, если у тебя есть идеи.


Если у тебя есть три flex-элемента с flex-значениями 3, 3, 4, тогда они гарантированно займут 30%, 30% и 40% доступного пространства, независимо от их содержимого, если их flex-basis равен 0. И только если он равен нулю.


Тем не менее, если ты хочешь чтобы flex вел себя в более дружественной, предсказуемой манере, используй flex-basis: auto. В этом случае flexbox примет твои flex-значения во внимание, но также учтет и другие факторы, подумает немного, и подберет ширины, подходящие по его мнению тебе.


Взгляни на эту четкую диаграмму из спецификации:



Я уверен, что это упомянуто по меньшей мере в одном из блог-постов про flex, которые я читал, но по какой-то причине, не проникся пока не увидел эту картинку в спецификации (schmick pick in the spec)(тройная рифма если ты из Новой Зеландии).



10. align-items: baseline


Когда я хотел выравнять flex-элементы по вертикали, я всегда использовал align-items: center. Но также как с vertical-align, у тебя есть возможность установить значение в baseline, что может быть более подходящим если у твоих элементов различный размер шрифта, а ты хочешь выравнять их базу.


Возможно очевидно, align-self: baseline тоже работает.



11. Я довольно глуп


Сколько бы раз я не читал следующий параграф, я остался неспособным его понять...


Размер содержимого — это минимальный размер содержимого на основной оси, зажатый, если он имеет соотношение сторон, с помощью любых определенных минимальных и максимальных свойств кросс-размера, преобразованных через соотношение сторон, а затем дополнительно зажатых с помощью свойства максимального основного размера, если это определено.

Оригинальный вариант
The content size is the min-content size in the main axis, clamped, if it has an aspect ratio, by any definite min and max cross size properties converted through the aspect ratio, and then further clamped by the max main size property if that is definite.

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


Как будто Минни Маус и Мэд Макс завели ребенка семь лет назад, и теперь он, будучи пьяным с мятного шнапса, оскорбляет всех в пределах слышимости словами, которые он узнал когда Мамочка и Папочка ругались.


Леди и Джентльмены, мы начали наш спуск в чепуху, что значит пришло время подвести итоги (или перестань читать, если ты здесь для изучения нового).




Самое интересное из того, что я узнал, читая спецификацию, это то, насколько неполным было мое понимание, несмотря на полдюжины блог-постов которые я прочитал, и на то, насколько относительно простым является flexbox. Оказывается, что «опыт» — это не просто занятие одним и тем же из года в год.


С удовольствием могу отметить, что время, потраченное мной на чтение, уже окупилось. Я прошелся по старому коду, выставил авто margin'ы, flex-значения в краткой записи auto или none, и задал минимальную ширину в ноль там, где это было нужно.


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


Еще я узнал, что несмотря на то, что спецификация — местами — перенасыщена и предназначена для вендоров как я и думал, все же содержит много дружественных слов и примеров. В ней даже выделены части которые скромные веб-разработчики могут пропустить.


Однако это спорный вопрос, потому что я рассказал тебе про все хорошие отрывки, так что тебе не нужно утруждать себя ее чтением.


Теперь, если позволите, мне надо идти и прочитать все остальные CSS спецификации.


P.S. Я крайне рекомендую прочитать следующий список всех flexbox багов по браузерам:
github.com/philipwalton/flexbugs




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


Оригинальный пост здесь: hackernoon.com/11-things-i-learned-reading-the-flexbox-spec-5f0c799c776b

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329820/


Метки:  

Инвентаризация SCCM

Вторник, 30 Мая 2017 г. 17:57 + в цитатник
При слове «инвентаризация» обычный человек вспоминает ситуацию, когда придя в магазин, видишь табличку на закрытой двери и думаешь, что тебе придётся пройти ещё несколько домов, а в худшем случае и кварталов, чтобы купить необходимое. Необычный человек, работающий с Microsoft System Center Configuration Manager, при упоминании этого слова, представляет кипу проблем, связанных с достоверностью получаемых результатов. Про их решение мы и поговорим под катом.



Передаю слово автору.

Здравствуйте коллеги. Каждый администратор, работающий с Microsoft System Center Configuration Manager (далее ConfigMgr), повседневно использует функционал инвентаризации (Inventory). Это базовый функционал, который собирает данные об управляемой среде и в дальнейшем это используется для построения коллекций, запросов, отчетов. При кажущейся легкости настройки и использования функционала инвентаризации, администраторы ConfigMgr сталкиваются с постоянными проблемами с достоверностью получаемых результатов. Задача статьи — дать полное понимание, как работает инвентаризация, как выявлять и как решать проблемы. По сути постараюсь максимально подробно рассмотреть «что есть под капотом».

Disclaimer


Прежде чем уйдём вглубь, необходимо обговорить маленький disclaimer. ConfigMgr работает как с Windows операционными системами, так и с Linux/Unix (используя nanoWbem), c мобильными системами. ConfigMgr изначально развивался как продукт по управлению Windows ОС, поэтому для полноценного технического охвата в статье будем рассматривать только клиентов, под управлением ОС Windows. Если есть интерес к пониманию, как работает инвентаризация для Linux/Unix — пишите в комментариях, подумаю над написанием статьи. Теперь перейдём к самому интересному.

Перейдём к инвентаризации


ConfigMgr имеет два разных типа инвентаризации — hardware inventory (в русскоязычной документации — инвентаризация оборудования) и software inventory (соответственно инвентаризация программного обеспечения). В статье я буду использовать англоязычные названия. Ключевой момент здесь то, что по сути «название не соответствует содержимому». И это причина одной из главных ошибок администраторов. По сути, hardware inventory — это WMI инвентаризация, а software inventory — файловая инвентаризация (сбор свойств файлов по заданной маске). Именно поэтому список установленного ПО ConfigMgr собирает через hardware inventory — эта информация находится в WMI классах (частично в дефолтовых, частично в ConfigMgr client WMI классах).

На практике более используемая и более критичная для успешного выполнения повседневных задач — hardware inventory. Поэтому в данной статье пристально рассматриваем именно её.
Для использования данного функционала необходимо, чтобы в настройках клиентов (client settings --> Hardware inventory) на стороне Primary site было значение «enable», настроено расписание, выбраны WMI классы, информацию из которых необходимо собрать (часть классов включены по умолчанию). Полное описание WMI классов есть на MSDN.

ConfigMgr использует файл Configuration.mof, расположенный в \inboxes\clifiles.src\hinv, в котором указывает используемые WMI provider, WMI классы. Когда клиент по расписанию обращается на сервер (к точке управления — management point), он скачивает политику, к которой прикреплен данный файл и компилит его локально. После этого, исходя из расписания, ConfigMgr client запускает процесс hardware inventory (далее по тексту hinv).

Здесь необходимо сделать маленькое отступление. ConfigMgr client состоит из движка (engine) и агентов, каждый из которых отвечает за определенный функционал. При этом, СonfigMgr клиент использует trigger codes (cписок можно посмотреть здесь) для запуска каких-либо действий со своими агентами. Для запуска hinv агента используется trigger code {00000000-0000-0000-0000-000000000001}.

На клиенте будет происходит следующая последовательность действий:


1. Запуск hinv по расписанию. В inventoryagent.log будет следующая запись:
Inventory: Opening store for action {00000000-0000-0000-0000-000000000001}…
Inventory: Action=Hardware, ReportType=Delta, MajorVersion=1, MinorVersion=5

ReportType — тип отсылаемого на Primary site отчета (Delta или FULL). FULL — в отчёте будет вся информация, которая собрана (по умолчанию отправляется при первой инвентаризации). Delta — отчёт, который содержит лишь изменения со времени предыдущей hinv. Использование Delta report позволяет уменьшить размер пересылаемой по сети информации.

2. Сбор данных из WMI:
……

https://habrahabr.ru/post/329792/


Метки:  

[recovery mode] Оценка качества алгоритмов распознавания лиц

Вторник, 30 Мая 2017 г. 17:52 + в цитатник
Привет, Хабр!

Мы, в компании NtechLab, занимаемся исследованиями и разработкой продуктов в области распознавания лиц. В процессе внедрения наших решений мы часто сталкиваемся с тем, что заказчики не очень ясно представляют себе требования к точности алгоритма, поэтому и тестирование того или иного решения для их задачи даётся с трудом. Чтобы исправить ситуацию, мы разработали краткое пособие, описывающее основные метрики и подходы к тестированию, которыми хотелось бы поделиться с сообществом Хабра.




В последнее время распознавание лиц вызывает все больше интереса со стороны коммерческого сектора и государства. Однако корректное измерение точности работы таких систем – задача непростая и содержит массу нюансов. К нам постоянно обращаются с запросами на тестирование нашей технологии и пилотными проектами на ее основе, и мы заметили, что часто возникают вопросы с терминологией и методами тестирования алгоритмов применительно к бизнес-задачам. В результате для решения задачи могут быть выбраны неподходящие инструменты, что приводит к финансовым потерям или недополученной прибыли. Мы решили опубликовать эту заметку, чтобы помочь людям освоиться в среде специализированных терминов и сырых данных, окружающих технологии распознавания лиц. Нам хотелось рассказать об основных понятиях в этой области простым и понятным языком. Надеемся, это позволит людям технического и предпринимательского склада говорить на одном языке, лучше понимать сценарии использования распознавания лиц в реальном мире и принимать решения, подтвержденные данными.

Задачи распознавания лиц


Распознаванием лиц часто называют набор различных задач, например, детектирование лица на фотографии или в видеопотоке, определение пола и возраста, поиск нужного человека среди множества изображений или проверка того, что на двух изображениях один и тот же человек. В этой статье мы остановимся на последних двух задачах и будем их называть, соответственно, идентификация и верификация. Для решения этих задач из изображений извлекаются специальные дескрипторы, или векторы признаков. В этом случае задача идентификации сводится к поиску ближайшего вектора признаков, а верификацию можно реализовать с помощью простого порога расстояний между векторами. Комбинируя эти два действия, можно идентифицировать человека среди набора изображений или принимать решение о том, что его нет среди этих изображений. Такая процедура называется open-set identification (идентификацией на открытом множестве), см. Рис.1.


Рис.1 Open-set identification

Для количественной оценки схожести лиц можно использовать расстояние в пространстве векторов признаков. Часто выбирают евклидово или косинусное расстояние, но существуют и другие, более сложные, подходы. Конкретная функция расстояния часто поставляется в составе продукта по распознаванию лиц. Идентификация и верификация возвращают разные результаты и, соответственно, разные метрики применяются для оценки их качества. Мы подробно рассмотрим метрики качества в последующих разделах. Помимо выбора адекватной метрики, для оценки точности алгоритма понадобится размеченный набор изображений (датасет).

Оценка точности


Датасеты


Почти всё современное ПО для распознавания лиц построено на машинном обучении. Алгоритмы обучаются на больших датасетах (наборах данных) с размеченными изображениями. И качество, и природа этих датасетов оказывают существенное влияние на точность. Чем лучше исходные данные, тем лучше алгоритм будет справляться с поставленной задачей.

Естественный способ проверить, что точность алгоритма распознавания лиц соответствует ожиданиям, это измерить точность на отдельном тестовом датасете. Очень важно правильно выбрать этот датасет. В идеальном случае организации стоит обзавестись собственным набором данных, максимально похожим на те изображения, с которыми система будет работать при эксплуатации. Обратите внимание на камеру, условия съемки, возраст, пол и национальность людей, которые попадут в тестовый датасет. Чем более похож тестовый датасет на реальные данные, тем более достоверными будут результаты тестирования. Поэтому часто имеет смысл потратить время и средства для сбора и разметки своего набора данных. Если же это, по какой-то причине, не представляется возможным,  можно воспользоваться публичными датасетами, например, LFW и MegaFace. LFW содержит только 6000 пар изображений лиц и не подходит для многих реальных сценариев: в частности, на этом датасете невозможно измерить достаточно низкие уровни ошибок, как мы покажем далее. Датасет MegaFace содержит намного больше изображений и подходит для тестирования алгоритмов распознавания лиц на больших масштабах. Однако и обучающее, и тестовое множество изображений MegaFace’a есть в открытом доступе, поэтому использовать его для тестирования следует с осторожностью.

Альтернативный вариант заключается в использовании результатов тестирования третьим лицом. Такие тестирования проводятся квалифицированными специалистами на больших закрытых датасетах, и их результатам можно доверять. Одним из примеров может служить NIST Face Recognition Vendor Test Ongoing. Это тест, проводимый Национальным Институтом Стандартов и Технологий (NIST) при Министерстве торговли США. “Минус” данного подхода заключается в том, что датасет организации, проводящей тестирование, может существенно отличаться от интересующего сценария использования.

Переобучение


Как мы говорили, машинное обучение лежит в основе современного ПО для распознавания лиц. Одним из распространенных феноменов машинного обучения является т.н. переобучение. Проявляется он в том, что алгоритм показывает хорошие результаты на данных, которые использовались при обучении, но результаты на новых данных получаются значительно хуже.

Рассмотрим конкретный пример: представим себе клиента, который хочет установить пропускную систему с распознаванием лиц. Для этих целей он собирает набор фотографий людей, которым будет разрешен доступ, и обучает алгоритм отличать их от других людей. На испытаниях система показывает хорошие результаты и внедряется в эксплуатацию. Через некоторое время список людей с допуском решают расширить и обнаруживается, что система отказывает новым людям в доступе. Алгоритм тестировался на тех же данных, что и обучался, и никто не проводил измерения точности на новых фотографиях. Это, конечно, утрированный пример, но он позволяет понять проблему.

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

Резюмируя вышесказанное, составим список рекомендаций: не используйте данные, на которых обучался алгоритм при тестировании, используйте специальный закрытый датасет для тестирования. Если это невозможно и вы собираетесь воспользоваться публичным датасетом, убедитесь, что вендор не использовал его в процессе обучения и/или настройки алгоритма. Изучите датасет перед тестированием, подумайте, насколько он близок к тем данным, которые будут поступать при эксплуатации системы.

Метрики


После выбора датасета, следует определиться с метрикой, которая будет использоваться для оценки результатов. В общем случае метрика – это функция, которая принимает на вход результаты работы алгоритма (идентификации или верификации), а на выходе возвращает число, которое соответствует качеству работы алгоритма на конкретном датасете. Использование одного числа для количественного сравнения разных алгоритмов или вендоров позволяет сжато представлять результаты тестирования и облегчает процесс принятия решений. В этом разделе мы рассмотрим метрики, наиболее часто применяемые в распознавании лиц, и обсудим их значение с точки зрения бизнеса.

Верификация


Верификацию лиц можно рассматривать как процесс принятия бинарного решения: “да” (два изображения принадлежат одному человеку), “нет” (на паре фотографий изображены разные люди). Прежде чем разбираться с метриками верификации, полезно понять, как мы можем классифицировать ошибки в подобных задачах. Учитывая, что есть 2 возможных ответа алгоритма и 2 варианта истинного положения вещей, всего возможно 4 исхода:


Рис. 2 Типы ошибок. Цвет фона кодирует истинное отношение между картинками (синий означает “принять”, желтый – “отвергнуть”), цвет рамки соответствует предсказанию алгоритма (синий – “принять”, желтый – “отвергнуть”



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

Из этих исходов два соответствуют правильным ответам алгоритма, а два – ошибкам первого и второго рода соответственно. Ошибки первого рода называют «false accept», «false positive» или  «false match» (неверно принято), а ошибки второго рода – «false reject», «false negative» или «false non-match» (неверно отвергнуто).

Просуммировав количество ошибок разного рода среди пар изображений в датасете и поделив их на количество пар, мы получим false accept rate (FAR) и false reject rate (FRR). В случае с системой контроля доступа «false positive» соответствует предоставлению доступа человеку, для которого этот доступ не предусмотрен, в то время как «false negative» означает, что система ошибочно отказала в доступе авторизованной персоне. Эти ошибки имеют разную стоимость с точки зрения бизнеса и поэтому рассматриваются отдельно. В примере с контролем доступа «false negative» приводит к тому, что сотруднику службы безопасности надо перепроверить пропуск сотрудника. Предоставление неавторизованного доступа потенциальному нарушителю (false positive) может привести к гораздо худшим последствиям.

Учитывая, что ошибки разного рода связаны с различными рисками, производители ПО для распознавания лиц зачастую дают возможность настроить алгоритм так, чтобы минимизировать один из типов ошибок. Для этого алгоритм возвращает не бинарное значение, а вещественное число, отражающее уверенность алгоритма в своем решении. В таком случае пользователь может самостоятельно выбрать порог и зафиксировать уровень ошибок на определенных значениях.

Для примера рассмотрим «игрушечный» датасет из трех изображений. Пусть изображения 1 и 2 принадлежат одному и тому же человеку, а изображение 3 кому-то еще. Допустим, что программа оценила свою уверенность для каждой из трех пар следующим образом:


Мы специально выбрали значения таким образом, чтобы ни один порог не классифицировал все три пары правильно. В частности, любой порог ниже 0.6 приведет к двум false accept (для пар 2-3 и 1-3). Разумеется, такой результат можно улучшить.

Выбор порога из диапазона от 0.6 до 0.85 приведет к тому, что пара 1-3 будет отвергнута, пара 1-2 по-прежнему будет приниматься, а 2-3 будет ложно приниматься. Если увеличить порог до 0.85-0.9, то пара 1-2 станет ложно отвергаться. Значения порога выше 0.9 приведут к двум true reject (пары 1-3 и 2-3) и одному false reject (1-2). Таким образом, лучшими вариантами выглядят пороги из диапазона 0.6-0.85 (один false accept 2-3) и порог выше 0.9 (приводит к false reject 1-2). Какое значение выбрать в качестве финального, зависит от стоимости ошибок разных типов. В этом примере порог варьируется в широких диапазонах, это связано, в первую очередь, с очень маленьких размеров датасетом и с тем, как мы выбрали значения уверенности алгоритма. Для больших, применяемых для реальных задач датасетов, получились бы существенно более точные значения порога. Зачастую вендоры ПО для распознавания лиц поставляют значения порога по умолчанию для разных FAR, которые вычисляются похожим образом на собственных датасетах вендора.

Также нетрудно заметить, что по мере того как интересующий FAR снижается, требуется все больше и больше положительных пар изображений, чтобы точно вычислить значение порога. Так, для FAR=0.001 нужно по меньшей мере 1000 пар, а для FAR=$10^{-6}$ потребуется уже 1 миллион пар. Собрать и разметить такой датасет непросто, поэтому клиентам, заинтересованным в низких значениях FAR, имеет смысл обратить внимание на публичные бенчмарки, такие как NIST Face Recognition Vendor Test или MegaFace. К последнему следует относиться с осторожностью, так как и обучающая, и тестовая выборки доступны всем желающим, что может привести к излишне оптимистичной оценке точности (см. раздел «Переобучение»).

Типы ошибок различаются по связанной с ними стоимости, и у клиента есть способ смещать баланс в сторону тех или иных ошибок. Для этого надо рассмотреть широкий диапазон значений порога. Удобный способ визуализации точности алгоритма при разных значениях FAR заключается в построении ROC-кривых (англ. receiver operating characteristic, рабочая характеристика приёмника).

Давайте разберемся, как строятся и анализируются ROC-кривые. Уверенность алгоритма (а следовательно, и порог) принимают значения из фиксированного интервала. Другими словами, эти величины ограничены сверху и снизу. Предположим, что это интервал от 0 до 1. Теперь мы можем измерить количество ошибок, варьируя значение порога от 0 до 1 с небольшим шагом. Так, для каждого значения порога мы получим значения FAR и TAR (true accept rate). Далее мы будет рисовать каждую точку так, чтобы FAR соответствовал оси абсцисс, а TAR – оси ординат.


Рис.3 Пример ROC-кривой

Легко заметить, что первая точка будет иметь координаты 1,1. При пороге равном 0 мы принимаем все пары и не отвергаем ни одной. Аналогично, последняя точка будет 0,0: при пороге 1 мы не принимаем ни одной пары и отвергаем все пары. В остальных точках кривая обычно выпуклая. Также можно заметить, что наихудшая кривая лежит примерно на диагонали графика и соответствует случайному угадыванию исхода. С другой стороны, наилучшая возможная кривая образует треугольник с вершинами (0,0) (0,1) и (1,1). Но на датасетах разумного размера такое трудно встретить.


Рис.4 ROC-кривые NIST FRVT

Можно построить подобие RОС-кривых с различными метриками/ошибками на оси. Рассмотрим, например, рисунок 4. На нем видно, что организаторы NIST FRVT по оси Y нарисовали FRR (на рисунке – False non-match rate), а по оси X – FAR (на рисунке – False match rate). В данном конкретном случае лучшие результаты достигнуты кривыми, которые расположены ниже и смещены влево, что соответствует низким показателям FRR и FAR. Поэтому стоит обращать внимание на то, какие величины отложены по осям.

Такой график позволяет легко судить о точности алгоритма при заданном FAR: достаточно найти точку на кривой с координатой Х равной нужному FAR и соответствующее значение TAR. «Качество» ROC-кривой также можно оценить одним числом, для этого надо посчитать площадь под ней. При этом лучшее возможное значение будет 1, а значение 0.5 соответствует случайному угадыванию. Такое число называют ROC AUC (Area Under Curve). Однако следует заметить, что ROC AUC неявно предполагает, что ошибки первого и второго рода однозначны, что не всегда так. В случае если цена ошибок различается, следует обратить внимание на форму кривой и те области, где FAR соответствует бизнес-требованиям.

Идентификация


Второй популярной задачей распознавания лиц является идентификация, или поиск человека среди набора изображений. Результаты поиска сортируются по уверенности алгоритма, и наиболее вероятные совпадения попадают в начало списка. В зависимости от того, присутствует или нет искомый человек в поисковой базе, идентификацию разделяют на две подкатегории: closed-set идентификация (известно, что искомый человек есть в базе) и open-set идентификация (искомого человека может не быть в базе).

Точность (accuracy) является надежной и понятной метрикой для closed-set идентификации. По сути, точность измеряет количество раз, когда нужная персона была среди результатов поиска.

Как это работает на практике? Давайте разбираться. Начнем с формулировки бизнес-требований. Допустим, у нас есть веб-страница, которая может разместить десять результатов поиска. Нам нужно измерить количество раз, которое искомый человек попадает в первые десять ответов алгоритма. Такое число называется Top-N точностью (в данном конкретном случае N равно 10).

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


Рис 5. Пример идентификации. В этом примере искомый человек появляется в позиции 2, поэтому точность Top-1 равна 0, а Top-2 и далее равна 1.

Open-set идентификация состоит из поиска людей, наиболее похожих на искомое изображение, и определения, является ли кто-то из них искомым человеком на основании уверенности алгоритма. Open-set идентификацию можно рассматривать как комбинацию closed-set идентификации и верификации, поэтому на этой задаче можно применять все те же метрики, что и в задаче верификации. Также нетрудно заметить, что open-set идентификацию можно свести к попарным сравнениям искомого изображения со всеми изображениями из галереи. На практике это не используется из соображений скорости вычислений. ПО для распознавания лиц часто поставляется с быстрыми алгоритмами поиска, которые могут находить среди миллионов лиц похожие за миллисекунды. Попарные сравнения заняли бы намного больше времени.

Практические примеры


В качестве иллюстрации давайте рассмотрим несколько распространенных ситуаций и подходов к тестированию алгоритмов распознавания лиц.

Розничный магазин


Допустим, что средний по размеру розничный магазин хочет улучшить свою программу лояльности или уменьшить количество краж. Забавно, но с точки зрения распознавания лиц это примерно одно и то же. Главная задача этого проекта заключается в том, чтобы как можно раньше идентифицировать постоянного покупателя или злоумышленника по изображению с камеры и передать эту информацию продавцу или сотруднику службы безопасности.

Пусть программа лояльности охватывает 100 клиентов. Данную задачу можно рассматривать как пример open-set идентификации. Оценив расходы, отдел маркетинга пришел в выводу, что приемлемый уровень ошибки – принимать одного посетителя за постоянного покупателя за день. Если в день магазин посещает 1000 посетителей, каждый из которых должен быть сверен со списком 100 постоянных клиентов, то необходимый FAR составит $\frac{1}{1000 * 100} = 10^{-5}$.

Определившись с допустимым уровнем ошибки, следует выбрать подходящий датасет для тестирования. Хорошим вариантом было бы разместить камеру в подходящем месте (вендоры могут помочь с конкретным устройством и расположением). Сопоставив транзакции держателей карт постоянного покупателя с изображениями с камеры и проведя ручную фильтрацию, сотрудники магазина могут собрать набор позитивных пар. Также имеет смысл собрать набор изображений случайных посетителей (по одному изображению на человека). Общее количество изображений должно примерно соответствовать количеству посетителей магазина в день. Объединив оба набора, можно получить датасет как «позитивных», так и «негативных» пар.

Для проверки желаемой точности должно хватить около тысячи «позитивных» пар. Комбинируя различных постоянных клиентов и случайных посетителей, можно собрать около 100 000 «негативных» пар.

Следующим шагом будет запустить (или попросить вендора запустить) ПО и получить уверенность алгоритма для каждой пары из датасета. Когда это будет сделано, можно построить ROC-кривую и удостовериться, что количество правильно идентифицированных постоянных клиентов при FAR=$10^{-5}$соответствует бизнес-требованиям.

E-Gate в аэропорту


Современные аэропорты обслуживают десятки миллионов пассажиров в год, а процедуру паспортного контроля ежедневно проходит около 300 000 человек. Автоматизация этого процесса позволит существенно сократить расходы. С другой стороны, пропустить нарушителя крайне нежелательно, и администрация аэропорта хочет минимизировать риск такого события. FAR=$10^{-7}$ соответствует десяти нарушителям в год и кажется разумным в этой ситуации. Если при данном FAR, FRR составляет 0.1 (что соответствует результатам NtechLab на бенчмарке NIST visa images), то затраты на ручную проверку документов можно будет сократить в десять раз. Однако для того чтобы оценить точность при данном уровне FAR, понадобятся десятки миллионов изображений. Сбор такого большого датасета требует значительных средств и может потребовать дополнительного согласования обработки личных данных. В результате инвестиции в подобную систему могут окупаться чересчур долго. В таком случае имеет смысл обратиться к отчету о тестировании NIST Face Recognition Vendor Test, который содержит датасет с фотографиями с виз. Администрации аэропорта стоит выбирать вендора на основе тестирования на этом датасете, приняв во внимание пассажиропоток.

Таргетированная почтовая рассылка


До сих пор мы рассматривали примеры, в которых заказчик был заинтересован в низких FAR, однако это не всегда так. Представим себе оборудованный камерой рекламный стенд в крупном торговом центре. Торговый центр имеет собственную программу лояльности и хотел бы идентифицировать ее участников, остановившихся у стенда. Далее этим покупателям можно было бы рассылать таргетированные письма со скидками и интересными предложениями на основании того, что их заинтересовало на стенде.

Допустим, что эксплуатация такой системы обходится в 10 $, при этом около 1000 посетителей в день останавливаются у стенда. Отдел маркетинга оценил прибыль от каждого таргетированного email в 0.0105 $. Нам хотелось бы идентифицировать как можно больше постоянных покупателей и не слишком беспокоить остальных. Чтобы такая рассылка окупилась, точность должна быть равна затратам на стенд, поделенным на количество посетителей и ожидаемый доход от каждого письма. Для нашего примера точность равна $\frac{10}{1000 * 0.0105} = 95%$. Администрация торгового центра могла бы собрать датасет способом, описанным в разделе «Розничный магазин», и измерить точность, как описано в разделе «Идентификация». На основании результатов тестирования можно принимать решение, получится ли извлечь ожидаемую выгоду с помощью системы распознавания лиц.

Поддержка видео


В этой заметке мы обсуждали преимущественно работу с изображениями и почти не касались потокового видео. Видео можно рассматривать как последовательность статичных изображений, поэтому метрики и подходы к тестированию точности на изображениях применимы и к видео. Стоит отметить, что обработка потокового видео гораздо более затратна с точки зрения производимых вычислений и накладывает дополнительные ограничения на все этапы распознавания лиц. При работе с видео следует проводить отдельное тестирование производительности, поэтому детали этого процесса не затрагиваются в настоящем тексте.

Частые ошибки


В этом разделе мы хотели бы перечислить распространенные проблемы и ошибки, которые встречаются при тестировании ПО для распознавания лиц, и дать рекомендации, как их избежать.

Тестирование на датасете недостаточного размера


Всегда следует быть аккуратным при выборе датасета для тестирования алгоритмов распознавания лиц. Одним из важнейших свойств датасета является его размер. Размер датасета нужно выбирать, исходя из требований бизнеса и значений FAR/TAR. «Игрушечные» датасеты из нескольких изображений людей из вашего офиса дадут возможность «поиграть» с алгоритмом, измерить его производительность или протестировать нестандартные ситуации, но на их основании нельзя делать выводы о точности алгоритма. Для тестирования точности следует использовать датасеты разумных размеров.

Тестирование при единственном значении порога


Иногда люди тестируют алгоритм распознавания лиц при одном фиксированном пороге (часто выбранном производителем «по умолчанию») и принимают во внимание лишь один тип ошибок. Это неправильно, так как значения порога «по умолчанию» у разных вендоров различаются или выбираются на основе различных значений FAR или TAR. При тестировании следует обращать внимание на оба типа ошибок.

Сравнение результатов на разных датасетах


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

Делать выводы на основе тестирования на единственном датасете


Следует стараться проводить тестирование на нескольких наборах данных. При выборе единственного публичного датасета нельзя быть уверенным, что он не использовался при обучении или настройке алгоритма. В этом случае точность алгоритма будет переоценена. К счастью, вероятность этого события можно снизить, сравнив результаты на разных датасетах.

Выводы


В этой заметке мы описали основные составные части тестирования алгоритмов распознавания лиц: наборы данных, задачи, соответствующие метрики и распространенные сценарии.

Конечно, это далеко не всё, что хотелось бы рассказать о тестировании, и наилучший порядок действий может отличаться при многочисленных исключительных сценариях (команда NtechLab с радостью поможет с ними разобраться). Но мы очень надеемся, что этот текст поможет правильно спланировать тестирование алгоритма, оценить его сильные и слабые стороны и интерпретировать метрики качества с точки зрения бизнес-задач.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329412/


Метки:  

Git: много хуков полезных и разных

Вторник, 30 Мая 2017 г. 17:45 + в цитатник
Статья является вольным переводом вот этого материала: krisjordan.com/essays/setting-up-push-to-deploy-with-git. Любителям длинных и заумных первоисточников можно сразу читать оригинал.

Когда перед нами ставится задача при изменении кодбейса, например, в Github-репозитории выполнить пересборку/перезапуск какого-нибудь приложения на каком-то нашем окружении, то первое, что приходит на ум в качестве возможного триггера такой пересборки, это предоставляемый тем же гитхабом механизм веб-хуков: при наступлении какого-либо события с нашим удаленным репозиторием (т.к. появление нового коммита в какой-нибудь его отслеживаемой ветке) гитхаб задействует соответствующий веб-хук и «дернет» указанный в его настройках сервис, который и запустит процесс пересборки/перезапуска нашего приложения. Это стандартный широкоиспользуемый и простой механизм для таких случаев, все так делают, и все такое…

Но что, если наше приложение живет на хосте, доступ к которому по каким-то причинам гитхабу не положен? Например, хост находится в закрытой сети или за NAT'ом и недоступен из интернета?

В этом случае можно воспользоваться механизмом локальных хуков самого Git, о котором (механизме), как выясняется, мало кто знает даже из тех, кто использует Git уже довольно продолжительное время.

Когда мы создаем локальный репозиторий (инициализируем пустой, клонируем удаленный, ...), то в папке .git, что в его корне, или в самом корне, если это bare-репозиторий, присутствует папка hooks. После инициализации репозитория в этой папке сохраняются шаблоны хуков для различных событий, таких как, например: post-merge, post-receive, post-update и др.
Полное описание поддерживаемых событий для хуков можно найти, например, тут: git-scm.com/book/ru/v1/%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-Git-%D0%9F%D0%B5%D1%80%D0%B5%D1%85%D0%B2%D0%B0%D1%82%D1%87%D0%B8%D0%BA%D0%B8-%D0%B2-Git

Мы воспользуемся этим механизмом и реализуем простенькую push-to-deploy схему для нашего горемычного приложения.

Нам понадобится два локальных репозитория. Создадим их, например, по указанным путям:
1. /opt/repo-dev/example-repo/
2. /opt/repo-remote.git/

Первый репозиторий — это клон нашего удаленного репозитория example-repo на гитхабе.
Второй — это bare репозиторий, копия первого, который будет служить нам исключительно для обработки события post-update при появлении обновлений в удаленном репозитории. Итак, как же мы это реализуем?

Схема очень проста (предположим, мы отслеживаем ветку test, а приложение наше это node.js, управляемый менеджером pm2):
1. Периодически обновляем первый локальный репозиторий до состояния, полностью соотвествующего состоянию удаленного репозитория.
2. Из первого локального репозитория обновляем второй.
3. Как только HEAD у нас переместился — появился новый коммит — во втором репозитории будет задействован хук post-update, который выполняется при появлении любых изменений в репозитории, и который и выполнит необходимые действия по ребилду и рестарту приложения.

Для этого мы делаем следующее:

1. В первом локальном репозитории добавляем remote — второй локальный репозиторий:
cd /opt/repo-dev/example-repo/ && git remote add prod /opt/repo-remote.git

Теперь мы можем выполнять git push из первого локального репозитория во второй.

2. В папке /opt/repo-remote.git/hooks/ создаем файл post-update и делаем его исполняемым:
touch /opt/repo-remote.git/hooks/post-update && chmod +x /opt/repo-remote.git/hooks/post-update

Это обычный шел-скрипт, но согласно внутренней конвенции Git без расширения .sh!
Давайте добавим в него несколько команд:
#!/bin/bash
cd /opt/repo-remote.git
/usr/bin/git --work-tree=/opt/repo/example-repo/ checkout -f origin/test

cd /opt/repo/example-repo/
/usr/bin/npm install
/usr/local/bin/pm2 restart all

Что делает скрипт? Сначала просто выгружает working tree нашего bare репозитория в папку с нашим работающим приложением, а затем пересобирает зависимости и рестартует сервисы pm2. Как видите, никакой магии.

3. Настраиваем cron, который каждые n минут будет обновлять первый репозиторий из удаленного:
git fetch origin && git reset --hard -f origin/test

Т.о. теперь наш хост будет являться регулярным инициатором проверки удаленного репозитория — а не появились ли там обновления?
Прошу заметить, что обновляем локальный репозиторий мы не путем git pull, а путем git reset --hard. Делается это для того, чтобы исключить необходимость мерджей при определенном содержимом очередного коммита — мы делаем локальный репозиторий полной копией удаленного.

4. Сразу после синхронизации первого локального репозитория с удаленным мы делаем пуш всех изменений в наш псевдо-удаленный второй локальный репозиторий:
git push prod test


Вот и все. Как только наш псевдо-удаленный локальный репозиторий получает ненулевые изменения, Git дергает свой хук post-update, который выполняет соответствующий скрипт. И мы получаем простенькую рабочую схему push-to-deploy, которую при желании можно и дальше усовершенствовать в соответствии с нашими потребностями.

«Зачем городить такую неудобоваримую монструозную схему?!» — спросите вы. Я сначала задавался этим же вопросом, но оказалось, что с существующим перечнем хуков Git'а только так мы сможем вызвать необходимую обработку при любом обновлении нашей ветки в удаленном репозитории. Нужный нам хук post-update предназначен для выполнения на remote репозитории (а часть хуков предназначена для выполнения на локальном репозитории). И мы таким вот не очень изящным способом это псевдо-удаленный репозиторий и сэмулировали. Возможно в скором времени появится еще какой-нибудь более удобный хук, выполняющийся локально, и схему можно будет упростить. Но пока так.

В заключение хочу дать несколько советов тем, кто решит это реализовать у себя и, столкнувшись с проблемами неработающего хука или каких-то его частей, будет яростно проклинать меня, Git, автора оригинальной статьи и всех остальных по списку:
1. Помните про специфику работы cron — программы в нем по умолчанию запускаются совсем не в том окружении, которое вы, вероятно, ожидаете.
2. Проверяйте версии ваших утилит (npm, node etc) при вызове их из скриптов и по cron — они могут быть не такими, как при ручном запуске из-за различия путей к исполняемым файлам в переменных окружения, например. А запуск других их версий может приводить к непрогнозируемым результатам.
3. Потратьте 20 минут на просмотр очередной серии Simpsons и возвращайтесь к экспериментам с новыми силами и хорошим настроением

Буду рад любым замечаниям и уточнениям по существу.

Хорошего всем дня!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329804/


Метки:  

Перспективы трудоустройства для Java-программистов

Вторник, 30 Мая 2017 г. 17:36 + в цитатник
Наш образовательный проект стартовал с программы «Разработчик Java» не случайно. Во-многом появление этого курса связано с темпами роста IT-сферы и постоянного спроса на квалифицированных программистов. В этой статье мы решили поделиться с вами цифрами и фактами, которые подтверждают наш выбор и помогут вам понять, стоит ли изучать Java на профессиональном уровне.


Почему Java?
Портал TIOBE, ежемесячно составляющий рейтинг языков, основанный на запросах в популярных поисковиках, уже целый год не меняет лидера. И да, это Java. Информацию по нему разыскивают в среднем в 2 раза чаще, чем по C, в 4 раза чаще, чем по Python и в 6,5 раз чаще, чем по Swift. И дело не в том, что Java — сложный язык или по нему мало хорошей документации. За 22 года своего существования этот язык создал вокруг себя целую экосистему, которая развивается год от года, что усложняет поиск правильных образовательных источников и инструментов. Впрочем, это больше не проблема.

Java — невероятно развитый и востребованный язык программирования, что подтверждается практически безграничной областью применения. Можно загибать пальцы:
1. Мобильная разработка — самая популярная в мире ОС Android работает именно на Java. Не стоит забывать и о J2ME-приложениях для бюджетного сегмента;
2. Веб-приложения — сложно даже представить, какое количество мобильных версий веб-сайтов написано именно на Java;
3. Десктопное ПО — широчайший диапазон применения от игр (Minecraft) до офисных программ (Open Office). Для встраиваемых систем Java также подходит безупречно;
4. Финансовая область — такие гиганты, как Barclays, Citigroup, Goldman Sachs активно используют Java для внутренних электронных систем и в качестве инструмента для создания пользовательских приложений;
5. Большие данные — очень актуальное на сегодняшний день направление, связанное с обработкой, прогнозированием и моделированием информации.

Что говорят цифры?
По информации портала trud.com в России Java-разработчиков требуется больше, чем C/C++/C# — разработчиков или, например, PHP-специалистов, не говоря уже о Python, Ruby или Swift. Аналогичную статистику можно найти на других HR-порталах, например, hh.ru.



Овладев языком Java и прилагающимся инструментарием, можно успешно начать карьеру и за пределами России, ведь потребность в профессиональных кадрах там не меньше, чем у нас в стране. Так, по информации портала Codingdojo, в 2017 году Java расположился на втором месте в списке самых востребованных языков, уступив лидерство лишь SQL. Как пишет издание, на сегодняшний день около 90% компаний из списка Fortune 500 (500 крупнейших компаний планеты) использует Java для разработки бэкенда в своих системах.

Справедливости ради, стоит всё же отметить, что потребность в JavaScript-программистах чуть выше, чем в Java-разработчиках. Однако и уровень зарплат там ниже, и спектр решаемых задач там куда уже.

Кстати о зарплатах. Угадайте, программисты со знаниями какого языка программирования имеют наибольшую среднюю заработную плату? И снова это Java. Вот цифры: Java-разработчик, окончивший ВУЗ по специальности или просто имеющий за плечами один год опыта, вполне может рассчитывать на 50-70 тысяч рублей зарплаты. Накопив опыт и знания, он уже претендует на оклад 70-100 тысяч рублей. Далее только по нарастающей: от 3 лет опыта — до 150 тысяч, от 5 лет — 200 тысяч, а тимлиды и сеньоры могут найти себе официальную зарплату от 200 до 300 тысяч рублей.

Если взглянуть на статистику по всей России, то ситуация изменится не сильно. По информации trud.com средняя заработная плата Java-разработчика составила 90 тысяч рублей. При этом важно учесть, что в данную статистику не входят тимлиды и руководители отделов.
Мировые тенденции в этом плане повторяют российские: так, по информации ресурса TechWorm, в 2016 году список самых “дорогих” и востребованных языков возглавил именно Java. Ведущий разработчик по данной специальности в США зарабатывает в среднем 115 тысяч долларов в год. Похожие цифры можно найти в Швейцарии, чуть ниже в Германии или Канаде. Сути это не меняет — программисты Java в любой стране живут хорошо.

Что насчёт конкуренции?
Она существует везде, где обитают большие деньги. Качественных Java-специалистов сейчас на рынке дефицит. Это косвенно подтверждает исследование CMS Magazine и «Рейтинга Рунета», в ходе которого 62% компаний, связанных с веб-разработкой, пожаловались на нехватку людей для выполнения поставленных задач. Как мы все понимаем, речь идёт не о верстальщиках и веб-дизайнерах.



Здесь мы подходим к главному вопросу: “Где получить качественное образование?”. Наша команда из otus.ru приложила максимум усилий, чтобы программа курса «Разработчик Java»
была полезна нашим студентам не просто с точки зрения новых знаний, но и с точки зрения соответствия требованиям компаний — работодателей на вакансии уровня middle и начала senior. Лучшим выпускникам мы гарантируем собеседование на вакантные позиции у наших партнеров — топовых IT компаний. Приходите к нам учиться и открывайте для себя новые карьерные перспективы, получая бесценные знания.

Кстати, новая группа Java начинает свое обучение уже в эту субботу!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329816/


Метки:  

[Перевод] SQL101: Почему восстановление из резервной копии медленнее, чем ее создание

Вторник, 30 Мая 2017 г. 16:50 + в цитатник
SQLskills запускает новую инициативу по размещению записей с базовыми знаниями, мы назвали ее SQL101. Мы будем писать о вещах, которые, как мы часто видим, делаются неправильно, технологиях, которые используются неверно, и о многих недопониманиях, которые приводят к серьезным проблемам. Если вы хотите найти все записи в этой серии, проверьте ссылку SQLskills.com/help/SQL101 (английский).

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

Создание полной резервной копии включает в себя следующие главные стадии:

  1. Создание контрольной точки.
  2. Чтение всех используемых данных из файлов данных (технически, чтение всех размещенных экстентов, независимо от того, какое количество из 8 страниц в экстенте на самом деле используется).
  3. Чтение журнала транзакций с начала самой старой незафиксированной транзакции с начальной контрольной точки до момента, когда была завершена вторая стадия. Это необходимо, чтобы база данных могла быть восстановлена в согласованное состояние на момент времени, принадлежащий периоду создания резервной копии (посмотрите эту статью (английский) для подробного объяснения).
  4. (Опционально тестирование контрольных сумм всех страниц, опционально выполнение сжатия резервной копии и опционально шифрование резервной копии).

Восстановление из полной резервной копии включает в себя следующие главные стадии:

  1. Создание файлов данных (и заполнение их нулями, если не разрешена мгновенная инициализация файлов (английский, хорошая альтернатива на русском).
  2. Копирование данных из резервной копии в файлы данных.
  3. Создание файла журнала транзакций и заполнение его нулями. Файл журнала транзакций должен быть всегда заполнен нулями при создании (посмотрите эту статью (английский) для подробного объяснения).
  4. Копирование журнала транзакций из резервной копии в файл журнала.
  5. Запуск восстановления после сбоя на базе данных.
  6. (Опционально тестирование контрольных сумм всех страниц во время второй фазы, выполнение распаковки, если резервная копия была сжата, выполнение расшифровки, если резервная копия была зашифрована.)

Стадия 3 часто бывает самой долгой стадией при восстановлении, и она пропорциональна размеру журнала транзакций. Этот процесс выполняется в отдельной стадии, вместо того, чтобы выполняться параллельно с 1-2 стадией, и для глубокого изучения смотрите недавнюю запись в блоге Боба Варда.

Стадия 5 может быть самой долгой стадией в процессе восстановления, если в процессе создания резервной копии существовали долгие незафиксированные транзакции. И еще более долгой она может быть, если в журнале транзакций находится большое количество виртуальных файлов журнала (тысячи), поскольку они очень сильно замедляют механизм отката незафиксированных транзакций.

Здесь перечень вещей, которые вы можете сделать, чтобы сделать восстановление из полной резервной копии быстрее:

  • Убедитесь, что мгновенная инициализация файлов включена для экземпляра SQL Server, который выполняет операцию восстановления, чтобы избежать траты времени на заполнение нулями любых файлов данных, которые должны быть созданы. Это может спасти часы времени простоя для очень больших файлов данных.
  • Если возможно — восстанавливайте поверх существующей базы данных — не удаляйте существующие файлы. Это позволит избежать необходимости создания и потенциального заполнения нулями полного объема файлов, особенно файлов журнала транзакций. Будьте очень осторожны, используя этот пункт, поскольку существующая база данных будет безнадежно уничтожена, как только процесс восстановления начнет перезаписывать ее.
  • Рассмотрите возможность использования сжатия резервных копий, это может ускорить операции и создания и восстановления из резервных копий, и сохранить дисковое пространство и затраты на место хранения.
  • Рассмотрите возможность использования нескольких файлов резервных копий, каждый из них — на отдельном томе. SQL Server распознает такую ситуацию и будет использовать параллельную запись (по одному потоку на том) для записей файлов при создании резервной копии и при чтении в процессе восстановления — ускоряя все процессы. Если у вас есть несколько файлов базы данных, произойдет похожее распараллеливание процессов ввода/вывода — обеспечивая еще большее ускорение.
  • Пытайтесь избегать долгих транзакций, так как они потребуют долгого времени в процессе отката.
  • Управляйте вашим журналом транзакций так, чтобы избежать наличия избыточного количества виртуальных файлов журнала, чтобы при наличии транзакций, требующих отката, откат производился настолько быстро, насколько это возможно. Смотрите эту запись в блоге (английский) для подробного объяснения.


Надеюсь, это было полезно!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329814/


Метки:  

IT — проект со школьниками: несколько рекомендаций

Вторник, 30 Мая 2017 г. 16:42 + в цитатник

За последние 5 лет мне удалось создать десяток учебных проектов вместе со школьниками 8-11 классов в сфере информационных технологий. И вот я решил поделиться своим опытом в этой статье, надеясь на конструктивную беседу по такой актуальной теме. В статье я попытаюсь раскрыть технологию реализации IT — проекта как способа обучения, а также затронуть технические аспекты, которые помогут вашей команде достигнуть результата.

Давайте, в первую очередь, определимся, что же такое проект. Кстати, о проектной деятельности в сфере образования сегодня очень много говорят и пытаются ввести этот метод обучения в образовательный процесс, что я лично крайне поддерживаю. Почему? Да все просто: в сжатые сроки вместе с командой вы создаете продукт, а ваши подопечные одновременно с этим изучают что-то новое.

Вы найдете огромное количество определений понятия «проект», но я попробую дать свое. Проект со школьниками — это некий процесс реализации конечного продукта, направленный на изучение новых инструментов командной работы, создание работающего прототипа или первого варианта продукта, изучение технологий, выходящих за рамки школьной программы.

Ключевыми словами в такой трактовке я считаю “процесс” и “продукт”. Многие проекты, которые я видел, являются исследовательскими, т.е. доказывающими или опровергающими какую-то гипотезу. Результаты таких проектов обычно — презентация и доклад. Многие проекты являются информационными, т.е. направленными на сбор и систематизацию информации об объекте, проблеме, явлении. Результат такого проекта — опять же презентация, доклад, дискуссия.

Я бы хотел, все же, сделать акцент на слове “продукт” и говорить о том, что конечной целью проекта в сфере IT должна быть демонстрация чего-то материального, созданного в процессе реализации проекта. Причем, я ни в коем случае не отрицаю, а наоборот, подчеркиваю важность научно — исследовательских проектов, которые направлены на создание прорывных технологий и разработку новых концепций в сфере информационных технологий. Просто наукой и исследованиями могут заниматься единицы, и, скорее всего, это удел, все-таки, высшего образования.

Идея и продукт


Отнеситесь к выбору темы своего проекта внимательно и тщательно. Зачем тратить впустую ближайшие несколько месяцев, верно? Цели могут быть совершенно разные: улучшить мир, выиграть конкурс, заработать денег, но вся ваша команда должна четко понимать, зачем вы тратите силы и ресурсы, создавая что-то новое.

Еще один неочевидный момент: когда вы создаете что-то осязаемое, гораздо выше вероятность того, что проект будет реализован. Очень часто случается так, что, загоревшись идеей, команда не доводит дело до конца, просто четко не понимая, а что же мы делаем?

Итак, первая мысль пришла в голову, вы с этой мыслью походили и решили, что вот оно! Посмотрите аналоги, сделайте подробный поиск уже существующих решений. Может случиться так, что до вас уже все реализовали. Не отчаивайтесь, если вы не хотите менять тему проекта — сделайте подобное, но по-другому, добавьте функций или измените дизайн. Но лучше, все-таки, создать что-то свое.

Темы проектов могут быть очень разными, и очень большую роль здесь играет наставник. Школьник в силу отсутствия опыта просто может не понимать значимость (или отсутствие таковой) той или иной темы. Школьник может делать что-то только ради процесса, не отдавая отчет в бессмысленности создаваемого. Например, давайте сделаем так, чтобы свет в комнате включался по хлопку ладонями? Интересная идея, но спросите себя, а зачем, кому это будет нужно, если таких решений уже пруд пруди. Ради изучения чего-то нового? Да, такую цель тоже можно достигать проектной деятельностью, но она не самая главная. Главное, на мой взгляд, — научить ребят творить и создавать что-то нужное. Анализировать, аргументировать, убеждать и отстаивать свою точку зрения. Искать варианты улучшения существующего, создавать новое. Людей, которые могут придумывать, не так много, и ценность подобных специалистов возрастает с каждым годом.

Итак, что же может быть продуктом учебного проекта в сфере информационных технологий? Выделим основные очевидные варианты.

Сайт


Это некий интернет — сервис, реализующий что-то новое или дополняющий уже созданную концепцию. Обратите внимание, что вы можете взять уже готовое решение и, не занимаясь плагиатом, а вдохновившись идеей, разработать что-то другое, более совершенное или просто с другим функционалом. Например, можно создать новый сервис для проведения тестирования или анкетирования. Какие технологии изучат ребята? Дизайн сайтов, верстка, программирование. Немало, на самом деле.

Мобильное приложение


Еще интереснее и сложнее, чем сайт. Поле для фантазии не ограничено, причем, всплывает такой интересный момент: вы можете заниматься созданием проекта озеленения территории вашего микрорайона, но оформить результат как мобильное VR — приложение с возможностью “прогуляться” по создаваемой территории для более полного погружения в реализуемую концепцию. Что мы изучаем? Современные тенденции дизайна, объектно — ориентированное программирование. И, конечно, новые инструментальные средства разработки. А заодно и ландшафтный дизайн.

Компьютерная игра


Этот продукт принимается к реализации ребятами без каких-либо лишних объяснений и обычно доводится до логического конца. Игру можно делать для малышей, игру можно делать обучающую. Можно сделать многопользовательскую браузерную игру, можно сделать игру для смартфонов и планшетов. Что изучают ребята? Приемы и методы геймификации, дизайн элементов компьютерной игры, объектно — ориентированное программирование.

Программа


Продукт, который будет что-то автоматизировать. Научите школьников думать о пользователе, ставить себя на место человека, который будет работать с программой. Научите тестировать свои творения. Пусть программа будет небольшая, но с уникальным функционалом. Новый калькулятор, виджет погоды или агрегатор новостей на рабочем столе — просто оглянитесь вокруг.

Еще один отличный метод — создавать что-то для себя. Вы анализируете, а чего вам не хватает в вашей деятельности или повседневной жизни? Гарантированно такой продукт будет популярным, так как если вы создадите решение, автоматизирующее вашу потребность, найдется круг людей, у кого потребность та же. Например, мне недавно надо было при публикации материалов на сайте добавлять подписи по разным шаблонам. Постоянно форматировать разные подписи — утомительно, вот я и написал плагин под Wordpress, позволяющий этот процесс частично автоматизировать. Сделал для себя, но выложу в открытый доступ потом.

Фильм, плакат, журнал, трехмерная визуализация — все это может стать результатом вашего проекта.

Давайте ниже приведу мои рекомендации по реализации учебного проекта в сфере информационных технологий. С ними можно соглашаться или мы можем поспорить, но, может, мои мысли помогут и вам. Некоторые этапы пригодятся и для проектов в сфере экологии, туризма, литературы или русского языка, так как несут достаточно общий характер и будут ценны не только айтишникам.

Формулировка концепции


Придумали идею — запишите ее. Сформулируйте актуальность проекта, цели, которые вы хотите достичь, опишите простыми словами конечный результат вашего проекта, конечный продукт.

Общие папки


Обязательно создайте для своего проекта облачное хранилище с совместным доступом участников. Если это Google Диск или Облако Mail.ru, то создайте общие папки. В одном проекте у нас их было 8: “Модели”, “Текстуры”, “База данных”, “Фоны”, “Картинки”, “Скрипты”, “Настройки”, “Общее”. Можно использовать, наверное, более продвинутые инструменты, например, Битрикс24, я не пробовал. Надо, кстати, обратить на это внимание. Наверняка, есть еще инструменты совместного ведения проектной деятельности.

План реализации


Важный документ, потратьте на него побольше времени. В этом документе вам надо разбить ваш проект на маленькие этапы с описанием результата по окончании каждого. Только так вы дойдете до конца. Разрезав слона, мы сможем его съесть целиком. Школьник должен постоянно ощущать, что время было проведено не зря, что маленькая цель достигнута, скоро будет реализована основная концепция. Такой документ можно назвать план — графиком работ. Причем, когда вы будете его создавать, всплывет масса полезных мелочей, которые надо будет реализовать.

Нарисуйте результат


Все, что есть в голове, должно быть скинуто на бумагу. Делаете программу — рисуйте окна. Делаете сайт — рисуйте страницы. Делаете приложение — рисуйте все views. Делаете игру — рисуйте процесс и графические элементы. На обычных листах обычной ручкой или карандашом. Все зарисовки сохраняйте, нчиего не выкидывайте. Схемы, идеи, кнопки, окна, рожицы и палочки — все сохраняйте! Вообще, должна быть общая папка, куда будут складываться все бумажные полезности для проекта.

Назовите команду


Обязательно дайте название своей команде! Это сплотит участников. По возможности, выберите логотип, хотя бы из бесплатных, и создайте лозунг, девиз. Пусть вы будете “IT гуру” или “Кодята”, но название команды даже из двух человек может стать началом целой истории. Обязательно придумайте название вашего конечного продукта, пусть оно будет емким и хлестким. “Газонокосилка 2.0”, “Веб заметки” или “Погода в кармане”. Да, обязательно разделите функции внутри вашей команды: пусть кто-то создает дизайн, а кто-то пишет код, кто-то ищет аналоги и тексты, а кто-то подбирает фотографии или звуковые файлы.

Добавляем экономику


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

Выбираем инструменты


План есть, эскизы есть, теперь самое время выбрать программные средства для реализации проекта. Почитайте, что сегодня используется в реальной разработке, что в тренде, что пригодится участникам проекта потом. Попробуйте различные IDE и редакторы, но не зацикливайтесь на учебной программе, выйдите за ее рамки. Обратите внимание, что многие разработчики идут навстречу образовательным организациям, просите у них бесплатные версии их продуктов. Так делает Autodesk и JetBrains, например. Посоветуйтесь с экспертами. Делайте учебный проект правильными инструментальными средствами.

Версионный контроль


Если будет код, то обязательно создайте репозиторий для версионного контроля. Это сэкономит кучу времени, и ребята приучатся к этой технологии. Как-то я заметил, что переход на систему версионного контроля кода изменило мое отношение к тому, что я пишу. Код стал для меня очень важным и ценным, что ли. Каждое изменение стало более обдуманным. Удаление кода тем более. Более ценным становится и время на разработку. Храните все файлы удаленно и в совместном доступе.

Создаем прототип


Первый самый большой результат проекта должен быть минимально работающим. Т.е. это должно быть что-то запускающееся и выполняющее основные функции, что-то, реализующее основную идею.

Тестируем


Отдаем первую версию продукта друзьям, знакомым, одноклассникам. Готовимся к критике и сразу настраиваемся на адекватное ее восприятие. Когда внутри себя решаешь, что критика будет, сразу становится легче. Внимательно выслушиваем и записываем, обязательно записываем, все советы и пожелания сохраняем. Вспоминаем про папку, куда все складываем.

Доделываем


Смотрим на часы. Оцениваем сроки и доделываем проект в соответствии с план — графиком. Причем, у вас могут быть как краткосрочные цели (выиграть ближайший конкурс), так и долгосрочные (доделать все до конца и выпустить продукт в свет). Дорабатываем основное, вспоминаем пожелания и выбираем из них самые критичные.

Презентуем


Все готово, отведите время на создание доклада и презентации. Рекомендую придерживаться вот таких разделов в презентации:
  • Введение: рассказываем основные положения, назначение проекта, рассказываем о команде;
  • Актуальность: говорим о том, насколько проект полезен и что достигаем, меняем, улучшаем его реализацией;
  • Цели: тут рассказываем аудитории, а какие же цели были или будут достигнуты реализацией проекта;
  • Задачи: показываем те задачи, которые были выполнены во время работы над проектом;
  • Обзор аналогов и прототипов: показываем уже существующие решения и говорим о том, чем ваше отличается от остальных;
  • Выбор инструментальных средств: в этом разделе презентации обосновываем свой выбор инструментов разработки;
  • Экономическая часть: немного говорим о деньгах, чтобы аудитория оценила степень реализуемости проекта;
  • Целевая аудитория: рассказываем о вашем потребителе;
  • Показываем продукт: тут надо отвести время для демонстрации работы созданного решения;
  • Планы развития: рассказываем о том, чем будем заниматься дальше. Можно планы разбить на несколько очередей.


Все, проект готов!

Шарик-то сдувается


Все хорошо на бумаге, но в реальности всегда чуть сложнее. На пути реализации проекта со школьниками встает несколько проблем. Первая — а когда делать? Вариантов несколько, может, это будет в рамках кружка, может, это будут старшеклассники в классах без экзаменов (8-ые и 10-е классы), может, на каникулах.

Вторая проблема — контроль. Чтобы шарик не сдулся, его надо все время надувать. Я столкнулся с тем, что ребята быстро начинают, но, самое страшное, быстро заканчивают, не доводя дело до конца. Тут без постоянного вмешательства наставника никак, надо напоминать, тянуть за руку, просить результаты. Повторюсь, проект должен быть разделен на малые части, пусть ребята что-то делают дома и присылают результаты или складывают в общий репозиторий.

И третья проблема — что дальше? Создайте сайт проекта, постарайтесь сделать так, чтобы на него обратили внимание, попробуйте доделать проект до конца. Сам, честно говоря, почти все проекты складывал в стол, решая только сиюминутные задачи и не развивая дальше. Вот написал эти строчки и решил к некоторым историям вернуться, может, они выльются во что-то большее.

Проектная деятельность — эффективнейший инструмент изучения нового, помимо уроков. Проект может помочь выявить скрытые таланты у детей. Кто-то научится публично выступать и защищаться, кто-то программировать, кто-то создавать графику, а кто-то станет в дальнейшем менеджером проектов. Побольше нам удачных и интересных проектов!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329758/


Метки:  

[Из песочницы] Портирование MIPSfpga на другие платы и интеграция периферии в систему. Часть 1

Вторник, 30 Мая 2017 г. 16:19 + в цитатник
MIPSfpga представляет собой предназначенный для образовательных целей микропроцессор MIPS32 microAptiv фирмы Imagination, который имеет кэш-память и блок управления памятью. Код процессора на языке Verilog доступен пользователю и может использоваться для моделирования и реализации процессора на FPGA плате.

В даной статье будет описано на примере Digilent cmodA7 как портировать процессор MIPSfpga-plus на другие платы.



На сегодняшний день MIPSFPGA портирован на популярные платы таких фирм как ALTERA и Xilinx, среди них Basys 3, Nexys4 ddr, и другие (полный список находится на github). Такие платы наиболее популярны среди разработчиков на FPGA. Цена на такие платы довольно не маленькая, да и загружаются программы в ядро MIPSfpga с использованием интерфейса EJTAG и адаптера Bus Blaster ценой около 50$. Адаптер Bus Blaster получает команды по высокоскоростному кабелю USB 2.0 и преобразует их в последовательный протокол EJTAG, это позволяет загружать программы в ядро MIPSfpga и управлять отладкой программ, которые на нем выполняются. Проблема с относительно дорогим Bus Blaster была решена введением в систему MIPSfpga ряда улучшений. Улучшеный вариант системи MIPSfpga, названый MIPSfpga-plus включает в себя такие новые функции:

— Возможность загрузки программного обеспечения с использованием USB-to-UART коннектора ценой в $ 5 FTDI вместо $ 50 Bus Blaster, который иногда не так уж и легко достать.

— Возможность изменять тактовую частоту на лету с 50 или 25 МГц до 1 Гц (один цикл в секунду) для наблюдения за работой процессора в режиме реального времени, включая промахи в кэш-памяти и перенаправления конвеера.

— Пример интеграции датчика освещенности с протоколом SPI.

— Небольшая последовательность инициализации программного обеспечения, которая вписывается в 1 КБ вместо 32 КБ памяти, что позволяет переносить MIPSfpga на более широкий выбор плат FPGA без использования внешней памяти. Реализация UART описана в статье: MIPSfpga и UART.

Создание проекта в Xilinx Vivado с MIPSfpga-plus


Кто работал с MIPSFPGA-plus на платах фирмы Xilinx, могут пропустить данный этап. В связи с постоянно растущим количеством различных FPGA плат и набирающим популярность проектом по предоставлению исходников промышленных процессоров для университетов (а именно на базовую конфигурацию экономичного процессорного ядра MIPS microAptiv UP). Подробнее тут: Исходники промышленных процессоров станут доступными для университетов?, инструкция по портированию системы MIPSfpga+ в новую плату по мнению автора не будет лишней:

1. Для начала нужно получить пакет c системой MIPSFPGA. Подробная инструкция о том как это сделать:

-> mipsfpga-download-instruction

Если у вас уже есть MIPSfpga система и требуется использование usb-to-uart преобразователя (в плате cmodA7, а так же на многих других платах фирмы Xilinx есть встроенный uart), то вам потребуется скачать актуальную версию расширения MIPSfpga-plus:

-> Mipsfpga-plus

2. Для плат фирмы Xilinx используется программное обеспечение Vivado, актуальную версию можно скачать по ссылке:

-> Download Vivado

3. Теперь давайте создадим новый проект в Vivado:



Выбираем где будет хранится созданный проект:



Жмем далее:



Выбираем RTL проект и жмем далее:



Теперь добавим файлы системы оригинального MIPSfpga:





А так же MIPSfpga-plus которые находятся в архиве скачаном с mipsfpga-plus:



Добавим в проект модуль uart о котором ранее шла речь:



Пропускаем создание IP и файлов констрейнов создадим их позже:





Далее нужно либо выбрать микросхему либо добавить вашу плату.

Плата Digilent cmod A7 была выбрана в связи с ее не большой ценой и наличием АЦП которое мы потом используем. Чтобы выбрать FPGA схему нужно прочитать на вашу плату документацию, на cmodA7 размещен чип xc7a35tcpg236-1:



Другим способом является добавление файла вашей платы в библиотеку Vivado, этот способ лучше тем что, во первых, запомнить название платы удобней чем чипа, во вторых если вы в будущем захотите использовать block designer в Vivado, то у вас будет дополнительный инструментарий для удобной работы с интерфейсами платы, IP ядрами, и т.д. Скачать их можно на GitHub, сохранить эти файлы нужно в ~\Vivado\2015.1\data\boards\ (актуально для Vivado 2015.1 и новее).





Вот мы и создали проект с MIPSfpga-plus.

Инструкция по портированию на примере платы Digilent CmodA7 на базе микросхемы Artix-7


Если вкратце то на борту платы cmodA7 находится чип семейства Artix-7, имеет 20800 LUT, 41600 FF, 225 KB блочной памяти, имеется 48 пинов, среди которых 2 является выходами АЦП, также имеется usb-uart преобразователь, Quad-SPI Flash, и JTAG, 2 тактовые кнопки, а также 5 светодиодов 3 из которых это RGB (даташит).

Чтобы перенести систему MIPSfpga на плату cmodA7, следует:

Шаг 1. Написать модуль-оболочку, который устанавливает соответствие между вводами/выводами MIPSfpga и вводами/выводами платы Basys3
Шаг 2. Уменьшить объем памяти системы MIPSfpga для соответствия плате Basys3
Шаг 3. Добавить файл ограничений, который устанавливает соответствие между вводами/выводами платы и выводами корпуса FPGA.

Шаг 1. Добавим новый файл оболочки cmoda7.v
















Установим cmoda7.v топ модулем в иерархии системы.



Так как на плате cmoda7 нет переключателей которые можно было бы использовать для понижения частоты процессора (эта модификация появилась в MIPSfpga-plus), этот модуль просто не был включен в модуль оболочку. Так же можно исключить выход EJTAG к которому подключается BUS Blaster.

Для начала нужно добавить заголовочный файл конфигурации шины AHB_lite.

`include "mfp_ahb_lite_matrix_config.vh"

Усовершенствованная высокопроизводительная шина (Advanced High-performance Bus, AHB) является открытым интерфейсом, который используется во многих микропроцессорных системах, особенно во встроенных. Шина AHB облегчает организацию соединения нескольких устройств. AHB-Lite является упрощенной версией AHB с одним ведущим устройством.



Эта конфигурация имеет одно ведущее устройство, процессор MIPSfpga, и три ведомых: RAM0, RAM1 и GPIO, которые представляют собой (соответственно) два блока ОЗУ и модуль доступа к устройствам ввода/вывода платы. Мы как раз и будем работать с блоком GPIO и писать модули взаимодействия с периферией.

Пропишем основные порты ввода-вывода:

module cmoda7
              (
                  input               i_clk,
                  input               i_btn0, 
                  input               i_btn1,
                  input               RsRx,

                  output [ 6:0]       seg,   
                  output              dp,
                  output [ 3:0]       an,
                  output              led0_r,
                  output              led0_g,
                  output              led0_b,

                  inout  [ 7:0]       JA
                  
               );

i_clk — сигнал тактового генератора платы частотой (для cmodA7 12 МГц).
i_btn0 — кнопка используется для перезагрузки процессора.
i_btn1 — n/c.
RsRx — сигнал приема по uart.
seg, dp, an, — контакты для подключения семисегментного 4 разрядного индикатора.
led_r, led_g, led_b, — выводи размещённого на плате RGB Led.
JA — Pmod интерфейс.

Основными сигналами являются сигнал тактовой частоты и reset (i_btn0) остальные для подключения периферии.



Основной целью модуля cmoda7.v является создание экземпляра системы MIPSfpga-plus (mipsfpga_sys) и ее соединение с вводами/выводами платы.


    wire clock;
    wire reset = i_btn0;
    
    wire display_clock;
    wire [7:0] anodes;

    wire [`MFP_N_BUTTONS           - 1:0] IO_Buttons;
    wire [`MFP_7_SEGMENT_HEX_WIDTH - 1:0] IO_7_SegmentHEX;
    
    assign IO_Buttons  = { { `MFP_N_BUTTONS  -  2 { 1'b0 } } , i_btn0, i_btn1 };

mfp_system mfp_system
    (
        .SI_ClkIn         ( clock            ), 
        .SI_Reset         ( reset            ),
             
        .HADDR            (                  ),
        .HRDATA           (                  ),
        .HWDATA           (                  ),
        .HWRITE           (                  ),

        .EJ_TRST_N_probe  (                  ),
        .EJ_TDI           (                  ),
        .EJ_TDO           (                  ),
        .EJ_TMS           (                  ),
        .EJ_TCK           (                  ),
        .SI_ColdReset     (                  ),
        .EJ_DINT          (   1'b0           ),

        .IO_Switches      (                  ),
        .IO_Buttons       ( IO_Buttons       ),
        .IO_RedLEDs       (                  ),
        .IO_GreenLEDs     (                  ), 
        .IO_7_SegmentHEX  ( IO_7_SegmentHEX  ),
        
        `ifdef MFP_DEMO_LIGHT_SENSOR
        .SPI_CS           (   JA [0]         ),
        .SPI_SCK          (   JA [3]         ),
        .SPI_SDO          (   JA [2]         ),
        `endif
        
        .UART_RX          ( RsRx             ),
        .UART_TX          (                  )
    );

`ifdef MFP_DEMO_LIGHT_SENSOR
    assign JA [1] = 1'b0;
`endif

MFP_DEMO_LIGHT_SENSOR будем использовать при тестировании портированой системы. Как видим на выходе системы mfp_system будет 32-х разрядная шина IO_7_SegmentHEX которую мы выводим в модуль дешифратора 4-х разрядного 7 сегментного индикатора, подключим в оболочку модуль екземпляра «mfp_multi_digit_display»:

mfp_multi_digit_display multi_digit_display
    (
        .clock          (   display_clock   ),
        .resetn         ( ~ reset           ),
        .number         (   IO_7_SegmentHEX ),

        .seven_segments (   seg             ),
        .dot            (   dp              ),
        .anodes         (   an              )
    );

При создании дешифратора стоит узнать является ли индикатор с общим анодом или катодом.
Код дешифратора семисегментного индикатора с общим анодом имеет такой вид:

module mfp_single_digit_seven_segment_display
(
    input      [3:0] digit,
    output reg [6:0] seven_segments
);

    always @*
        case (digit)
        'h0: seven_segments = 'b1000000;  // a b c d e f g
        'h1: seven_segments = 'b1111001;
        'h2: seven_segments = 'b0100100;  //   --a--
        'h3: seven_segments = 'b0110000;  //  |     |
        'h4: seven_segments = 'b0011001;  //  f     b
        'h5: seven_segments = 'b0010010;  //  |     |
        'h6: seven_segments = 'b0000010;  //   --g--
        'h7: seven_segments = 'b1111000;  //  |     |
        'h8: seven_segments = 'b0000000;  //  e     c
        'h9: seven_segments = 'b0011000;  //  |     |
        'ha: seven_segments = 'b0001000;  //   --d-- 
        'hb: seven_segments = 'b0000011;
        'hc: seven_segments = 'b1000110;
        'hd: seven_segments = 'b0100001;
        'he: seven_segments = 'b0000110;
        'hf: seven_segments = 'b0001110;
        endcase

endmodule

//--------------------------------------------------------------------

module mfp_multi_digit_display
(
    input             clock,
    input             resetn,
    input      [31:0] number,

    output reg [ 6:0] seven_segments,
    output reg        dot,
    output reg [ 7:0] anodes
);

    function [6:0] bcd_to_seg (input [3:0] bcd);

        case (bcd)
        'h0: bcd_to_seg = 'b1000000;  // a b c d e f g
        'h1: bcd_to_seg = 'b1111001;
        'h2: bcd_to_seg = 'b0100100;  //   --a--
        'h3: bcd_to_seg = 'b0110000;  //  |     |
        'h4: bcd_to_seg = 'b0011001;  //  f     b
        'h5: bcd_to_seg = 'b0010010;  //  |     |
        'h6: bcd_to_seg = 'b0000010;  //   --g--
        'h7: bcd_to_seg = 'b1111000;  //  |     |
        'h8: bcd_to_seg = 'b0000000;  //  e     c
        'h9: bcd_to_seg = 'b0010000;  //  |     |
        'ha: bcd_to_seg = 'b0001000;  //   --d-- 
        'hb: bcd_to_seg = 'b0000011;
        'hc: bcd_to_seg = 'b1000110;
        'hd: bcd_to_seg = 'b0100001;
        'he: bcd_to_seg = 'b0000110;
        'hf: bcd_to_seg = 'b0001110;
        endcase

    endfunction

    reg [2:0] i;

    always @ (posedge clock or negedge resetn)
    begin
        if (! resetn)
        begin
            seven_segments <=   bcd_to_seg (0);
            dot            <= 0;
            anodes         <= 8'b00000001;

            i <= 0;
        end
        else
        begin
            seven_segments <=  bcd_to_seg (number [i * 4 +: 4]);
            dot            <= 0;
            anodes         <= (1 << i);

            i <= i + 1;
        end
    end

endmodule

Как можно увидеть по каждому переднему фронту clock в seven_segments выводится соответствующий сигнал bcd_to_seg, а переключение между разрядами индикатора производится с помощью переключения активного сигнала на соответствующих анодах (либо катодах).

Так как на вход процессора поступает сигнал в частотой в 50 МГц который мы создадим далее, если ми будем с такой частотой менять значения на индикаторе наш глаз не будет замечать эти изменения(для нормального отображения значений на 7 сегментном индикаторе необходима частота приблизительно в 763 Гц). Для этого подключим экземпляр делителя частоты:

   mfp_clock_divider_50_MHz_to_763_Hz mfp_clock_divider_50_MHz_to_763_Hz
        (clock, display_clock);

В исходных файлах делителя частоты с 50 MГц в 763 Гц нет. Поэтому мы добавим его в файл mfp_clock_dividers.v:



module mfp_clock_divider_50_MHz_to_763_Hz
(
    input  clki,
    output clko
);

    mfp_clock_divider
    # (.DIV_POW_SLOWEST (16))
    mfp_clock_divider
    (
        .clki    ( clki ),
        .sel_lo  ( 1'b1 ),
        .sel_mid ( 1'b0 ),
        .clko    ( clko )
    );

endmodule

На вход системы поступают сигналы reset и clock, RsRx, IO_Buttons. Но у нас на входе топ модуля сигнал i_clk, а не clock. Дело в том что на плате присутствует тактовый генератор в 12 МГц, а процессор в FPGA может работать на частотах 50 МГц и выше, а что делать если у вас другая плата с другой тактовой частотой (например Nexys 4 DDR имеет тактовую частоту 100 МГц). Решается проблема созданием IP ядра Clocking Wizard (PLL), для этого откроем IP каталог:



Откроем Clocking Wizard:



Вкладку board оставляем как есть, либо настраиваем нужные нам входы и переходим на вкладку clocking options можно выбрать либо MMCM имеет более широкий диапазон входных частот 10...800МГц, чем PLL 19...800МГц, поскольку на cmoda7 всего 12 МГц выбираем MMCM, но для других плат можно выбирать другие параметры:



Во вкладке output clocks устанавливаем частоту 50 МГц (с частотой можно и нужно экспериментировать, так на других FPGA могут быть другие характеристики):



Также убираем reset и locked:



Port renaming, MMCM setting и Summary смотрим и оставляем как есть, жмем ОК, ОК, в следующем окне выбираем generate:

image

Последним штрихом сделаем непрерывное присваивание для RGB Led, поскольку как видно из схемы в плавающем состоянии они будут тускло светится, а мы хотим что бы они были выключены:

image

assign led0_r = 1'b1;
assign led0_g = 1'b1;
assign led0_b = 1'b1;

В конце напишем:

endmodule

Модуль оболочка создан, перейдем к изменению размера памяти.

Шаг 2. Уменьшаем объем памяти системы MIPSfpga для соответствия плате cmoda7


Плата cmoda7 имеет 225 Кбайт блоковой памяти. Таким образом, два блока памяти (128 Кбайт ОЗУ сброса и 256 Кбайт ОЗУ программ) не помещаются на плате cmoda7. Так как, загрузочный код может уместиться в 32 Кбайт, и можно ограничить потребности программ объемом 64 Кбайт. Таким образом, общая необходимая память (32 Kбайт + 64 Kбайт = 96 Kбайт) соответствует объему памяти платы cmoda7. Оставшиеся 225-96 = 129 Kбайт памяти могут быть использованы для других нужд системы MIPSfpga, например, в качестве кэш-памяти.

Уменьшить объем памяти можно, изменив размер памяти, заявленный в заголовочном файле Verilog который мы подключали в файл оболочку «mfp_ahb_lite_matrix_config.vh». Открываем файл mipsfpga_ahb_const.vh. Адреса ОЗУ сброса (или ОЗУ загрузки) состоят из 13 бит. Таким образом, объем ОЗУ сброса равен 213 32-битных слов = 215 байт = 32 Kбайт.



`define H_RAM_RESET_ADDR_WIDTH  13 

Адреса ОЗУ программ состоят из 14 бит. Таким образом, объем ОЗУ программ равен 214 32-битных слов = 216 байт = 64 Kбайт.

`define H_RAM_ADDR_WIDTH  14

Шаг 3. Создаем файл ограничений cmoda7


Теперь создадим «cmoda7.xdc» который устанавливает соответствие между внешними сигналами модуля-оболочки и выводами корпуса FPGA платы cmoda7 (xdc файл с полным списком выводов для cmoda7):






## Clock signal 12 MHz
set_property -dict {PACKAGE_PIN L17 IOSTANDARD LVCMOS33} [get_ports i_clk]
create_clock -period 83.330 -name sys_clk_pin -waveform {0.000 41.660} -add [get_ports i_clk]

## Buttons
set_property -dict {PACKAGE_PIN A18 IOSTANDARD LVCMOS33} [get_ports i_btn0]
set_property -dict {PACKAGE_PIN B18 IOSTANDARD LVCMOS33} [get_ports i_btn1]

## LEDs
set_property -dict {PACKAGE_PIN B17 IOSTANDARD LVCMOS33} [get_ports led0_b]
set_property -dict {PACKAGE_PIN B16 IOSTANDARD LVCMOS33} [get_ports led0_g]
set_property -dict {PACKAGE_PIN C17 IOSTANDARD LVCMOS33} [get_ports led0_r]

## Pmod Header JA
set_property -dict {PACKAGE_PIN G17 IOSTANDARD LVCMOS33} [get_ports {JA[0]}]
set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS33} [get_ports {JA[1]}]
set_property -dict {PACKAGE_PIN N18 IOSTANDARD LVCMOS33} [get_ports {JA[2]}]
set_property -dict {PACKAGE_PIN L18 IOSTANDARD LVCMOS33} [get_ports {JA[3]}]
set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports {JA[4]}]
set_property -dict {PACKAGE_PIN H19 IOSTANDARD LVCMOS33} [get_ports {JA[5]}]
set_property -dict {PACKAGE_PIN J19 IOSTANDARD LVCMOS33} [get_ports {JA[6]}]
set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS33} [get_ports {JA[7]}]

## GPIO Pins 1 - 6   7_segment_ind
set_property -dict {PACKAGE_PIN M3 IOSTANDARD LVCMOS33} [get_ports {seg[1]}]
set_property -dict {PACKAGE_PIN L3 IOSTANDARD LVCMOS33} [get_ports {an[1]} ]
set_property -dict {PACKAGE_PIN A16 IOSTANDARD LVCMOS33}[get_ports {an[2]} ]
set_property -dict {PACKAGE_PIN K3 IOSTANDARD LVCMOS33} [get_ports {seg[5]}]
set_property -dict {PACKAGE_PIN C15 IOSTANDARD LVCMOS33}[get_ports {seg[0]}]
set_property -dict {PACKAGE_PIN H1 IOSTANDARD LVCMOS33} [get_ports {an[3]} ]

## GPIO Pins 43 - 48  7_segment_ind
set_property -dict {PACKAGE_PIN U3 IOSTANDARD LVCMOS33} [get_ports {seg[3]}]
set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS33} [get_ports {seg[4]}]
set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS33} [get_ports dp    ]
set_property -dict {PACKAGE_PIN W7 IOSTANDARD LVCMOS33} [get_ports {seg[2]}]
set_property -dict {PACKAGE_PIN U8 IOSTANDARD LVCMOS33} [get_ports {seg[6]}]
set_property -dict {PACKAGE_PIN V8 IOSTANDARD LVCMOS33} [get_ports {an[0]} ]

## UART
#set_property -dict { PACKAGE_PIN J18   IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L7N_T1_D10_14 Sch=uart_rxd_out
set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS33} [get_ports RsRx]

Например, следующая строка устанавливает соответствие между входом i_clk и выводом корпуса FPGA L17, на который поступает тактовый сигнал с частотой 12 МГц с платы cmoda7.

set_property -dict {PACKAGE_PIN L17 IOSTANDARD LVCMOS33} [get_ports i_clk]
create_clock -period 83.330 -name sys_clk_pin -waveform {0.000 41.660} -add [get_ports i_clk]

Так же в файл ограничений нужно добавить следующие выходные временные ограничения для сигналов:

# I/O virtual clock
create_clock -period 83.330 -name "clk_virt"

# tsu/th constraints
set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports i_btn0]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports i_btn0]
set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports i_btn1]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports i_btn1]
set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports led0_b]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports led0_b]
set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports led0_g]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports led0_g]
set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports led0_r]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports led0_r]

## PMOD ALS
set_output_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports {JA[0]}]
set_output_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports {JA[0]}]
set_output_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports {JA[1]}]
set_output_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports {JA[1]}]
set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports {JA[2]}]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports {JA[2]}]
set_output_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports {JA[3]}]
set_output_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports {JA[3]}]

set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports {seg[]}]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports {seg[]}]
set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports {an[]}]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports {an[]}]
set_input_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports dp]
set_input_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports dp]
set_output_delay -clock "clk_virt" -min -add_delay 0.000 [get_ports RsRx]
set_output_delay -clock "clk_virt" -max -add_delay 10.000 [get_ports RsRx]

Тест MIPSfpga


Мы можем протестировать портированый на нашу плату процессор, для этого нужно зайти в файл конфигурации «mfp_ahb_lite_matrix_config.vh» и расскоментируем строку:

`define MFP_DEMO_LIGHT_SENSOR



Таким образом мы подключили написанный на Verilog модуль интерфейса SPI к шине AHB Lite для соединения с датчиком освещённости PmodALS фирмы Digilent.

Модуль SPI
module mfp_pmod_als_spi_receiver
(
    input             clock,
    input             reset_n,
    output            cs,
    output            sck,
    input             sdo,
    output reg [15:0] value
);

    reg [21:0] cnt;
    reg [15:0] shift;

    always @ (posedge clock or negedge reset_n)
    begin       
        if (! reset_n)
            cnt <= 22'b100;
        else
            cnt <= cnt + 22'b1;
    end

    assign sck = ~ cnt [3];
    assign cs  =   cnt [8];

    wire sample_bit = ( cs == 1'b0 && cnt [3:0] == 4'b1111 );
    wire value_done = ( cnt [21:0] == 22'b0 );

    always @ (posedge clock or negedge reset_n)
    begin       
        if (! reset_n)
        begin       
            shift <= 16'h0000;
            value <= 16'h0000;
        end
        else if (sample_bit)
        begin       
            shift <= (shift << 1) | sdo;
        end
        else if (value_done)
        begin       
            value <= shift;
        end
    end

endmodule




Схема подключения изображена на рисунке:



Датчик подключен к порту Pmod, выходи которого описаны в «cmoda7.xdc» прописаны как JA[7..0].

## Pmod Header JA
set_property -dict {PACKAGE_PIN G17 IOSTANDARD LVCMOS33} [get_ports {JA[0]}]
...
set_property -dict {PACKAGE_PIN K18 IOSTANDARD LVCMOS33} [get_ports {JA[7]}]

Полученую RTL схему можно доследить во вкладке RTL Analisys -> Schematic, где модуль интерфейса SPI «mfp_pmod_als_spi_receiver» находится в «mfp_system»:



Что бы загрузить в FPGA созданный проект нужно сгенерировать bitstream файл «cmoda7.bit», для этого во вкладке Program and Debug -> Generate Bitstream и подождать завершения операции:



После создания bitstream файла нужно его загрузить в плату, для этого во вкладке Program and Debug -> откроем Open Hardware Manager -> Open Target -> Auto Connect -> Program Device и загрузим систему:



Загрузка программы для работы с датчиком


Чтобы процессор обменивался с датчиком данными нужно написать программу и загрузить в блок RAM1 который так же подключён к шине AHB Lite.

Процессор MIPSfpga программируют с использованием инструментов разработки Codescape компании Imagination. Установите Codescape SDK и OpenOCD. Codescape поддерживает программирование как на языке C, так и на языке ассемблера.

Для загрузки кода в систему нужно перейти в папку скачаного mipsfpga plus -> github -> mipsfpga-plus -> programs-> 01_light_sensor откроем «mfp_memory_mapped_registers.h».

#define MFP_LIGHT_SENSOR_ADDR   0xBF800014

и

#define MFP_LIGHT_SENSOR        (* (volatile unsigned *) MFP_LIGHT_SENSOR_ADDR  )

далее откроем main.c и напишем пару строк:

#include "mfp_memory_mapped_registers.h"

int main ()
{
    int n = 0;

    for (;;)
    {
        MFP_7_SEGMENT_HEX = MFP_LIGHT_SENSOR;
    }

    return 0;
}

После в папке находим скрипт который компилирует код:

02_compile_and_link

Генерируем motorola_s_record файл:

08_generate_motorola_s_record_file

Проверяем к какому СОМ порту подключен USB UART преобразователь:

11_check_which_com_port_is_used

Изменяем файл 12_upload_to_the_board_using_uart:

set a=7 
mode com%a% baud=115200 parity=n data=8 stop=1 to=off xon=off odsr=off octs=off dtr=off rts=off idsr=off type program.rec >\.\COM%a%

где а – номер СОМ порта, к которому подключен USB UART преобразователь. И загружаем программу:

12_upload_to_the_board_using_uart

Результат портирования системы можно посмотреть на видео:





Для понимания работы процессора, и возможности написания новых модулей на языке описания аппаратуры (Verilog, VHDL), а так же схемотехники, архитектуры компьютера, микроархитектуры (организация процессорного конвейера) и программирования на ассемблере, и много чего другого что поможет вам взять старт в изучении всего что связано с электроникой рекомендуется прочитать книгу про которую написано в статье: Бесплатный учебник электроники, архитектуры компьютера и низкоуровневого программирования на русском языке.

В следующей части будет описано как подключать различную периферию в систему MIPSfpga на примере клавиатуры Digilent Pmod KYPD, встроенной АЦП, и LCD дисплея от Nokia.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329808/


Ко-маркетинг как способ монетизации мобильных приложений

Вторник, 30 Мая 2017 г. 16:15 + в цитатник
image

Из всех бизнес-моделей, которые используются для продвижения и монетизации, ко-маркетинг, или взаимовыгодное партнерство — направление самое молодое. Недостаток внимания к форме маркетинговой активности, которая предполагает совмещение усилий и получение взаимных выгод, объясняется рядом факторов. И это не только отсутствие мотивации и понимания, зачем это нужно, но и длительное согласование деталей работы с партнерами, нежелание делиться клиентской базой, отстаивание только своих интересов и многие, многие другие.

При этом ко-маркетинг на порядок перспективнее и имеет большее количество выгод и преимуществ по сравнению с другими формами продвижения. Партнерство с компанией, которая имеет аналогичную целевую аудиторию, а также возможность интегрировать свои продукты в приложение партнера или создавать совместными усилиями более ценные продукты открывают новые, и главное – эффективные, пути для увеличения прибыли. Ключевое значение также играет возможность принести пользу своим клиентам, что повышает лояльность, число рекомендаций и положительных отзывов. При условии работы с подходящими партнерами и постоянной подпитки сотрудничества с другим брендом, монетизация может быть ускорена в несколько раз.

Пример #1. Создание нового продукта

В качестве примера, когда в союзе двух разработчиков рождался более эффективный и ценный продукт, можно привести совместный проект Localytics и Optimizely.

Платформа Localytics позволяет в режиме использовать аналитику для мобильных приложений, разделять пользователей по сегментам, анализировать активность, узнавать, откуда он пришел и что делает. Американская компания Optimizely имеет схожее направления, но больше специализируется на оптимизации программного обеспечения для других компаний, беря за основу все те же пользовательские предпочтения.

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

По словам Трэвиса Брайанта – вице-президента по продажам и партнерскому направлению Optimizely, компания стремится предоставить своим клиентам возможность интеграции с лучшими в своем классе платформами. «Мы рады, что Localytics присоединиться к партнерской экосистеме Optimizely, чтобы помочь нашим клиентам добиваться лучших результатов в Интернете и на мобильных устройствах».

Вместе Localytics и Optimizely способны предоставить клиентам расширенные возможности тестирования, мобильную аналитику, таргетинг и инструменты для многоканального маркетинга, который помогает принимать решения на основе имеющихся данных. Клиенты также могут использовать эту интеграцию, чтобы выполнить полный анализ воронки, основанный на тестовых результатах от Optimizely, а затем использовать маркетинговые функции Localytics' для целевых пользователей. По мнению Брайана Сатоффа — стратегического директора Localytics, интеграция с Optimizely помогает клиентам лучше понять, что работает, а что нет, и подбирать лучшие способы вовлечения пользователей.

Когда одна компания в большей степени специализируется на получении и обработке данных, а вторая — на создании инструментов, объединение имеющихся ресурсов открывает пути для создания более ценного и эффективного продукта.

Такая форма сотрудничества может быть использована, если:
· ваше приложение обладает достойным функционалом для того, чтобы стать интересным другим разработчикам;
· вы открыты к совместной работе с коллегами, готовы проявлять гибкость и идти на уступки;
· трезво оцениваете собственные ресурсы и ожидаемые выгоды

Пример #2. Поощрение

Как вариант ко-маркетингового взаимодействия может быть использована такая модель партнерских отношений, при которой пользователи за выполнение определенных действий получают награды от партнеров разработчика. Такой формат может предполагать плату разработчику за возможность стать частью приложения и войти в систему мотивации. Приложение также может зарабатывать, беря долю дохода от вознаграждения, которые было активировано пользователем.

Например, за активное использование приложения при занятиях спортом пользователь может быть награжден скидкой в магазин спортивной одежды или бесплатным посещением фитнес-зала. За своевременное внесение данных в календарь беременности будущие мамы могут получить скидку в соответствующие магазины и т.д. Таким образом, увеличивается функциональность приложения, повышается лояльность пользователей, а при взаимной рекламе можно рассчитывать на привлечение новых пользователей.

Такая рекламная стратегия лучше воспринимается пользователями, нежели традиционная реклама, поскольку имеет отношение к выбранному пользователем приложению и отвечает цели этого приложения. При этом все участники взаимодействия получают свои выгоды. Разработчики увеличивают доход, рекламодатели получают больше рекламного пространства, а пользователи — бесплатные промо.

Интеграция логотипа партнерского бренда или создание интерактивного элемента, отсылающего к компаньону, — это готовый путь для переключения трафика на партнерское приложение. При выполнении необходимых условий пользователям можно дать возможность разблокировать эксклюзивные награды и поощрения, предоставляемые партнерами. Используя эту стратегию, монетизация приложения проходит безболезненно для пользователей, не раздражая их навязчивыми рекламными баннерами.

Эта модель может пригодиться, если:
· у вас есть приложение, которое позволяет вручать награды за активность в приложении;
· вы против использования навязчивых рекламных баннеров;
· открыты к новому и необычному;
· не боитесь стимулировать скачивание стороннего приложения и не боитесь обмена пользовательскими группами.

Пример #3. Расширение функционала

Еще одним вариантом получения дополнительной прибыли является расширения функционала мобильного приложения. Например, в приложение-еженедельник можно включить функцию оплаты счетов, вызова такси, бронирования столика в ресторане, билетов в кино и т.д. Имея раскрученный ежедневник, разработчик может сделать платный «вход» для рекламодателей или брать процент от пришедшего клиента.

Кто мешает фитнес-приложениям добавить в свой функционал возможность заказывать продукты в магазинах здорового питания? А приложению, связанному с автомобилями, взять в партнеры магазин автозапчастей и т.д.?

Нечто подобное внедряет крупнейший телекоммуникационный оператор Японии DKKI. Он активно сотрудничает со многими компаниями. Не так давно партнером стала страховая компания LIFENET Insuarane. Интеграция предполагает полное объединение платформ, что позволит пользователям выбирать услуги страхования жизни или имущества из приложения мобильного оператора.

Совместный маркетинг в мобайл имеет широчайшие перспективы с точки зрения объединения возможностей товаропроизводителей и мобильных разработчиков. Включение в функционал новых возможностей выгодно обеим сторонам. Но тут возникает другой вопрос — где искать партнеров, открытых к сотрудничеству? Англоязычные разработчики используют платформу Hubspot.

Для россйиских маркетологов и разработчиков подобный функционал предоставляет платформа АКО-М, объединившая более 500 участников, среди которых ритейлеры, производители, застройщики, крупные и мелкие предприниматели. Для участников такое взаимодействие перспективно с точки зрения расширения аудитории. В первую очередь, это интересно компаниям-производителям товаров и услуг. Взаимодействие с более сильным брендом поможет проложить путь дальше по воронке продаж.

Ко-маркетинг как бизнес-направление только начинает развиваться. Но поскольку миллионы людей ежедневно используют смартфоны и планшеты по сотне раз, грамотный маркетинг приложений является ключевой задачей любого разработчика. Объединение усилий позволяет достигать целого ряда преимуществ, среди которых ведущими являются возможность сократить расходы на продвижение и получить доступ к новой аудитории.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329806/


Много бессмысленных переписок

Вторник, 30 Мая 2017 г. 15:58 + в цитатник
Одна из root cause нашего ежегодного опроса вовлеченности звучит именно так. С одной стороны, это мировой тренд: нам все больше нравится отложенная коммуникация текста и голосовых сообщений. А с другой, проблема в качестве текста. Грамотность формулирования вопросов и ответов по e-mail, знание инструментов почтовых программ — это отдельный важный бизнес-навык. Здесь на помощь приходят тренинги soft skills, публичные рекомендации и опыт коллег. Остается только навести фокус. А вот о выгодах интерактивной коммуникации предлагаю поразмышлять.

image

СОКР личного пространства


На беседе по итогам испытательного срока моя новая сотрудника сказала, что все ей понятно и нравится, кроме одного: слишком много переписки. «Ведь куда проще, — сказала она, — подойти к человеку и обсудить вопрос голосом». Это ее первая большая компания.


Что же произошло? Почему мы вдруг стали считать, что звонок — это не радость общения и технологическое чудо, а безобразное вторжение в личное пространство? Думали ли психологи, что их рекламная кампания «частных зон» приведет к массовому отключению звука у мобильных телефонов?

Бесспорно, экология личного пространства — это ценно. Информации и возможностей общения стало так много, что сами по себе они перестали доставлять радость. Поэтому мессенджеры с их отложенностью (текста, звука) — это однозначно полезная опция. Но есть одно «но». Отложенность хороша как раз в личном пространстве: дома, на отдыхе, на обеде. Но не работе. Здесь другие критерии экологии.

Рабочее время — это часы, которые вы продали компании. И в это время ваш телефон, особенно если его оплачивает компании, должен быть включен и востребован. К тому же онлайн-общение — один из эффективнейших инструментов, созданных (и совершенствуемых до сих пор) для решения рабочих задач.

О хорошем тоне


Что получается? С одной стороны, наши девайсы все дальше и глубже развивают сервисы, помогающие нам уходить в «подполье». А с другой, этика вокруг них пока еще не успела сформироваться и каждый сам выбирает, в каких случаях ему нужно перезвонить после неотвеченного вызова…

А что, если сформулировать несколько рекомендаций и предложить их для корпоративного использования? Понятные и одинаковые для всех правила коммуникации, как известно, делают ее продуктивнее.

В дополнение к почтовой этике, которая уже укрепилась в нашей компании (дать ссылку на сайт), предлагаю:

Рекомендация №1. Телефон — это такое же средство рабочей коммуникации, как и e-mail. Голосовое общение в Lynk, Skype, sms, Whatsapp, Telegram — все, что используют члены вашей команды, рабочей группы, ваше руководство и подчиненные, стоит использовать и вам. Договоритесь с рабочей группой, какой канал вы используете для решения срочных вопросов. Пусть в этой договоренности будет не только e-mail и правило включенного звука в течение рабочего дня.

Ежегодно мы проводим награждения лучших сотрудников: большое и торжественное мероприятие. Организаторы — наши HR — координируются в реальном времени в «Телеграме».

image

Рекомендация №2. Да, телефонный звонок — это теперь сложно. Как остаться вежливым, но решить срочную задачу или вопрос, который «проще объяснить голосом»? Самое простое решение — согласовать время звонка. Если срочность «второго уровня», то это можно сделать письменно с помощью e-mail или мессенджера, привязанного к номеру. Если не ждет, то устно: «Удобно ли говорить сейчас?» или «Срочный вопрос. Есть пара минут?.. А когда перезвонить?»

То, что не написано, не существует


Один хорошо знакомый мне проектный менеджер начинает свое утро со звонков заказчикам и попутно их комментирует: «Вот, а этот товарищ только по телефону со всеми разговаривает. И потом: упс, я этого не говорил! И он прав: то, что не написано, не существует!».


Да, на управленческих тренингах нас именно этому и учат: обязательно фиксируйте все письменно, это повышает управляемость. И это очень хорошее правило, но до тех пор, пока оно не становится конечным пунктом развития событий: коммуникация = e-mail. Самое простое для нас, занятых интровертов, это перенести все рабочее общение в почту. И до какого-то момента это нормально. Пока не включается термин «критическая масса» и количество перестает переходить в качество.

Коллеги, вы правы: то, что не написано, не существует. Поэтому обязательно фиксируйте результаты «живого» общения. Письмом в виде meeting notes, смарт-задачей, стикером в TFS или Jira. Пусть это будет рекомендацией №3.

Застряли, правило трех писем, распределенные команды


Иногда нам кажется, что наше решение прекрасно или очевидно, а коллеги восторженно согласятся. Или ожидаем, что ответ на вопрос будет коротким и быстрым. И мы пишем письмо. Одно, второе, третье. В ответ или тишина, или уточняющие вопросы, или открытые комментарии — все это не дает никакого шанса вычеркнуть пункт из списка дел. Но по инерции мы продолжаем нажимать reply. И нам никак не встретить коллег-адресатов у кофе-машины, потому что они в нескольких тысячах километров от нас. Уверена, что ситуация знакома.

И в такой ситуации важно вспомнить про другие способы коммуникации. Быстрые вопросы можно уточнить сразу же голосом в чате, а потом, при необходимости, назначить общий звонок и подбить итоги. Потому что:

  1. «Живое» общение позволяет по-настоящему обсуждать проблему. Именно обсуждать, а не «описывать». Идеи, способные в интерактивном полилоге превратиться в решения, — это чудо! А многим из нас вообще лень писать все мысли на тему. На первый взгляд они могут казаться неважными, но по факту могут подсветить проблему с интересной стороны. Спор, интонирование, выразительное молчание, мелкие замечания — все это позволяет увидеть предмет обсуждения по-новому.
  2. Онлайн-коммуникация дает возможность выстроить более комфортные отношения с коллегами из других офисов, а значит повысить эффективность распределенной команды. Если вы ее часть, старайтесь чаще пользоваться телефоном или «Скайпом»: почта и мессенджеры лишают вас возможности построить личные взаимоотношения с коллегами. Идеальный способ — видеозвонок.
  3. Дедлайн в виде звонка стимулирует адресатов включиться в вопрос. В некоторых случаях письменная отложенная коммуникация —это законный способ «слить» проблему, отложить, проигнорировать: если адресат — «один из» или даты ответа размыты. Приглашение к интерактивной коммуникации в этом случае может оказаться единственной возможностью двигаться в вопросе.
  4. Разговор в разы быстрее позволяет выяснить, что имелось в виду на самом деле. Это свойство интерактивного общения особенно актуально в ситуации конфликта или его назревания. Если чувствуете, что переписка «напрягает», звоните, приглашайте на кофе.


Рекомендация №4. Не пишите короткие письма с короткими простыми вопросами. Их однозначно проще решить по любому из интерактивных каналов: телефон, чат, видеозвонок. Пример: «Сможешь расшарить презентацию со своего тренинга?» «Да». «До вечера сможешь?»

Рекомендация №5. Если вы отправляете уже третье письмо по вопросу, и оно не становится решающим, подумайте: может быть стоит остановить переписку и организовать «живое» общение. И вернуться в e-mail уже в виде готовых решений.

Рекомендация №6. Если в вашей рабочей группе коллеги, которых вы не видели давно, а может быть и ни разу, самое время выбрать вместо e-mail — устный разговор. Да, зафиксировать результаты. Но эффект «знакомства голосом», а тем более в режиме видеосвязи сложно переоценить.

Резюмируем


У нас получилось 7 ситуаций, когда имеет смысл выйти из переписки в онлайн. Есть ли что добавить?

image

Да, переводя тексты в устное общение, мы рискуем усилить «много бессмысленных совещаний». И это уже история про другой коммуникационный навык, который критично необходим любому бизнесу.

В нашей компании умению эффективно проводить совещания обучают на курсе «Как проводить деловые встречи и конференц-звонки». Ключевые фразы в нем: «3 минуты на звонок», «я не играю в глухой телефон», agenda, MN, ведущий звонка.

А какими правилами при выборе инструмента коммуникации руководствуетесь вы?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329796/


Метки:  

WebVR: второе рождение виртуальной реальности

Вторник, 30 Мая 2017 г. 15:56 + в цитатник
Виртуальная реальность (VR) снова вышла на передний план и становится одним из основных направлений развития индустрии. Все активнее развивается направление WebVR — технологии и средства, которые встраиваются напрямую в веб-браузеры и позволяют строить трехмерные объекты без использования собственных аппаратных и программных платформ. Насколько это удобно, хорошо ли проработаны решения и каково будущее технологий VR, узнаем у экспертов.




WebVR может напрямую в браузере работать с современными терминалами типа Oculus Rift, Google Cardboard, HTC Vive и другими.  По сути это направление предлагает единые стандарты, которым следуют и создатели браузеров, и разработчики аппаратных решений, и производители контента. Это позволяет избежать «зоопарка устройств», несовместимых между собой решений, пользователям не нужно мучиться выбором — какую платформу предпочесть, а у разработчиков контента есть единый набор правил, которому можно легко следовать. Кроме того, WebVR способен работать на любых устройствах, независимо от ОС и аппаратных платформ, где работает браузер с поддержкой WebVR. Плюс, не нужно скачивать и устанавливать приложения и сам контент — все запускается напрямую из интернета в браузере.

Из минусов технологии можно отметить невысокую скорость работы — в браузере много лишних прослоек, трансляция инструкций и т.д., все это отнимает заметную долю производительности. К тому же, браузеры, как правило, меньше оптимизированы под аппаратные и программные особенности конкретных устройств. Плюс, технология еще не достигла зрелости — не все еще реализовано в должной мере и обкатано, иногда встречаются ошибки и несовместимости.  Очень многое в статусе беты, включая сами браузеры.

О перспективности и перспективах Web VR мы решили поговорить с Мартином Сплиттом и Денисом Радиным.

Мартин Сплитт — инженер по ПО по фронт- и бэкенду в Archilogic. Евангелист и активный участник развития ПО с открытым кодом. Верит в веб-платформы и работает с самыми современными технологиями, направленными на развитие веба.

Денис Радин — фронтенд-инженер, разрабатывающий «встроенный» JavaScript в Liberty Global. Энтузиаст компьютерной графики и оптимизации быстродействия веб-приложений. Организатор AmsterdamJS и React Amsterdam. Ведет блог PixelsCommander.com.

— Пока технология VR — это либо узкая отрасль для гиков, либо развлечения (в том числе аттракционы на рынках, в залах игровых автоматов и пр.). Насколько растет использование технологий обычными пользователями (особенно вне игр)? Сохраняется ли интерес у старых пользователей, которые уже пользовались технологией?

Мартин Сплитт:
Технологии VR не настолько узконишевые, как может показаться. С другой стороны, они не так распространены на рынке, как хотели бы продемонстрировать их активные сторонники. В 2016 году объемы продаж оказались значительно ниже прогнозов (согласно им, объем рынка должен был достигнуть 10,7 млн устройств, а в реальности GearVR, Rift и Vive вместе продали примерно три млн устройств). Но некоторого успеха VR-технологии все же достигли. Более активно развивается рынок мобильных устройств: уровень продаж GearVR составил 2,2 млн шт, а Google Cardboard вообще разошелся феноменальным тиражом в 88 млн устройств.

Интересно отметить, что мобильные пользователи используют VR-устройства два-три раза в неделю, но не очень долго. При этом основной сценарий — это не игры, а развлечения и журналистика. Впрочем, игры не стоит сбрасывать со счетов — в конце концов, третьим устройством по объему продаж стала Playstation VR.

Денис Радин: На первый взгляд действительно кажется, что основная шумиха спала и VR становится специализированной технологией, но давайте посмотрим, что это за специализации: обучение, медицина, игровая индустрия. Вот, например, PornHub дает бодрый отчет — полмиллиона DAU в VR. Выходит, что специализации очень разнообразные и VR занимает свои ниши там, откуда, вполне вероятно, еще раз начнет наступление на наши мониторы через несколько лет. Я все-таки думаю, что мониторы со временем исчезнут. Зачем нужна доска с диагональю 27 дюймов, если можно получить 360 градусов рабочего пространства, используя мобильный телефон? Особенно актуально это может быть для тех, кто часто бывает в рабочих поездках.

— Нет ли опасений, что VR повторит судьбу 3D? Какими вы видите причины провала 3D, какие шаги индустрия предпринимает и намерена предпринять, чтобы избежать той же судьбы для VR?

Мартин Сплитт:
Если речь идет о 3D-телевидении, то да, сейчас ситуация другая. Трехмерное телевидение не сумело набрать популярность как из-за отсутствия широкого интереса пользователей, так и из-за нехватки каких-то существенных преимуществ перед двухмерным ТВ-контентом. VR предлагает куда более глубокую степень погружения и более широкий спектр приложений. Так что мне кажется, что здесь не получится еще один «потерянный рынок».

Денис Радин: 3D-кинотеатры же не исчезли. VR развивается очень динамично, что же до рывка на широкий потребительский рынок, то здесь большие надежды подают Daydream и PS VR. Посмотрите на Daydream HMD: он мягкий, эластичный, тканевый, разработчики очень удачно перенесли VR из мира электронных устройств в мир аксессуаров, одежды. Пока непонятно, насколько это найдет отклик у покупателя, но можно легко представить, что через 10 лет у вас в одном шкафчике будут собраны уютные домашние тапочки, пижамка и свой мягкий персональный VR шлем.

— Будут ли использоваться элементы VR (именно VR, а не просто 3D) в обычных сайтах, интерфейсах и т.д.? Или останется узкая специализированная ниша типа 3D-моделей или презентаций?

Мартин Сплитт:
Скорее всего, они не будут заменять существующие элементы обычных интерфейсов или сайтов — скорее, станут дополнять их там, где существующие способы визуализации недостаточно хороши: в описании взаимодействия пространства и данных, образовании, науке, журналистике и описании продукции. Я бы не сказал, что это «нишевые возможности» — эти сферы применения достаточно широкие, и нам еще предстоит до конца определить, что там можно сделать. Однако опросы пользователей показывают, что там есть некоторые многообещающие перспективы.

Денис Радин: Мне вообще кажется, что неправильно ставить вопрос о каких-то узких нишах. Да, сейчас VR-устройств в мире намного меньше, чем мобильных телефонов, но их уже больше, чем ПК в начале 90-х. Те интерфейсы, что мы знаем, будут вынуждены адаптироваться к VR, в вебе WebVR можно ожидать в виде Progressive Enchancement. Например при отображении сайта продающего акваланги на устройстве с VR погружаем пользователя под воду, запускаем VR рыбок, VR водоросли, VR блики поверхности… Об этом в том числе я расскажу в своем докладе на HolyJS.

— Насколько сегодня технологии WebVR зрелые? Пока остается впечатление, что WebVR находится в статусе даже не беты, а альфы. В какую сторону идет развитие технологий в целом?

Мартин Сплитт:
Что касается готовности именно технологий, то мы постепенно подходим к этому. Еще есть над чем поработать, однако уже сейчас разработчики браузеров приняли технологию, идет активная работает над стандартом WebVR 2.0, а версию 1.1 можно назвать относительно стабильной. Я отвечал за внедрение WebVR на базе более ранних версий API, и могу сказать, что уже тогда сложностей было немного.

Однако у WebVR та же проблема, что и у VR в целом — мы все еще пытаемся найти оптимальные пути ее использования. Вопрос не в самой технологии, а в таких вещах, как удобство использования (UX), собственно представление истории и интерфейсы (UI). Например, сейчас появляются новые способы взаимодействия с пользователем, а также новые пути расширения WebVR относительно «традиционного» 3D-контента в интернете.

Денис Радин: Технология сама по себе рабочая, сейчас ее успешное использование скорее ограничивает недостаток эффективных инструментов разработки и низкая распространенность устройств по сравнению с теми же смартфонами. Конечно, намного проще и эффективней сделать сайтик на HTML/CSS и показать его на экранах смартфонов миллиардам потенциальных пользователей, но вторая сторона медали в том, что эти миллиарды уже имеют доступ к огромному массиву продуктов. Поэтому, чтобы выделиться, нужно искать новые средства выражения и модели взаимодействия.

— Насколько развита экосистема: поддержка браузеров, функции, возможности, библиотеки? Эти веб-приложения или технологии опираются на возможности браузера (или внешних библиотек)? Насколько сильное сообщество? Как поддерживают крупные коммерческие игроки рынка?

Мартин Сплитт:
Я уже говорил раньше, что и экосистема, и стандарты стали сильными и устойчивыми. Google, Mozilla, Microsoft, Samsung и Facebook вместе работают над тем, чтобы внедрить WebVR в свои браузеры. Технологии уже есть в Google Chrome для Android, находятся в финишной стадии в Firefox и уже работают в Firefox Nightly, Microsoft вскоре внедрит их в Edge, браузер GearVR от Samsung поддерживает их уже достаточно давно, а Facebook внедряет их в своей браузер Carmel. Они есть даже в экспериментальном браузерном движке Servo от Mozilla.

Один из наиболее крупных игроков рынка, который хочет использовать WebVR вне собственно браузера, — это Facebook. В рамках ReactVR они хотят дать разработчикам React возможность проще и легче начать использование WebVR.

Что касается сообществ, то у нас есть отличное активное сообщество у Mozilla A-Frame, поэтому приобщиться к WebVR можно уже прямо сейчас.

Денис Радин: Поддержка браузеров пока не так хороша, как хотелось бы, но в целом достаточная: Firefox, Chrome + полноценный WebVR в Android Chrome (!), а это в перспективе весь сегмент Android. Тут очень любопытно, чем ответит Apple. Ведь в конце концов им тоже придется внедрять поддержку, деваться некуда.

Если говорить о библиотеках, то тут у Three.js с его плагинами нет конкурентов. Unity при экспорте в веб так же использует Three.js. Экосистема там, конечно, неплохая, но, надеюсь, кто-то из альтернативных движков сможет избавить нас от монополии в долгосрочной перспективе.

— Предполагается, что WebVR позволит унифицировать работу за счет единых стандартов. Ранее уже предпринимались подобные попытки, однако они приводили лишь к появлению нескольких конкурирующих или вовсе несовместимых стандартов. Есть ли шанс, что сейчас удастся реализовать задуманное?

Мартин Сплитт:
Недавние технологии, такие как CSS grid, WebGL или Web Components, ясно показали, что мы уже прошли тот период, когда необходимо было работать с некорректными, несовместимыми реализациями в разных браузерах. Большая часть разработчиков браузеров достигла взаимопонимания, а учитывая, что нас вскоре ждут такие вещи, как Web Assembly, в будущем у нас будет все больше и больше возможностей создавать разные варианты виртуальной реальности, работающие во всех браузерах.

Вряд ли мы окажемся у разбитого корыта, а опыт Facebook, занимающегося разработкой и WebVR, и React, внушает мне надежду, что мощная платформа появится у нас скорее раньше, чем позже.

Денис Радин: Ну почему же? Web сдержал обещание и стал самой универсальной средой для создания интерфейсов. Думаю, WebVR разделит его успех, но это в большей степени завязано на энтузиазм больших игроков, публики и разработчиков. Поскольку сейчас все стороны заинтересованы в успехе, думаю, что все получится. Небольшой конфликт произошел вокруг WebGL, ведь этот стандарт не предполагает использование отличного от OpenGL интерфейса(например Direct3D) однако этот момент оперативно взяла в работу WebGPU рабочая группа в которую входят представители многих компаний.

— Нет ли войны стандартов? Насколько WebVR объединяет разработчиков контента, или они предпочитают создавать продукты под проприетарные платформы производителей оборудования?

Мартин Сплитт:
Контент — это всегда основа всего. Многие производители контента уже высказывали мнение, что они с удовольствием будут создавать контент для WebVR, поскольку это позволяет им получить более широкую аудиторию. Да и те, кто предпочитает Unity или другую проприетарную систему, тоже не останутся в стороне — Web Assembly даст возможность производителям контента сохранить возможность работы со своими инструментами, и при этом их контент будет работать и на веб-платформах.

Денис Радин: Стандарт — это все, что JavaScript + WebGL, а дальше разработчик сам решает в рамках стоящей задачи. Можно ожидать, что свое влияние окажут разрабатываемый WebGPU и только что вышедший WebAssembly, но это все детали реализации. Отображение контента в браузере через контекст OpenGL/Direct3D никуда не уйдет, хотя форматы данных для моделей развиваются весьма бурно. Есть несколько групп, работающих над форматами данных, которые можно было бы назвать «JPEG для 3D-моделей». Этому способствует и развитие технологий 3D-сканирования, в частности Tango. Посмотрим, что из этого выйдет…

— «Традиционные» технологии VR требуют для взаимодействия с ними очки или шлем, что создает отдельные сложности — нужно надевать шлем, да и сидеть в нем долго не очень комфортно. Пропадает легкость использования. С WebVR ситуация аналогична. Окажет ли это какое-то влияние на дальнейшее развитие  технологии?

Мартин Сплитт
: Это проблема скорее не WebVR, а VR в целом. Тут я не смогу много сказать, поскольку не занимаюсь разработкой аппаратных платформ для VR, но просто подумайте — если посмотреть на ноутбуки, скажем, пятилетней давности, то они куда тяжелее и толще, чем современные модели.



Денис Радин:  Легкость использования обусловлена качеством устройств. Да, конечно, Oculus Rift был большим шагом по сравнению со шлемами первой волны 90х, но они все еще очень громоздки и далеки от того, чтобы быть незаметными при ношении. Мягкий, компактный Daydream, о котором я уже упоминал, тут видится серьезным шагом вперед, и это только начало.



— Смотреть — это хорошо. А какие идеи насчет того, как в будущем управлять браузером в VR? Махать руками? Или как?

Мартин Сплитт
: Если взглянуть в прошлое, то такие вещи мы всегда отвратительно предсказывали. Вспомните Google Glass. Но если уж придется заняться предсказаниями, то я бы сказал, что ввод должен осуществляться с помощью движений рук — может, с помощью жестов. Может, отслеживание рук… пока сложно сказать. Ввод с помощью луча (типа лазерной указки) — пока в тумане, т.к. это может работать как с контроллерами  (контроллер daydream, контроллеры для работы с рукой от Vive/Oculus), так и без него (используя взгляд пользователя).

Денис Радин: На картинке выше мы видим небольшой пульт с акселерометром. Можно им махать, можно нажимать кнопки, можно вот удочку позакидывать.

Каждый тип шлема имеет свои контроллеры, работающие по похожему принципу, но с разным количеством функций и разной эргономикой. Увы, надежней таких коробочек с акселерометрами пока ничего нет, хотя, конечно, заслуживает упоминания контроллер Leap Motion. Он все еще ощутимо зависит от условий установки и освещения, но за последние 5 лет сделал большой рывок вперед. Его можно использовать в WebVR через JS API, позволяющее читать положение пальцев.



— Каково ваше видение WebVR, если технология в техническом плане станет успешной. Какие задачи обычных пользователей (кроме развлечения, это недолговечно) она будет решать? Один из примеров — возможность виртуального шоппинга, есть ли другие? И какие изменения она принесет в социальном плане? Не станет ли  VR при повсеместном распространении конкурентом нашей реальности?

Мартин Сплитт
: Ну, не знаю, насколько это нам поможет в совершении обычных покупок. Я скорее вижу основные выгоды от использования VR там, где нам сложно что-то сделать в реальном мире.

Например, хотя мир превращается в глобальное сообщество, я не могу раз в два дня прыгать на самолет, чтобы слетать к своим родителям, а телефонные разговоры и даже видеозвонки — это все-таки не то. В этом плане VR может помочь мне получить впечатления, которые недоступны в реальной жизни.

Мне кажется, основным направлением будут коммуникации и развлечения, как вариант — виртуальный тур по местам, куда мы сами не можем попасть, или просмотр фильмов или курсов, которые нам недоступны.

Такие сценарии использования обществу будет легче воспринять, чем «просто вместе тусоваться в VR». Но со временем все может измениться.  В свое время обмен сообщениями люди более старшего возраста считали антисоциальным и глупым, а он стал основной формой общения среди молодежи. Кто знает, может, вместо того, чтобы постоянно пялиться в телефон, мы когда-нибудь будем носить шлемы, которые позволят нам проводить время с друзьями в VR, например, во время поездок на работу.

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

Денис Радин:  Виртуальное рабочее пространство, обучающие материалы, продажа недвижимости и туристических услуг через интернет — это то, что приходит в голову первым. Огромные рынки, пресыщенные обычными веб-приложениями, которые ждут свежих, эффективных решений. Ну и, конечно, общение в виртуальной реальности… Обычно именно интересов к этому направлению объясняют решение Facebook купить Oculus.

Кто-то назовет это началом классической антиутопии, где все сидят дома и общаются в виртуальном мире, но так смотреть на вещи как минимум скучно, да и необъективно. Давайте посмотрим на ближайшее прошлое… За последние полвека мы получили компьютеры и огромное количество сидячих рабочих мест, но тем не менее, в обществе наоборот процветает культ здоровья, и оно никогда еще не было более спортивным и здоровым, и никогда не жило так долго, как сейчас.

Сомнений в необходимости технологии нет. Я с нетерпением жду новых событий в развитии инструментов, браузеров, устройств. Очень хочу, чтобы больше разработчиков начали работать с WebGL и трехмерными пространствами в браузере, ведь именно наличие талантливых специалистов в первую очередь определяет потенциал технологии.



Глубже погрузиться в тему виртуальной реальности можно будет в Петербурге на конференции HolyJS, где с интересными докладами выступят оба эксперта. Денис Радин расскажет о том, «как интегрировать существующие web-приложения в мир виртуальной реальности», давая пользователям новые возможности и UX, а себе дозу фана.

А Мартин Сплитт уже рассказывал о WebVR на предыдущей HolyJS, и в этот раз выступит с другой темой «Rendering performance from the ground up» - о «перформансе по ступеням»: как разметка превращается в пиксели, как они собираются в целую страницу и чем мы можем помочь платформе в ускорении наших сайтов.

Более подробное описание интересных докладов можно найти тут, а вся программа конференции представлена на официальном сайте мероприятия.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329786/


Метки:  

Ещё раз о хранении логов в Zabbix

Вторник, 30 Мая 2017 г. 15:51 + в цитатник


Тема сбора и хранения логов в Zabbix поднималась уже не раз. И не два. Если не учитывать, что это не вполне корректный подход, серьёзно нагружающий базу, у таких способов есть еще один существенный недостаток – они хранят логи целиком. И если в случае с логами роутеров или Linux с этим можно как-то смириться, то event-log Windows начинает доставлять много страданий, как серверу Zabbix, так и системному администратору, который решится его собирать и хранить. Ниже — о решении этой проблемы.

Лирическое отступление


Всех технарей уже ждут в следующем кабинете, а мы немного приостановимся, переведём дух, вынырнем из нашего уютного пушистого IT-мирка с единорогами и попытаемся определить, стоит ли овчинка выделки. Ведь есть же специализированные решения, best practices и прочие слова, напрочь убивающие фантазию и любовь к своему колхозику с заборами из костылей. Я искренне рад за людей, у которых полный ELK стек, шарды, отказоустойчивость и миллионы строк лога в секунду. Эти полубоги редко снисходят со своих сияющих вершин до нас, простых смертных. А потому им не понять простого желания мониторить всю свою инфраструктуру и при этом не быть задушенным жабой. А в мониторинг входят не только числовые показатели. Например, подсистема безопасности Windows Server манипулирует практически только логами. И если нет необходимости стрелять из пушки по воробьям, и уже есть налаженный мониторинг на основе Zabbix, то почему бы не расширить его возможности? Возможно, я сейчас скажу банальность, но мониторинг инфраструктуры – краеугольный камень своевременной реакции на инциденты, так что необходимость иметь у себя в арсенале такой инструмент как сборщик и анализатор логов, совместимый с Zabbix и потребляющий минимум ресурсов, не должна обсуждаться.

За дело!


Обычно при обработке Event-лога придерживаются следующей схемы.



EvtSys — крохотный сервис, который преобразует сообщения EventLog в стандарт Syslog.
У этой связки есть, как минимум, 2 недостатка:

  • Microsoft не особенно церемонится с размерами сообщений лога, зачастую превышающих 4 кб, в которых есть и сообщение об ошибке, и справка по решению, и ссылки на развернутое решение, и кони, и цыгане, и медведи… И все такое прочее. И это при том, что, кроме самого сообщения, больше ничего не надо. В итоге, мы храним в базе тонны бесполезной информации, а место на дисках нерезиновое.
  • На каждое новое сообщение RSyslog создаёт новый форк для zabbix_sender и при большом количестве поступающих данных можно запросто заддосить себе сервер сбора логов, что тоже неприятно.

Именно поэтому расчехляем свой велосипедостроитель и начинаем ваять наш дивный новый мир.

Общая концепция


У нашего нового транспортного средства будет треугольное колесо следующая схема работы.



Heka – это сердце нашего пепелаца. Она почти, как Logstash, только труба пониже и дым пожиже. Зато без JRuby, а, значит, не так требовательна к ресурсам и, к тому же, потрясающе шустра. Спокойно переваривает и обрабатывает несколько тысяч строк лога в секунду. Примерно так:



При этом легко и непринужденно расширяется с помощью плагинов, что в дальнейшем и будет проделано. Общая логика работы системы такова. Поступающие сообщения EvtSys приводит к формату Syslog и передает на обработку Heka. Та парсит syslog-сообщение, выделяет внутреннюю часть сообщения (payload) и парсит далее регулярным выражением, формируя новую строку лога. Эта строка передаётся напрямую в Zabbix с помощью самописного плагина. Размещается всё необходимое на Zabbix-сервере, отдельной машине или, как в нашем случае, на Zabbix-прокси. Такой подход к работе системы устраняет оба ранее озвученных недостатка. Разберёмся подробнее, как всё это устроено внутри.

Настройка EvtSys


Не буду детально останавливаться на настройке EvtSys, это было неоднократно сделано до меня, например, тут. Отмечу лишь основные моменты, важные для работы решения. Версия EvtSys должна быть не ниже 4.5. Это связано с тем, что при инсталляции будет использоваться ключ -t. Рекомендуется брать LP версию, потому что она может отправлять сообщения больше 2 кб, что для нас актуально. Команда установки EvtSys:

evtsys -i -h  -p  -f 17 -t 


Для Windows-логов я использую facility local1, вы же можете использовать то, что больше подходит именно вам. Особое внимание следует уделить параметру -t. В нём надо указать имя узла сети именно так, как оно указано в Zabbix. Это поле Heka может быть использовано для отправки сообщений правильным узлам сети в Zabbix.

Настройка конвейера обработки сообщений


Вот мы и добрались до самой интересной и вкусной части нашего решения. Установку Heka я описывать тоже не буду, она тривиальна до ужаса и хорошо расписана в официальной документации. Поэтому просто примем, что Heka уже установлена и перейдём сразу к её настройке. Как и в Logstash, в Heka реализован конвейер преобразования логов на основе меток. Общий путь, который проходит обрабатываемая строка следующий:



Splitter и Filter могут отсутствовать в конвейере. У нас в конечном итоге так и будет. Какой путь пройдет строка лога, через какие фильтры и как в результате станет выглядеть, определяется условиями, основывающимися на полях внутреннего представления сообщения в Heka. Подробнее об этом можно почитать в документации, а нам сейчас надо сформировать следующий алгоритм работы Heka.

  1. Принять syslog-сообщение через UDP порт.
  2. Декодировать syslog-сообщение, выделить дополнительный тег.
  3. Распарсить текст строки лога (payload) и выделить из него ключевые параметры и значения.
  4. Сформировать на основе выделенных значений новую информативную строку лога.
  5. Закодировать строку лога в виде json-сообщения для Zabbix.
  6. Отправить закодированное сообщение в Zabbix.


Для реализации алгоритма выстраиваем функциональные блоки конвейера Heka следующим образом:



Отдельных пояснений заслуживает MultiDecoder. Он представляет собой контейнер для декодеров, которые могут выполняться либо все последовательно (именно таким образом настроено в syslog-decoder), так и до первого успешного декодирования (в events-decoder). Теперь посмотрим, как это реализовано в конфиге Heka. Чтобы не засорять основной конфиг, выносим всю конфигурацию в отдельный файл. У меня это /etc/heka/conf.d/20-eventlog.toml.

Конфиг Heka


Рассмотрим настройки каждого компонента по отдельности.

[eventlog]
type = "UdpInput"
address = ":10514"
decoder = "syslog-decoder"


Здесь в настройках указываем, что слушать будем на всех интерфейсах и порт берём больше 1024, чтобы не иметь проблем с правами доступа к порту. Именно этот порт надо указывать в EvtSys как порт syslog-сервера. Также сразу указываем декодер, которому будем передавать принятые сообщения.

[syslog-decoder]
type = "MultiDecoder"
subs = ["rsyslog-decoder", "events-decoder"]
cascade_strategy = "all"
#log_sub_errors = true


Как уже писалось выше, этот декодер является контейнером для других декодеров с двумя типами поведения (выполнить все декодеры или выполнять до первого успешного декодирования). Тип поведения задается параметром cascade_strategy и в данном случае он указывает, что надо выполнить все декодеры в порядке, указанном в параметре subs. Для отладки мультидекодера полезно использовать опцию log_sub_errors = true. При её указании Heka будет записывать ошибки декодирования sub-декодеров в свой лог.

[events-decoder]
type = "MultiDecoder"
subs = ["event-4624-decoder", "event-4625-decoder", "event-4724-decoder", "event-4738-decoder", "event-4740-decoder"]
cascade_strategy = "first-wins"
#log_sub_errors = true


Events-decoder сам по себе является мультидекодером, но стратегия поведения у него уже другая — first-wins. Она заставляет декодер выполняться, пока один из внутренних декодеров не вернёт успешно декодированные данные. Это помогает обрабатывать данные по нескольким шаблонам, что и будет продемонстрировано далее.

[rsyslog-decoder]
type = "SandboxDecoder"
filename = "lua_decoders/rsyslog.lua"
 
        [rsyslog-decoder.config]
        type = "RSYSLOG_TraditionalForwardFormat"
        template = '%TIMESTAMP% %HOSTNAME% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%'
        tz = "Europe/Moscow"


Один из стандартных декодеров, который входит в поставку Heka, по словам автора, поддерживает шаблоны логов от RSyslog. Но мне показалось, что не полностью. Обратите внимание на двойной параметр %HOSTNAME% в шаблоне лога. Это не опечатка, просто мне не удалось настроить шаблон так, чтобы параметр, который передается через -t в EvtSys, не слипался с текстом сообщения. А так мы получаем практически то, что надо, кроме одного маленького пустячка – в конце имени хоста стоит двоеточие. Мы его уберём при кодировании сообщения. Вы спросите: а как же парсится значение поля Hostname? А очень просто – новое значение просто перезаписывает старое.

Event-декодеры все похожи один на другой, как братья-близнецы, потому я рассмотрю только один. Отличия в остальных касаются только regexpдля парсинга и выходной строки лога.

[event-4624-decoder]
type = "PayloadRegexDecoder"
match_regex = '^(?P4624):(?:[^:]+:){10}\s(?P[^\s]+)[^:]+:\s(?P[^\s]+)(?:[^:]+:){8}\s(?P[^\s]+)'
 
        [event-4624-decoder.message_fields]
        Type = "windows.eventlog"
        Key = 'eventlog.%EventID%'
        Value = 'Успешный вход пользователя %Domain%\%Account% с адреса %IP%.'


Этот декодер прогоняет строку через регулярное выражение и при этом выделяет отдельные её части, которые можно использовать для создания дополнительных полей сообщения. Такие поля потом нам пригодятся для создания выходного сообщения. Также здесь выставляется тип сообщений (поле Type), чтобы направить их на соответствующий выход (связанный с соответствующим encoder-ом).

[ZabbixEncoder]
type = "SandboxEncoder"
filename = "lua_encoders/zabbix_trapper.lua"


А теперь жемчужина нашей коллекции – самописный плагин на Lua. Его работу я рассмотрю в свое время (ниже по течению текста). Здесь же достаточно написать, что он кодирует сообщение для Zabbix-а.

[event-out-zabbix]
type = "TcpOutput"
message_matcher = "Type == 'windows.eventlog'"
address = "127.0.0.1:10051"
encoder = "ZabbixEncoder"
reconnect_after = 1


Выход для пересылки сообщений в Zabbix. Пропускает через себя не всё, а только сообщения с соответствующим значением в поле Type. Каждое сообщение пропускает через Encoder, который мы описали выше.

Особое внимание рекомендую обратить на параметр reconnect_after = 1. Это очень важный параметр. Дело в том, что TcpOutput содержит в себе баг и не может долго поддерживать TCP сессию. Выглядит это примерно так: в определённый момент Zabbix вместо полноценных сообщений лога начинает получать какие-то ощипки, а потом прекращается и это. Если посмотреть обмен между Heka и Zabbix через Wireshark, можно увидеть, что TcpOutput начинает бить пакеты и связь обрывается. В итоге, чтобы это не происходило, выставляется вышеуказанный параметр, который заставляет TcpOutput переподключаться после каждой отправки сообщения на Zabbix. Да, естественно, это создаёт оверхед, но я не заметил сколь-нибудь значительного роста нагрузки и на хост с Heka, и на Zabbix-прокси. Может просто сообщений мало отправляю? ;)

Отладка обработки сообщений


Для отладки конвейера я рекомендую две вещи: RstEncoder и вывод в файл. RstEncoder кодирует каждое поле сообщения текстовой строкой, что позволяет видеть, из каких полей состоит сообщение и чему они равны. Вывод в файл помогает отслеживать, что кодируется, а что пропускается и как оно кодируется. Организовать вывод в файл можно так:

[event-out-file]
type = "FileOutput"
message_matcher = "Type == 'windows.eventlog'"
path = "/tmp/events.log"
perm = "666"
flush_count = 100
flush_operator = "OR"
encoder = "RstEncoder"


Все параметры здесь понятны, поясню только назначение параметра flush_operator = «OR». Он указывает, что новые порции сообщений должны дописываться к уже существующему файлу лога. Меняя encoder, можно проверять формат записываемых сообщений, а message_matcher поможет удостовериться, что сообщения имеют нужный тип. Отключая его, мы начинаем записывать всё. Иногда это помогает обнаружить ошибку в фильтре message_matcher или то, что сообщения не создаются.

Zabbix Trapper


И вот мы подошли к описанию того, как устроен кастомный encoder. Все дополнительные плагины должны лежать в /usr/share/heka/. Так как у нас это encoder, то кладем его сюда – /usr/share/heka/lua_encoders/zabbix_trapper.lua. Посмотрим, что за шестерёнки крутятся у него внутри.

Модуль Zabbix Trapper для Heka
require "os"
require "string"
require "table"
 
-- Библиотека JSON.
-- https://www.kyne.com.au/~mark/software/lua-cjson.php
local cjson = require("cjson")
 
function process_message()
-- Название хоста в Zabbix.
    local host = read_message("Hostname")
-- Ключ элемента данных.
    local key = read_message("Fields[Key]")
-- Значение элемента данных.
    local value = read_message("Fields[Value]")
 
-- Начинаем собирать JSON-сообщение. 
    local message = {}
-- Отрезаем паразитное двоеточие, которое у нас осталось со времён парсинга syslog сообщения.
    message["host"] = string.sub(host, 1, -2)
    message["key"] = key
    message["value"] = value
 
    local buffer = {message}
 
    local zabbix_message = {}
    zabbix_message["request"] = "sender data"
    zabbix_message["data"] = buffer
 
-- Создаём новый payload в сообщении, который состоит из подготовленного массива с данными, закодированного в JSON.
    inject_payload("json", "Payload", cjson.encode(zabbix_message))
    return 0
end



Библиотека CJSON должна лежать в месте, доступном Lua, поэтому я расположил её в /usr/share/heka/lua_modules/cjson.so.

Шаблон для Zabbix


Из особенностей шаблона следует отметить, что элементы данных должны быть типа Zabbix Trapper, с типом информации «Журнал (лог)» и ключами вида eventlog.1102.

Шаблон Zabbix


    3.0
    2016-10-01T13:30:30Z
    
        
            Шаблоны безопасности
        
    
    
        
    
    
        
            {Template Windows Users Audit:eventlog.4732.nodata(120)}=0
            {HOST.NAME}: Добавлен участник в защищённую локальную группу.
            
            0
            4
            {HOST.NAME}: Добавлен участник в защищённую локальную группу.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.1102.nodata(120)}=0
            {HOST.NAME}: Журнал аудита очищен.
            
            0
            4
            {HOST.NAME}: Журнал аудита очищен.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4740.nodata(120)}=0
            {HOST.NAME}: Заблокирована учётная запись пользователя.
            
            0
            3
            {HOST.NAME}: Заблокирована учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4735.nodata(120)}=0
            {HOST.NAME}: Изменена защищённая локальная группа безопасности.
            
            0
            4
            {HOST.NAME}: Изменена защищённая локальная группа безопасности.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4738.nodata(120)}=0
            {HOST.NAME}: Изменена учётная запись пользователя.
            
            0
            4
            {HOST.NAME}: Изменена учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4781.nodata(120)}=0
            {HOST.NAME}: Изменено имя учётной записи.
            
            0
            4
            {HOST.NAME}: Изменено имя учётной записи.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4725.nodata(120)}=0
            {HOST.NAME}: Отключена учётная запись пользователя.
            
            0
            4
            {HOST.NAME}: Отключена учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4724.nodata(120)}=0
            {HOST.NAME}: Попытка сбросить пароль учётной записи.
            
            0
            4
            {HOST.NAME}: Попытка сбросить пароль учётной записи.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4731.nodata(120)}=0
            {HOST.NAME}: Создана защищённая локальная группа безопасности.
            
            0
            4
            {HOST.NAME}: Создана защищённая локальная группа безопасности.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4720.nodata(120)}=0
            {HOST.NAME}: Создана учётная запись пользователя.
            
            0
            4
            {HOST.NAME}: Создана учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4734.nodata(120)}=0
            {HOST.NAME}: Удалена защищённая локальная группа безопасности.
            
            0
            3
            {HOST.NAME}: Удалена защищённая локальная группа безопасности.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4726.nodata(120)}=0
            {HOST.NAME}: Удалена учётная запись пользователя.
            
            0
            3
            {HOST.NAME}: Удалена учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4733.nodata(120)}=0
            {HOST.NAME}: Удален участник из защищённой локальной группы.
            
            0
            3
            {HOST.NAME}: Удален участник из защищённой локальной группы.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4624.nodata(10)}=0
            {HOST.NAME}: Успешный вход пользователя в систему.
            
            0
            1
            {HOST.NAME}: Успешный вход пользователя в систему.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4625.nodata(120)}=0
            {HOST.NAME}: Учётной записи не удалось выполнить вход в систему.
            
            0
            2
            {HOST.NAME}: Учётной записи не удалось выполнить вход в систему.
{ITEM.LASTVALUE}
            0
            
        
    




Наверное, вы уже обратили внимание на странное устройство триггеров. Так как у нас нет порогового значения, и поступающие данные непостоянны, то такое построение триггеров показалось мне самым правильным. Триггер горит 2 минуты, при этом при высокой важности отправляются соответствующие уведомления и событие не теряется.

И что же в итоге?


Система получилась из разряда настроил и забыл. Усердно трудится на ниве эксплуатации уже несколько месяцев, не требуя никакого обслуживания. Конечно, как и у любой хорошей системы, потенциал расширения у нее есть. Из того, что планируется в будущем:

  • Больший спектр событий.
  • Оптимизация шаблона.
  • Поддержка отправки событий пакетами (будет хорошо при большом потоке).
  • Более оптимальное открытие и закрытие TCP соединения (уменьшить оверхед).


Ну, и под занавес капельку аналитики – графики очереди Zabbix-сервера при прямой записи лога в базу и после оптимизации.



Жалкая попытка включить прямое логирование – видно, как очередь ненормированно растет, а потом Zabbix трескается пополам, больного едва удалось спасти. Логировался один хост с достаточно высокой нагрузкой на security-лог.



Так уже больше похоже на правду. Да, некоторое количество сообщений по-прежнему торчит в очереди, но это не проблема Windows-логов, и в целом, по общей длине очереди можно оценить прирост производительности. Вдобавок, тут мониторятся два хоста, сообщений меньше не стало, но нагрузка именно этой подсистемы мониторинга успешно теряется на общем фоне.

P.S. Ни на что не претендуя, было интересно поделиться своим решением. Если кто-то знает альтернативные, буду рад вашим комментариям.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329794/


Метки:  

Intel представила 18-ядерный Core i9 Extreme из линейки Core X

Вторник, 30 Мая 2017 г. 15:39 + в цитатник
На выставке Computex 2017, проходящей в Тайване, компания Intel представила новую линейку процессоров. Серия называется Core X и состоит из высокопроизводительных чипов для ПК, ориентированных на геймеров и людей, работающих с ресурсоемким контентом. В линейку вошли более мощные версии уже представленных на рынке Core i5 и Core i7, а также процессоры Core i9.

/ фото Chris Isherwood CC

Самая младшая модель линейки — Core i5-7640X с четырьмя ядрами и таким же количеством потоков (предварительная стоимость $242).

В серии Core i7 X количество ядер равняется четырем или десяти, а количество потоков — восьми или двадцати. Что до серии Core i9 X, то в неё войдут процессоры с 12 и 16 ядрами, по 24 и 32 потока соответственно.

Также будет выпущен первый 18-ядерный десктопный процессор потребительского класса Core i9 Extreme с 36 потоками (предварительная стоимость $1999).

Он получил название Intel Core i9-7980X и является своеобразным ответом чипу Ryzen от AMD. Чип относится к семейству CPU Skylake-X, совместимому с материнскими платами LGA2066 (на чипсете X299) и имеет новую пересмотренную иерархию кешей: 24,75 мегабайт L3 и 18 мегабайт L2. Core i9-7980XE будет обладать показателями TDP на уровне 165 Вт.

Новые процессоры Skylake-X в качестве материала для передачи тепла от процессорного кристалла к теплораспределительной крышке будут использовать термопасту вместо металлического припоя с высокой теплопроводностью. Таким образом компания Intel планирует унифицировать технологию производства процессоров.

Известно, что в работе процессору будут помогать представленные ранее технологии Hyper-Threading и Turbo Boost Max 3.0. Последняя использует возможности драйвера и информации, хранимой в CPU, чтобы распределять нагрузки на самые быстрые ядра. Как ожидается, в рамках Turbo Boost 3.0, частоты Skylake-X будут возрастать вплоть до 4,5 ГГц.

О компании Intel

Intel — производитель электронных устройств и компьютерных компонентов, включающих микропроцессоры и наборы системной логики. Компанию основали Роберт Нойс и Гордон Мур в 1968 году. Intel внесли существенный вклад в развитие компьютерной техники — спецификации на множество портов, шин, стандартов и систем команд разрабатывались при участии Intel.

P.S. О чем еще мы пишем в нашем блоге:

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329398/


Метки:  

[Перевод] Node.js и cote: простая и удобная разработка микросервисов

Вторник, 30 Мая 2017 г. 15:33 + в цитатник

Метки:  

[Перевод] Chrome победил

Вторник, 30 Мая 2017 г. 15:08 + в цитатник
Примечание: Я семь лет работал в Mozilla и был техническим директором, прежде чем два года назад ушёл для основания стартапа в области ИИ

Неделю назад Mozilla опубликовала блог-пост, где подчеркнула свои усилия, чтобы сделать десктопный Firefox снова конкурентоспособным. В своё время я внимательно следил за рынком браузеров, но уже пару лет не изучал его. Пришло время посмотреть на некоторые цифры:



Диаграмма вверху показывает рыночную долю в процентах каждого из четырёх основных браузеров за последние шесть лет. Это данные StatCounter, и вы можете поспорить, что данные искажены множеством разных способов, но в глобальном смысле придётся с уверенностью сказать, что Chrome захватывает рынок браузеров, а всё кроме Safari уничтожается.

Тренд


Я пробовал несколько разных способов изобразить линию тренда, и лучше всего вроде подходит экспоненциальное приближение. Это довольно хорошо соответствует теориям о взрывном распространении инноваций и медленном закате старых технологий. Если шестилетний тренд сохранится, IE должен быть в значительной степени мёртв через два-три года. Firefox чувствует себя ненамного лучше, к сожалению, и направляется в сторону рыночной доли 2-3%. Для IE и Firefox такие низкие рыночные доли приведут к дальнейшему ускорению упадка, потому что веб-разработчики не тестируют сайты для браузеров с маленькой долей рынка. Встретив поломанную вёрстку, пользователи перейдут на другие браузеры, что вызовет ещё больший отток пользователей. Порочный цикл.

Доли Chrome и Safari не так хорошо совпадают с линией экспоненциального приближения, как IE и Firefox. Для Chrome причина может быть в том, что рыночная доля настолько велика, что Chrome уже не хватает новых пользователей. Некоторые застряли на старых операционных системах, которые не поддерживают Chrome. Недавний рост Safari не достаёт до тренда, вероятнее всего, из-за замедления роста устройств iOS.

Рыночная доля на десктопах


Изучение предыдущего графика может вводить в заблуждение, потому что там совмещаются рыночные доли на десктопах и мобильных устройствах. Safari/iOS доминирует на мобильных устройствах, в то время как у десктопного Safari очень маленькая доля. В свою очередь, Firefox по сути не представлен на мобильных устройствах. Так что взглянем только на цифры с десктопов.



К сожалению, этот график тоже не предсказывает иную судьбу для IE и Firefox. Общий рынок настольных компьютеров и ноутбуков медленно растёт (большинство продаж относятся к замене старых ПК, но добавляются и новые пользователи). Несмотря на расширение рынка, доля IE и Firefox неустойчиво снижается.

Больше пользователей?


Эрик упомянул в блог-посте, что у Firefox в прошлом году прибавилось пользователей. За этот период относительная рыночная доля Firefox снизилась с 16% до 14,85%. Для сравнения, положение десктопного Safari практически не изменилось. Вероятно, это означает, что рыночная доля Safari растёт вместе с (медленным) ростом рынка ПК/ноутбуков. Есть две разные теории, что имел в виду Эрик, упоминая в блог-посте рост количества пользователей. Может быть, он имел в виду рост количества установок. Люди часто переустанавливают браузер на новом компьютере, что можно назвать «новым пользователем», но после этого часто старый компьютер больше не используется. Также возможно, что общая суточная аудитория в самом деле выросла из-за роста рынка ПК/ноутбуков, несмотря на глубокий провал относительной рыночной доли. Статистика по суточной аудитории Firefox не является открытой, так что трудно сказать.

Из этих графиков довольно очевидно, что Firefox не развивается. Это значит, что почитаемая Лисичка останется с нами много-много лет, несмотря на постоянно уменьшающуюся долю рынка. Это также означает, к сожалению, что разворот почти невозможен.

Со сменой CEO около трёх лет назад было принято стратегическое решение, что в Mozilla снова сконцентрирует усилия на Firefox и десктопном рынке. До 2014 года Mozilla активно вкладывала в развитие мобильной ОС для конкуренции с Android: Firefox OS. Я начал проект Firefox OS и довёл его до масштаба. Хотя мы показали некоторый всплеск и продали несколько миллионов устройств, но не смогли угнаться за взрывным ростом Android. Многие не понимают стратегической аргументации Mozilla для разработки Firefox OS. Изначальной миссией Mozilla было создание веба путём создания браузера. Мобильный рынок основательно подорвал эту миссию. На мобильных устройствах браузер не настолько важен и нужен, а тем более сторонний мобильный браузер. На мобильных устройствах браузер — это функция приложений Facebook и Twitter, а не продукт. Для влияния на веб через мобильные устройства Mozilla должна была выстроить весь стек с вебом в своём ядре. Разработка мобильных браузеров (Firefox Android) или браузероподобных приложений (Firefox Focus) вряд ли соответствует значительному числу сценариев использования. И у Firefox Android, и у Firefox Focus рыночная доля близка к 0%.

Стратегическое решение 2014 года вернуться к Firefox, и вместе с тем вернуться на десктоп, имело важное значение для Mozilla. Как описал Эрик в своей статье, за последние годы проделано много великолепной технической работы с десктопным Firefox. Соответствующие группы разработки расширены, а усилия в области мобильной разработки свёрнуты. Десктопный Firefox сегодня технически конкурентоспособен с десктопным Chrome во многих областях, а в некоторых даже превосходит его. К сожалению, из графиков видно, что всё это не оказывает никакого эффекта на рыночные тенденции. Браузеры — это продукт массового потребления. Они выглядят почти одинаково и работают почти одинаково. Все браузеры работают довольно хорошо, и если один из них будет работать чуть быстрее или потреблять чуть меньше памяти, то вряд ли это повлияет на пользователей. Даже если сам Эрик — который возглавляет маркетинговый отдел Mozilla — каждый день использует Chrome, как он упомянул в первом предложении, то неудивительно, что почти 65% десктопных пользователей делают то же самое.

Что это значит для веба?


Я начал проект Firefox OS в 2011 году, потому что уже тогда был убеждён в смерти десктопов и браузеров. Не мгновенной смерти — сейчас прошло шесть лет, и они по-прежнему с нами — но это две старые технологии, которые недостаточно влиятельны, чтобы двигаться дальше. Я не думаю, что когда-нибудь произойдёт новая война браузеров, в которой Firefox или какой-нибудь другой конкурент отнимет рыночную долю у Chrome. Это как представить новую и улучшенную лошадь в 2017 году. Мы все уже на машинах. Некоторые всё ещё ездят на лошадях, и лошади имеют ценность, но технология транспорта ушла вперёд.

Значит ли это, что Google владеет вебом так же, как она владеет Chrome? Нет. Совершенно нет. Браузеры — это то, как выглядел веб в первые десятилетия Интернета. Смартфоны подорвали веб, но веб переварил смартфоны, так что в сердце большинства приложений сегодня работает JavaScript, HTTPS и REST. Будущий веб опять же станет совершенно иным. Многое останется, а некоторые его части будут разрушены. Я покинул Mozilla, потому что мне стало интересно, как будет выглядеть веб, когда он останется преимущественно на устройствах, а не на десктопах и мобильных телефонах. В компании Silk мы создали платформу IoT на основе веб-технологий, таких как JavaScript, и многое делаем для освобождения прав на информацию, встраивая ИИ в устройства вместо отправки всех данных в облако.

Так что пусть Google выиграл войну браузеров, но они не получили веб. Возвращаясь к метафоре про лошадей: Google делает лучших лошадей в мире и они точно победили в скачках. Я просто не думаю, что скачки продолжатся в будущем.

Дополнение: Много хороших комментариев в ветке HackerNews здесь. Больше всех мне нравится этот: «Mozilla выиграла войну браузеров. Firefox проиграл следующую схватку. Но осталось ещё много сражений, и я надеюсь, что Mozilla вступит в новое». Не могу не согласиться.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329780/


Метки:  

Ещё раз о хранении логов в Zabbix

Вторник, 30 Мая 2017 г. 15:05 + в цитатник


Тема сбора и хранения логов в Zabbix поднималась уже не раз. И не два. Если не учитывать, что это не вполне корректный подход, серьёзно нагружающий базу, у таких способов есть еще один существенный недостаток – они хранят логи целиком. И если в случае с логами роутеров или Linux с этим можно как-то смириться, то event-log Windows начинает доставлять много страданий, как серверу Zabbix, так и системному администратору, который решится его собирать и хранить. Ниже — о решении этой проблемы.

Лирическое отступление


Всех технарей уже ждут в следующем кабинете, а мы немного приостановимся, переведём дух, вынырнем из нашего уютного пушистого IT-мирка с единорогами и попытаемся определить, стоит ли овчинка выделки. Ведь есть же специализированные решения, best practices и прочие слова, напрочь убивающие фантазию и любовь к своему колхозику с заборами из костылей. Я искренне рад за людей, у которых полный ELK стек, шарды, отказоустойчивость и миллионы строк лога в секунду. Эти полубоги редко снисходят со своих сияющих вершин до нас, простых смертных. А потому им не понять простого желания мониторить всю свою инфраструктуру и при этом не быть задушенным жабой. А в мониторинг входят не только числовые показатели. Например, подсистема безопасности Windows Server манипулирует практически только логами. И если нет необходимости стрелять из пушки по воробьям, и уже есть налаженный мониторинг на основе Zabbix, то почему бы не расширить его возможности? Возможно, я сейчас скажу банальность, но мониторинг инфраструктуры – краеугольный камень своевременной реакции на инциденты, так что необходимость иметь у себя в арсенале такой инструмент как сборщик и анализатор логов, совместимый с Zabbix и потребляющий минимум ресурсов, не должна обсуждаться.

За дело!


Обычно при обработке Event-лога придерживаются следующей схемы.



EvtSys — крохотный сервис, который преобразует сообщения EventLog в стандарт Syslog.
У этой связки есть, как минимум, 2 недостатка:

  • Microsoft не особенно церемонится с размерами сообщений лога, зачастую превышающих 4 кб, в которых есть и сообщение об ошибке, и справка по решению, и ссылки на развернутое решение, и кони, и цыгане, и медведи… И все такое прочее. И это при том, что, кроме самого сообщения, больше ничего не надо. В итоге, мы храним в базе тонны бесполезной информации, а место на дисках нерезиновое.
  • На каждое новое сообщение RSyslog создаёт новый форк для zabbix_sender и при большом количестве поступающих данных можно запросто заддосить себе сервер сбора логов, что тоже неприятно.

Именно поэтому расчехляем свой велосипедостроитель и начинаем ваять наш дивный новый мир.

Общая концепция


У нашего нового транспортного средства будет треугольное колесо следующая схема работы.



Heka – это сердце нашего пепелаца. Она почти, как Logstash, только труба пониже и дым пожиже. Зато без JRuby, а, значит, не так требовательна к ресурсам и, к тому же, потрясающе шустра. Спокойно переваривает и обрабатывает несколько тысяч строк лога в секунду. Примерно так:



При этом легко и непринужденно расширяется с помощью плагинов, что в дальнейшем и будет проделано. Общая логика работы системы такова. Поступающие сообщения EvtSys приводит к формату Syslog и передает на обработку Heka. Та парсит syslog-сообщение, выделяет внутреннюю часть сообщения (payload) и парсит далее регулярным выражением, формируя новую строку лога. Эта строка передаётся напрямую в Zabbix с помощью самописного плагина. Размещается всё необходимое на Zabbix-сервере, отдельной машине или, как в нашем случае, на Zabbix-прокси. Такой подход к работе системы устраняет оба ранее озвученных недостатка. Разберёмся подробнее, как всё это устроено внутри.

Настройка EvtSys


Не буду детально останавливаться на настройке EvtSys, это было неоднократно сделано до меня, например, тут. Отмечу лишь основные моменты, важные для работы решения. Версия EvtSys должна быть не ниже 4.5. Это связано с тем, что при инсталляции будет использоваться ключ -t. Рекомендуется брать LP версию, потому что она может отправлять сообщения больше 2 кб, что для нас актуально. Команда установки EvtSys:

evtsys -i -h  -p  -f 17 -t 


Для Windows-логов я использую facility local1, вы же можете использовать то, что больше подходит именно вам. Особое внимание следует уделить параметру -t. В нём надо указать имя узла сети именно так, как оно указано в Zabbix. Это поле Heka может быть использовано для отправки сообщений правильным узлам сети в Zabbix.

Настройка конвейера обработки сообщений


Вот мы и добрались до самой интересной и вкусной части нашего решения. Установку Heka я описывать тоже не буду, она тривиальна до ужаса и хорошо расписана в официальной документации. Поэтому просто примем, что Heka уже установлена и перейдём сразу к её настройке. Как и в Logstash, в Heka реализован конвейер преобразования логов на основе меток. Общий путь, который проходит обрабатываемая строка следующий:



Splitter и Filter могут отсутствовать в конвейере. У нас в конечном итоге так и будет. Какой путь пройдет строка лога, через какие фильтры и как в результате станет выглядеть, определяется условиями, основывающимися на полях внутреннего представления сообщения в Heka. Подробнее об этом можно почитать в документации, а нам сейчас надо сформировать следующий алгоритм работы Heka.

  1. Принять syslog-сообщение через UDP порт.
  2. Декодировать syslog-сообщение, выделить дополнительный тег.
  3. Распарсить текст строки лога (payload) и выделить из него ключевые параметры и значения.
  4. Сформировать на основе выделенных значений новую информативную строку лога.
  5. Закодировать строку лога в виде json-сообщения для Zabbix.
  6. Отправить закодированное сообщение в Zabbix.


Для реализации алгоритма выстраиваем функциональные блоки конвейера Heka следующим образом:



Отдельных пояснений заслуживает MultiDecoder. Он представляет собой контейнер для декодеров, которые могут выполняться либо все последовательно (именно таким образом настроено в syslog-decoder), так и до первого успешного декодирования (в events-decoder). Теперь посмотрим, как это реализовано в конфиге Heka. Чтобы не засорять основной конфиг, выносим всю конфигурацию в отдельный файл. У меня это /etc/heka/conf.d/20-eventlog.toml.

Конфиг Heka


Рассмотрим настройки каждого компонента по отдельности.

[eventlog]
type = "UdpInput"
address = ":10514"
decoder = "syslog-decoder"


Здесь в настройках указываем, что слушать будем на всех интерфейсах и порт берём больше 1024, чтобы не иметь проблем с правами доступа к порту. Именно этот порт надо указывать в EvtSys как порт syslog-сервера. Также сразу указываем декодер, которому будем передавать принятые сообщения.

[syslog-decoder]
type = "MultiDecoder"
subs = ["rsyslog-decoder", "events-decoder"]
cascade_strategy = "all"
#log_sub_errors = true


Как уже писалось выше, этот декодер является контейнером для других декодеров с двумя типами поведения (выполнить все декодеры или выполнять до первого успешного декодирования). Тип поведения задается параметром cascade_strategy и в данном случае он указывает, что надо выполнить все декодеры в порядке, указанном в параметре subs. Для отладки мультидекодера полезно использовать опцию log_sub_errors = true. При её указании Heka будет записывать ошибки декодирования sub-декодеров в свой лог.

[events-decoder]
type = "MultiDecoder"
subs = ["event-4624-decoder", "event-4625-decoder", "event-4724-decoder", "event-4738-decoder", "event-4740-decoder"]
cascade_strategy = "first-wins"
#log_sub_errors = true


Events-decoder сам по себе является мультидекодером, но стратегия поведения у него уже другая — first-wins. Она заставляет декодер выполняться, пока один из внутренних декодеров не вернёт успешно декодированные данные. Это помогает обрабатывать данные по нескольким шаблонам, что и будет продемонстрировано далее.

[rsyslog-decoder]
type = "SandboxDecoder"
filename = "lua_decoders/rsyslog.lua"
 
        [rsyslog-decoder.config]
        type = "RSYSLOG_TraditionalForwardFormat"
        template = '%TIMESTAMP% %HOSTNAME% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%'
        tz = "Europe/Moscow"


Один из стандартных декодеров, который входит в поставку Heka, по словам автора, поддерживает шаблоны логов от RSyslog. Но мне показалось, что не полностью. Обратите внимание на двойной параметр %HOSTNAME% в шаблоне лога. Это не опечатка, просто мне не удалось настроить шаблон так, чтобы параметр, который передается через -t в EvtSys, не слипался с текстом сообщения. А так мы получаем практически то, что надо, кроме одного маленького пустячка – в конце имени хоста стоит двоеточие. Мы его уберём при кодировании сообщения. Вы спросите: а как же парсится значение поля Hostname? А очень просто – новое значение просто перезаписывает старое.

Event-декодеры все похожи один на другой, как братья-близнецы, потому я рассмотрю только один. Отличия в остальных касаются только regexpдля парсинга и выходной строки лога.

[event-4624-decoder]
type = "PayloadRegexDecoder"
match_regex = '^(?P4624):(?:[^:]+:){10}\s(?P[^\s]+)[^:]+:\s(?P[^\s]+)(?:[^:]+:){8}\s(?P[^\s]+)'
 
        [event-4624-decoder.message_fields]
        Type = "windows.eventlog"
        Key = 'eventlog.%EventID%'
        Value = 'Успешный вход пользователя %Domain%\%Account% с адреса %IP%.'


Этот декодер прогоняет строку через регулярное выражение и при этом выделяет отдельные её части, которые можно использовать для создания дополнительных полей сообщения. Такие поля потом нам пригодятся для создания выходного сообщения. Также здесь выставляется тип сообщений (поле Type), чтобы направить их на соответствующий выход (связанный с соответствующим encoder-ом).

[ZabbixEncoder]
type = "SandboxEncoder"
filename = "lua_encoders/zabbix_trapper.lua"


А теперь жемчужина нашей коллекции – самописный плагин на Lua. Его работу я рассмотрю в свое время (ниже по течению текста). Здесь же достаточно написать, что он кодирует сообщение для Zabbix-а.

[event-out-zabbix]
type = "TcpOutput"
message_matcher = "Type == 'windows.eventlog'"
address = "127.0.0.1:10051"
encoder = "ZabbixEncoder"
reconnect_after = 1


Выход для пересылки сообщений в Zabbix. Пропускает через себя не всё, а только сообщения с соответствующим значением в поле Type. Каждое сообщение пропускает через Encoder, который мы описали выше.

Особое внимание рекомендую обратить на параметр reconnect_after = 1. Это очень важный параметр. Дело в том, что TcpOutput содержит в себе баг и не может долго поддерживать TCP сессию. Выглядит это примерно так: в определённый момент Zabbix вместо полноценных сообщений лога начинает получать какие-то ощипки, а потом прекращается и это. Если посмотреть обмен между Heka и Zabbix через Wireshark, можно увидеть, что TcpOutput начинает бить пакеты и связь обрывается. В итоге, чтобы это не происходило, выставляется вышеуказанный параметр, который заставляет TcpOutput переподключаться после каждой отправки сообщения на Zabbix. Да, естественно, это создаёт оверхед, но я не заметил сколь-нибудь значительного роста нагрузки и на хост с Heka, и на Zabbix-прокси. Может просто сообщений мало отправляю? ;)

Отладка обработки сообщений


Для отладки конвейера я рекомендую две вещи: RstEncoder и вывод в файл. RstEncoder кодирует каждое поле сообщения текстовой строкой, что позволяет видеть, из каких полей состоит сообщение и чему они равны. Вывод в файл помогает отслеживать, что кодируется, а что пропускается и как оно кодируется. Организовать вывод в файл можно так:

[event-out-file]
type = "FileOutput"
message_matcher = "Type == 'windows.eventlog'"
path = "/tmp/events.log"
perm = "666"
flush_count = 100
flush_operator = "OR"
encoder = "RstEncoder"


Все параметры здесь понятны, поясню только назначение параметра flush_operator = «OR». Он указывает, что новые порции сообщений должны дописываться к уже существующему файлу лога. Меняя encoder, можно проверять формат записываемых сообщений, а message_matcher поможет удостовериться, что сообщения имеют нужный тип. Отключая его, мы начинаем записывать всё. Иногда это помогает обнаружить ошибку в фильтре message_matcher или то, что сообщения не создаются.

Zabbix Trapper


И вот мы подошли к описанию того, как устроен кастомный encoder. Все дополнительные плагины должны лежать в /usr/share/heka/. Так как у нас это encoder, то кладем его сюда – /usr/share/heka/lua_encoders/zabbix_trapper.lua. Посмотрим, что за шестерёнки крутятся у него внутри.

Модуль Zabbix Trapper для Heka
require "os"
require "string"
require "table"
 
-- Библиотека JSON.
-- https://www.kyne.com.au/~mark/software/lua-cjson.php
local cjson = require("cjson")
 
function process_message()
-- Название хоста в Zabbix.
    local host = read_message("Hostname")
-- Ключ элемента данных.
    local key = read_message("Fields[Key]")
-- Значение элемента данных.
    local value = read_message("Fields[Value]")
 
-- Начинаем собирать JSON-сообщение. 
    local message = {}
-- Отрезаем паразитное двоеточие, которое у нас осталось со времён парсинга syslog сообщения.
    message["host"] = string.sub(host, 1, -2)
    message["key"] = key
    message["value"] = value
 
    local buffer = {message}
 
    local zabbix_message = {}
    zabbix_message["request"] = "sender data"
    zabbix_message["data"] = buffer
 
-- Создаём новый payload в сообщении, который состоит из подготовленного массива с данными, закодированного в JSON.
    inject_payload("json", "Payload", cjson.encode(zabbix_message))
    return 0
end



Библиотека CJSON должна лежать в месте, доступном Lua, поэтому я расположил её в /usr/share/heka/lua_modules/cjson.so.

Шаблон для Zabbix


Из особенностей шаблона следует отметить, что элементы данных должны быть типа Zabbix Trapper, с типом информации «Журнал (лог)» и ключами вида eventlog.1102.

Шаблон Zabbix


    3.0
    2016-10-01T13:30:30Z
    
        
            Шаблоны безопасности
        
    
    
        
    
    
        
            {Template Windows Users Audit:eventlog.4732.nodata(120)}=0
            {HOST.NAME}: Добавлен участник в защищённую локальную группу.
            
            0
            4
            {HOST.NAME}: Добавлен участник в защищённую локальную группу.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.1102.nodata(120)}=0
            {HOST.NAME}: Журнал аудита очищен.
            
            0
            4
            {HOST.NAME}: Журнал аудита очищен.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4740.nodata(120)}=0
            {HOST.NAME}: Заблокирована учётная запись пользователя.
            
            0
            3
            {HOST.NAME}: Заблокирована учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4735.nodata(120)}=0
            {HOST.NAME}: Изменена защищённая локальная группа безопасности.
            
            0
            4
            {HOST.NAME}: Изменена защищённая локальная группа безопасности.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4738.nodata(120)}=0
            {HOST.NAME}: Изменена учётная запись пользователя.
            
            0
            4
            {HOST.NAME}: Изменена учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4781.nodata(120)}=0
            {HOST.NAME}: Изменено имя учётной записи.
            
            0
            4
            {HOST.NAME}: Изменено имя учётной записи.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4725.nodata(120)}=0
            {HOST.NAME}: Отключена учётная запись пользователя.
            
            0
            4
            {HOST.NAME}: Отключена учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4724.nodata(120)}=0
            {HOST.NAME}: Попытка сбросить пароль учётной записи.
            
            0
            4
            {HOST.NAME}: Попытка сбросить пароль учётной записи.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4731.nodata(120)}=0
            {HOST.NAME}: Создана защищённая локальная группа безопасности.
            
            0
            4
            {HOST.NAME}: Создана защищённая локальная группа безопасности.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4720.nodata(120)}=0
            {HOST.NAME}: Создана учётная запись пользователя.
            
            0
            4
            {HOST.NAME}: Создана учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4734.nodata(120)}=0
            {HOST.NAME}: Удалена защищённая локальная группа безопасности.
            
            0
            3
            {HOST.NAME}: Удалена защищённая локальная группа безопасности.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4726.nodata(120)}=0
            {HOST.NAME}: Удалена учётная запись пользователя.
            
            0
            3
            {HOST.NAME}: Удалена учётная запись пользователя.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4733.nodata(120)}=0
            {HOST.NAME}: Удален участник из защищённой локальной группы.
            
            0
            3
            {HOST.NAME}: Удален участник из защищённой локальной группы.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4624.nodata(10)}=0
            {HOST.NAME}: Успешный вход пользователя в систему.
            
            0
            1
            {HOST.NAME}: Успешный вход пользователя в систему.
{ITEM.LASTVALUE}
            0
            
        
        
            {Template Windows Users Audit:eventlog.4625.nodata(120)}=0
            {HOST.NAME}: Учётной записи не удалось выполнить вход в систему.
            
            0
            2
            {HOST.NAME}: Учётной записи не удалось выполнить вход в систему.
{ITEM.LASTVALUE}
            0
            
        
    




Наверное, вы уже обратили внимание на странное устройство триггеров. Так как у нас нет порогового значения, и поступающие данные непостоянны, то такое построение триггеров показалось мне самым правильным. Триггер горит 2 минуты, при этом при высокой важности отправляются соответствующие уведомления и событие не теряется.

И что же в итоге?


Система получилась из разряда настроил и забыл. Усердно трудится на ниве эксплуатации уже несколько месяцев, не требуя никакого обслуживания. Конечно, как и у любой хорошей системы, потенциал расширения у нее есть. Из того, что планируется в будущем:

  • Больший спектр событий.
  • Оптимизация шаблона.
  • Поддержка отправки событий пакетами (будет хорошо при большом потоке).
  • Более оптимальное открытие и закрытие TCP соединения (уменьшить оверхед).


Ну, и под занавес капельку аналитики – графики очереди Zabbix-сервера при прямой записи лога в базу и после оптимизации.



Жалкая попытка включить прямое логирование – видно, как очередь ненормированно растет, а потом Zabbix трескается пополам, больного едва удалось спасти. Логировался один хост с достаточно высокой нагрузкой на security-лог.



Так уже больше похоже на правду. Да, некоторое количество сообщений по-прежнему торчит в очереди, но это не проблема Windows-логов, и в целом, по общей длине очереди можно оценить прирост производительности. Вдобавок, тут мониторятся два хоста, сообщений меньше не стало, но нагрузка именно этой подсистемы мониторинга успешно теряется на общем фоне.

P.S. Ни на что не претендуя, было интересно поделиться своим решением. Если кто-то знает альтернативные, буду рад вашим комментариям.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329770/


Метки:  

[Из песочницы] Создаем свой Angular 2

Вторник, 30 Мая 2017 г. 14:49 + в цитатник
Здравствуйте, в этой статье описан механизм работы Angular 2. Сегодня мы заглянем под капот популярного фреймворка.

Эта статья является вольным переводом доклада Тобиаса Боша (Tobias Bosch) — The Angular 2 Compiler. Ссылку на оригинал доклада Вы можете найти в конце статьи.

Овервью


Тобиас Бош – сотрудник компании Google и член рабочей группы разработчиков Angular, который создал большинство составляющих частей компилятора. Сегодня он рассказывает о том, как работает Angular изнутри. И это не что-то заоблачно сложное.

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

Что такое компилятор?


Это все, что происходит между входными данными приложения (ими могут быть ваши команды, шаблоны и т.д.) и вашим запущенным приложением.
angular2 compiler process
Все то, что происходит между ними – это сфера деятельности компилятора. С виду может показаться, что это чистой воды магия. Но это не так.

Что мы сегодня рассмотрим?


angular2 compiler agenda

Сначала мы немного поговорим о производительности: что имеется в виду под быстрой работой? Мы поговорим о том, какие виды входных данных у нас есть.

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

Также мы обсудим разные среды, достоинства и недостатки динамической (Just In Time) и статической (Ahead Of Time) компиляции.

Производительность: что означает быстрая работа?


Представим ситуацию: я написал приложение и утверждаю, что оно быстро работает. Что я имею в виду? Первое, что можно подумать, это то, что приложение очень быстро загружается. Возможно, вы видели AMP-страницы Google? Они загружаются нереально быстро. Это можно отнести к понятию «быстрый».

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

Или, скажем, у меня есть большая таблица и сейчас я просто изменю все ее значения. Я создаю новые значения без изменения структуры. Это реально быстро. Все это – разные аспекты одного и того же понятия, разные вещи, на которые нужно обращать внимание в приложении.

Переход по путям


Я хотел бы остановиться детальней на этапе перехода по путям (switching a route).

Важный момент, — при переходе по путям, фреймворк разрушает и воссоздает все заново. Он не придерживается структуры: все разрушается и все воссоздается заново.

Как можно сделать этот процесс быстрым?

Чтобы сделать что-то быстро, нужно измерить эту быстроту. Для этого нужен тест. Один из тестов на производительность, которые мы используем – это тест производительности по методу deep-tree. Возможно, вы слышали о таком. Это компонент, который используется дважды. Это рекурсия компонента до тех пор, пока не будет достигнута определенная глубина.

angular2 compiler benchmarks

У нас есть 512 компонентов и кнопки, которые могут разрушать или создавать эти компоненты. Далее мы замеряем, сколько времени уходит на разрушение и создание компонентов. Так и происходит переход по путям. Переход от одного view к другому. Разрушение всего – создание всего.

Какие у нас есть входные данные?

Компоненты

У нас есть компоненты, и я думаю, что их все знают.

angular2 compiler component

У них есть шаблон (template). Вы можете сделать шаблоны встроенными или поместить их в отдельный файл, стоит помнить что у них есть контекст.

Экземпляры компонентов по своей сути – это контекст, данные, которые используются для постройки шаблона (template). В нашем случае, у нас есть пользователь, у пользователя есть имя (в нашем случае это мое имя).

Шаблон

Далее у нас есть шаблон. Это простой HTML, сюда можно вставить что-то вроде формы ввода, можно применить вообще все, что предлагает HTML.

angular2 compiler template

Здесь мы имеем некоторый новый синтаксис: помните двойные фигурные скобки, квадратные и круглые скобки? Это привязка Angular к свойствам или событиям. Сегодня мы будем говорить только о фигурных скобках и о том, что они означают. С точки зрения семантики это значит «взять данные из компонента и поместить их в определенное место». При изменении данных должно происходить обновление текста.

Директивы

angular2 compiler directives

Директивы содержат селектор – это селектор CSS. Суть в том, что когда Angular проходит разметку, если он находит директиву, которая соответствует какому-то элементу, то выполняет ее.

Допустим, у нас есть селектор для форм, и этим мы как бы говорим, — каждый раз когда мы создаем элемент формы, пожалуйста создай эту директиву.

Точно так же и с ngModel. Когда вы создаете атрибут ngModel, вы должны создать и директиву.
У этих директив могут быть зависимости. Это наше выражение зависимости.

angular2 compiler directives

Зависимость имеет иерархическую структуру, таким образом, чтобы ngModel запрашивала ngForm.

И что же делает Angular?

Он просматривает все дерево в поисках ближайшей ngForm, которая на один уровень выше в структуре дерева. Он не будет просматривать одноуровневые элементы, только родительские.

Есть и другие входные данные, но мы не будем останавливаться на них подробно.

Все, что делается в Angular, проходит через компилятор.

Хорошо, у нас есть входные данные. Следующее, что нам необходимо – это понять их.
Это просто набор бреда, или, все-таки, это имеет какой-то смысл?

Процесс лексического анализа


Первая стадия


Допустим, у нас есть какой-то шаблон, к примеру, HTML.

Представление шаблона

angular2 compiler template

Как мы его можем представить таким образом, чтоб компилятор его понял?

Этим занимается анализатор. Он прочитывает каждый символ, а затем анализирует смысл. То есть, он создает дерево. У каждого элемента есть только один объект. Допустим, есть какое-то имя – имя элемента, есть дочерние элементы. Скажем так, текстовый узел представляет собой JSON объект с текстовыми свойствами. Также у нас есть атрибуты элемента. Скажем так, мы кодируем это все как вложенные списки. Первое значение – это ключ, второе – это значение атрибута. И так далее, здесь нет ничего сложного. Такая репрезентация называется абстрактным синтаксическим деревом (АСД, english — AST). Вы будете часто слышать это понятие. Это все – HTML.

Как мы можем изобразить связь элемента с данными?

angular2 compiler template

Мы можем отобразить это следующим образом. Это – текстовый узел, то есть у нас есть JSON объект с текстовыми характеристиками. Текст пустой, потому что изначально нет никакого текста для отображения. Текст зависит от входящих данных. Входящие данные представлены в этом выражении. Любые выражение также анализируются на предмет того, что же они означают. Они выглядят как JavaScript, их может быть больше или меньше. Здесь вы не можете применить функцию или цикл for, но у нас есть такая штука как потоки, как нечто особое, что можно применить в этом случае. Мы можем изобразить этот user.name как propPath (путь к характеристике), который можно прочитать.

Это, скажем, особый путь, который представляет данное выражение, а также мы может уловить, откуда именно из вашего шаблона это выражение пришло.

Определение места выражения
Так почему же это так важно? Почему нам важно знать, откуда именно из АСД пришло это выражение?

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

И потом, бывают же и исключения? Например, невозможно прочитать имя из undefined. Если такое происходит, тогда вам нужно отправиться в отладчик ошибок и проверить, установить точку прерывания на первой ошибке. Тогда вы должны понять, где именно произошла ошибка.

Компилятор Angular предоставляет вам больше информации

angular2 compiler template

Он показывает, из какого именно места в шаблоне «растут ноги» этой ошибки. Цель – показать вам, что ошибка берет свои истоки, например, из конкретно этой интерполяции во второй строке, 14 столбце вашего шаблона. Для этого нам нужно, чтобы номера строк и столбцов были в АСД.

Далее, какие нам нужны анализаторы, чтобы построить это АСД?

Здесь существует множество возможностей. Например, мы можем использовать браузер.

Браузер – отличный анализатор HTML, верно? Он занимается этим каждый день. Такой подход у нас был при разработке Angular 1, этот же подход мы начинали использовать при разработке Angular 2.

Сейчас мы не используем браузер в таких целях по двум причинам:

  1. из браузера нельзя вытащить номера строк и столбцов. При анализе HTML браузер просто не использует их.
  2. мы хотим, чтобы Angular работал и на сервере.

Очевидно, что на сервере нет браузера. Мы могли бы сказать: в браузере мы используем браузер, а на сервере мы используем нечто другое. Так и было. Но потом мы попали в тупиковые ситуации, например, с SVG, или с размещением запятых, поэтому нам нужно было, чтобы везде была одинаковая семантика. Поэтому, проще вставить фрагмент JavaScript, и анализатор. Это как раз то, что делаем мы.

Итак, мы говорили об HTML и выражениях.

Как мы представляем директивы, которые мы находим?

Мы можем отобразить их через JSON объекты, которые представляют элементы, просто добавив другое свойство: директивы. И мы ссылаемся на функции конструктора этих директив.

В нашем примере с вводными данными с ngModel, мы можем изобразить этот элемент как JSON объект. У него есть имя input, атрибуты, ngModel и директивы. У нас есть указатель на конструкторы, а также мы улавливаем зависимости, потому что нам нужно указать, что если мы создаем ngModel, нам нужна и ngForm, и нам нужно подхватить эту информацию.

Учитывая АСД с информацией HTML, связями и директивами, — как мы воплощаем это все в жизнь? Как это можно сделать проще всего?

Сначала разберемся с HTML. Какой самый простой способ создать элемент DOM? Во-первых, вы можете использовать innerHTML. Во-вторых, вы можете взять уже существующий элемент и клонировать его. И в-третьих, вы можете вызвать document.createElement.

Давайте проголосуем. Кто считает, что способ innerHTML – самый быстрый? А кто считает, что element.cloneNode быстрее всего создаст элемент? Или может, самый быстрый способ – это element.createElement?

Очевидно, все меняется с течением времени. Но на данный момент:

  • innerHTML – это самый медленный вариант. Это очевидно, потому что браузер должен вызвать свой анализатор, взять вашу строку, пройтись по каждому символу и построить элемент DOM. Очевидно, что это очень медленно.

    angular2 compiler innerHTML

  • element.cloneNode – это самый быстрый способ, потому что у браузера уже есть построенная проекция, и он просто клонирует эту проекцию. Это просто добавление в память еще одного элемента. Это все, что требуется сделать.

  • document.createElement – это нечто между двумя предыдущими способами. Этот способ очень близок к element.cloneNode. Чуть-чуть медленнее, но очень близок.

    angular2 compiler createElement

Вы скажете: «Хорошо, давайте будем использовать element.createElement для создания нового элемента DOM».

Так работал Angular 1, и так же мы начинали при разработке Angular 2. И по традиции, оказывается, что это не совсем честное сравнение, по крайней мере, не в случае с Angular. В случае использования Angular, нам нужно создать какие-то элементы, но, помимо этого, мы должны разместить эти элементы. В нашем случае мы хотим создать новые текстовые узлы, но также нам нужно найти именно тот, который отвечает за user.name, поскольку позже мы хотим обновить его.

Поэтому, если сравнивать, то мы должны сравнивать как создание, так и размещение. Если использовать innerHTML или cloneNode, то придется заново проходить весь путь построения DOM. При использовании createElement или createTextNode вы обходите эти действия стороной. Вы просто вызываете метод и сразу же получаете его исполнение. Никаких новых построений и прочего.

В этом отношении, если сравнивать createElement и createTextNode, они оба примерно одинаковы по скорости (зависимо от количества привязок).

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

Итак, мы уже можем создавать элементы DOM.

Теперь нам нужно создать директивы

Нам нужно внедрение зависимостей от дочернего элемента к родительскому. Допустим, у нас есть структура данных под названием ngElement, которая включает элемент DOM и директивы для данного элемента. Также есть родительский элемент. Это простое дерево внутри дерева DOM.

angular2 compiler dependency hierarchy

И как же мы можем создать элементы DOM из АСД?

У нас есть шаблон, у нас есть элемент, из которого мы построили АСД. Что мы можем сделать со всем этим?

angular2 compiler dependency hierarchy

В нашем ngElement и конструкторе вызываем document.createElement, просматриваем атрибуты и присваиваем их элементам, и дальше добавляем элемент к нашему родительскому элементу. Как видите, никакой магии.

Дальше переходим к директивам. Как это работает?

Мы просматриваем привязки, каким-то образом получаем их (расскажу об этом чуть позже) и просто повторно вызываем new для конструктора, отдаем ему привязки и сохраняем Map. Map будет переходить от типа директив (ngModel) к экземплярам директив.

И весь этот поиск директив будет работать таким образом: у нас будет метод, который получает директиву, которая сначала проверяет сам элемент (если ли у него директива). Если нет, то возвращаемся к родителю и проверяем там.

Это самое простое, что можно сделать. Мы сами начинали в этом направлении. И это работает.

Важная деталь: привязки. Как отобразить привязки?

Вы просто создаете класс binding, у которого есть target – Node. Им будет текстовый узел.
У target есть свойство, в нашем случае это будет значение узла, это место, куда поместится значение. И выражение.

angular2 compiler dependency binding

Привязка работает таким образом: каждый раз, когда вы оцениваете выражение или когда оно просто изменяется, вы сохраняете его в target.

То есть у вас может быть следующий метод: сначала вы оцениваете выражение, если оно изменилось – то обновляете target и другие сохраненные ранее значения.

angular2 compiler dependency binding

Что касается тех исключений, о которых речь шла ранее – мы вызываем методы try catch для отслеживания пути оценивания. Когда срабатывает исключение, мы его повторно генерируем и создаем для него модель из номеров строк и столбцов.

Так мы и получаем номера строк и столбцов, в которых есть ошибки. Это все мы связываем в представление. Это последняя структура данных.

angular2 compiler view

Представление – это элемент шаблона. То есть, когда мы просматриваем код ошибок – мы увидим много представлений. Это просто элементы шаблона. И их мы соединяем в представление. Представление ссылается на компонент, ng-элементы и привязки а также метод dirty-check, который просматривает привязки и проверяет их.

Вот мы и закончили первую стадию. У нас есть новый компилятор. Насколько мы быстры? Почти на таком же уровне, что и Angular 1. Уже неплохо. Используя подход проще, мы добились той же скорости. А ведь Angular 1 не медленный.

Вторая стадия



angular2 compiler dependency second step

Как нам ускорить процесс? Какой следующий шаг? Что мы упустили? Давайте разбираться.

Нам нужно что-то, что имеет отношение к нашим структурам данных. Когда дело касается структуры данных, на самом деле, это очень сложный вопрос. Если сравнивать с прошлой написанной нами программой, где появляется try-catch, но если отбросить это, мы увидим, что многие функции тормозят процесс, и что многие моменты нужно оптимизировать. Если вы считаете причиной медленной работы своей программы структуры данных, то это очень сложный вопрос, потому что они разбросаны по всей вашей программе. Это всего лишь предположение, что дело в структурах данных.

Мы провели эксперименты и попробовали разобраться. Мы наблюдали за этими директивами: Map внутри ngElements.

angular2 compiler dependency second step

Получается, что для каждого элемента в дереве DOM мы создаем новый map? Можно было бы сказать, что там нет директив, мы их не создавали. Но все-таки, мы всегда создаем map, наполняем его директивами и считываем с него информацию. Это может быть неэкономно, это может перегружать память, прочтение все-таки занимает тоже какое-то время.

Альтернативный подход: можно сказать: «Окей, мы разрешаем только 10 директив для одного элемента. Далее мы создаем класс inlinengElement, 10 свойств для элементов директив и типов директив, и для того, чтобы найти директиву мы создаем 10 условных операторов IF». Это быстрее? Возможно.

Это не потребляет много ресурсов памяти, да?

К примеру, установка: вы устанавливаете свойство, а не map. Чтение может быть немного медленным из-за 10 условий. Это как раз тот случай, для которого был оптимизирован JavaScript VM. JavaScript VM может создавать скрытые классы (можете погуглить о них на досуге). Это и делает JavaScript VM быстрее. Переключение на эту структуру данных – это то, что ускоряет процессы. Позже мы посмотрим на результаты тестов производительности. Еще одна штука, для которой нужно оптимизировать структуры данных – это повторное использование существующих экземпляров.

Можно задать логичный вопрос, — Если некоторые строки уничтожены, а другие восстанавливаются, то почему тогда не кешировать эти строки в кеше и изменять данные, как только строки появляются? Так мы и сделали. Мы создали так называемый view cache, который восстанавливает старые экземпляры представлений.

angular2 compiler view cache

Перед тем, как перейти в новый пул, нужно уничтожить состояние. Состояние содержится в директиве. Так мы убиваем все директивы. Далее, когда происходит выход из пула, нужно заново создать эти директивы. Этим занимаются методы hydrate и dehydrate. Узлы DOM мы сохранили, поскольку все происходит из модели, весь статус – в модели. Поэтому мы ее и сохранили. И снова мы провели тест на производительность.

Среда тестирования

Чтобы вы поняли результаты этих тестов, стоит отметить, что Baseline – это программа с ручным JavaScript кодом и жесткой кодировкой. В такой программе не были использованы никакие фреймворки, программа была написана только для этого теста deep–tree. В программе производится dirtyChecking. Эту программу мы приняли за единицу. Все остальное сравнивается в соотношении. Angular 1 получил отметку 5,7.

angular2 compiler benchmarks

Раньше мы показывали такую же скорость с оптимизированными структурами данных и без view cache. Мы были на уровне 2,7. Так что, это неплохой показатель. Мы увеличили скорость в два раза за счет быстрого доступа к свойствам. Сначала мы подумали, что наша работа на этом заканчивается.

Недостатки второй стадии

Мы создали приложения на этой базе. Но потом мы увидели недостатки:

  1. ViewCache плохо дружит с памятью. Представьте, вы переключаете маршруты обработки запросов. Ваши старые запросы остаются в памяти, потому что они кешированы, не так ли? Вопрос в том, когда удалять запросы из кэша? На самом деле, это очень сложный вопрос. Можно было бы создать несколько простых элементов, которые бы позволяли пользователю выбирать, кэшировать что-то или нет. Но это было бы, как минимум, странно.

  2. Еще одна проблема: элементы DOM имеют скрытое состояние. Например, элемент помещен в фокус. Даже если у вас нет привязки к фокусу, и элемент может находиться как в фокусе, так и вне его, то его удаление или возвращение может изменять фокус этого или других элементов. Про это мы не подумали. Появились связанные с этим баги. Можно было пойти таким путем: мы могли полностью удалять элементы, чтобы удалить их состояние, и даже восстанавливать их. Но это бы свело на нет показатели ViewCache, если бы нам пришлось воссоздавать DOM. Ведь у нас был показатель 2,7. Как же мы бы достигли скорости в такой ситуации?

Третья стадия


Класс view

Дальше к нам пришла мысль: давайте еще раз посмотрим на наш класс view. Что там у нас?
У нас есть компонент – эти уже оптимизированные ngelement, так? У нас есть привязки. Но класс view по-прежнему содержит эти массивы. Можем ли мы создать InlineView, который тоже использует только свойства? Никаких массивов. Это возможно? Оказалось, да.

Как это выглядит? Примерно так.

angular2 compiler view

Шаблон

Итак, у нас, как и ранее, будет шаблон, и для каждого элемента мы просто будем создавать код. Для этого шаблона мы будем создавать код, который отображает наш класс view. В конструкторе для каждого элемента мы вызовем document.createElement, который будет храниться в свойстве Node0 – для первого элемента, для второго мы опять вызовем document.createElement, который будет храниться в Node1. Дальше, когда нам понадобится присоединить элемент к своему родителю, у нас есть свойства, так ведь? Нам просто нужно сделать все в правильном порядке. Мы можем использовать свойство для обращения к предыдущему состоянию. Именно так мы поступим с DOM.

angular2 compiler template

Директивы

С директивами мы поступаем точно так же. У нас есть свойства для каждого экземпляра. И опять-таки, нам просто нужно убедиться в правильности порядка выполнения действий: что сначала идут зависимости, а затем те компоненты, которые используют эти зависимости. Что сначала мы используем ngForm, а затем – ngModel.

Привязки

Далее, привязки. Мы просто создаем код, который выполняет dirty-check. Мы берем наши выражения, конвертируем их обратно в JavaScript. В этом случае это будет this.component user.name. Это значит, что мы вытаскиваем user.name из компонента, сравниваем его с предыдущим значением, которое так же является свойством. Если значение изменилось – мы обновляем текстовый узел. В конце мы сводим все к представлением со структурой данных. В ней только свойства. Нет никаких массивов, Map, везде используется быстрый доступ через свойства.

Это значительно ускоряет процесс. Скоро я покажу вам цифры, чтобы вы могли убедиться в этом.

Вопрос вот в чем: как мы это делаем?

Скажем, кому-нибудь нужно создать строку, которая оценивает этот новый класс. Как это делается? Мы просто применяем то, что мы делали в реализации 101 в нашей текущей реализации.

Суть вот в чем: Если раньше мы создавали DOM узлы, сейчас мы создаем код для создания DOM узлов. Если раньше мы сравнивали элементы, сейчас мы создаем код для сравнения элементов. И наконец, Если раньше мы обращались к экземплярам директив или узлам DOM, сейчас мы храним свойства там, где хранятся экземпляры директив и узлы DOM. В таком случае код выглядит вот как.

angular2 compiler differences with first step

Раньше, у нас был наш ngelement, сейчас у нас есть compileElement. На самом деле эти классы сейчас существуют в компиляторе. Там есть compileElement, compileView и так далее.

Отображение будет таким: раньше у нас был элемент DOM, сейчас же у нас есть только свойство, в котором хранится элемент DOM. Раньше мы вызвали document.createElement, сейчас же мы создаем строку с этой новой строковой интерполяцией, которая отлично подходит для создания кода, в котором мы говорим, что this.document + название его свойства равнозначен document.createElement с названием АСД.

И наконец, если раньше мы вызывали appendChild, то сейчас мы создаем код для присоединения дочернего элемента к родительскому. То же самое происходит и с поиском директив-зависимостей. Все происходит по такому же алгоритму, только сейчас для этих целей мы создаем код.

angular2 compiler differences benchmarks

Если сейчас мы посмотрим на показатели, то увидим, что сейчас мы гораздо увеличили скорость. Если раньше наш показатель был 2,7, то сейчас он составляет 1,5. Это почти в два раза быстрее. ViewCache, по-прежнему, остается чуть быстрее. Но мы исключили вариант с его использованием, и вы уже знаете причины нашего решения. Мы отлично справились, и могли бы уже закончить. Но нет.

Динамическая (Just in Time) компиляция

Итак, вначале мы говорили про динамическую (Just in Time) компиляцию. Динамическая – это значит, что мы компилируем в браузере.

angular2 compiler jit

Напомним, это работает примерно так: у вас есть какие-то входящие данные, которые находятся на вашем сервере. Браузер их загружает и забирает, анализирует все, создает исходный класс view. Теперь нам нужно оценить этот исходный код для того, чтобы получить еще один класс. После этого мы можем создать этот класс, и далее мы получаем работающее приложение. С этой частью возникают определенные проблемы:

  1. Первая проблема в том, что нам нужно анализировать и создавать код внутри браузера. Это занимает какое-то время, в зависимости от того, сколько у нас компонентов. Мы должны пройти все символы. Конечно, это происходит достаточно быстро. И все же, на это тоже нужно время. Поэтому ваша страница будет загружаться не самым быстрым образом.

  2. Вторая проблема – это то, что анализатор должен находиться в браузере, поэтому нужно загрузить весь Angular компилятор в браузер. Поэтому, чем больше свойств мы добавляем и чем больше мы создаем кода, тем больше становиться размер.

  3. Следующая проблема – это оценка. В оценке кроется подвох. Главная проблема оценки – это то, что вы можете сделать ошибки, используя ее. Из-за одной такой ошибки кто-то может взломать ваш сайт. Поэтому вам не стоит использовать оценку, даже если вы думаете, что с вашим кодом все в порядке.

  4. Еще одной проблемой является то, что сейчас браузер добавляет политику защиты содержимого в качестве отличительной особенности (возможно, вы знаете об этом). С таким раскладом, сервер может дать указание браузеру, что не нужно вообще оценивать ту или иную страницу. Для браузера это может означать, что на этой странице не нужно запускать Angular вообще. Это не очень хорошо.

  5. Следующая проблема, с которой мы столкнулись, это минификация кода. Если вы хотите минифицировать код (а я надеюсь, что вы так и делаете, чтобы предоставлять клиенту как можно меньше кода), существуют кое-какие уловки, которые вы можете применить:

    1. Во-первых, вы можете переименовать переменные, обычно это безопасно, потому что вы можете определить, где используется та или другая переменная.
    2. Во-вторых, вы можете переименовать свойства объектов. Это сложнее, поскольку вы должны знать, где же именно используется тот или иной объект. Компилятор Clojure поддерживает такую функцию (она называется «улучшенная минификация»), мы его использовали в Google и использовали часто.

Итак, если мы используем улучшенную минификацию во время работы компилятора, происходит вот что.

Есть наши компоненты, наша разметка, загружаются в браузер, браузер анализирует шаблон и создает класс view. Пока все идет нормально. Браузер использует user.name, компонент также содержит user.name, просто этот user.name минифицирован с помощью технологии улучшенной минификации. Таким образом, компонент называется, скажем, С1, а мой пользователь внезапно оказывается просто U, а имя – N. Проблема в том, что минификатор не знает о моем шаблоне. Ведь в шаблоне по-прежнему остался user.name.

Итак, шаблон исполняется, по-прежнему создает user.name, которого просто не существует в компоненте. Есть определенные решения этой проблемы. Вы можете указать компоненту, что это свойство минифицировать не нужно. Но это не то, что нам нужно. Нам нужно, чтобы мы могли минифицировать это свойство, но с оперативной компиляцией и оценкой это работать не будет.

Статическая (Ahead of Time) компиляция

Именно по этой причине, следующим нашим шагом стало появление статической (Ahead of Time) компиляции. Она работает следующим образом.

angular2 compiler aot
Снова у нас есть входные данные, которые анализируются на сервере, и класс view также создается на сервере.

Тогда браузер просто подхватывает их, загружает как обычный текст сценария (как вы загружаете свой обычный код JavaScript), и затем просто создает нужные элементы.

Такой способ компиляции отлично подходит, потому что: Анализ происходит на сервере (а поэтому происходит быстро), компилятор не нужно переносить в браузер (и это тоже отлично). Также мы больше не используем оценку, ведь это скрипт. Поэтому такая компиляция подойдет для любого браузера.

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

Отлично, теперь мы можем использовать улучшенную минификацию. Поэтому, наши показатели скорости упали еще ниже.

Недостатки статической компиляции

Итак, теперь у нас есть статическая компиляция. Теперь все отлично, да? Но как всегда, существуют и недостатки. Первая проблема состоит в том, что с использованием статической компиляции нам нужно создавать другой код.

Для оценки в браузере нужно создавать код по стандарту ES5. Вы создаете код, который использует локальные переменные, или который получает аргументы, переданные в функцию. Вы не используете require.js или что-либо в этом роде.

Поскольку код генерируется на сервере, то нужно было генерировать код TypeScript по двум причинам:

  • Во-первых, мы хотели проверять типы ваших выражений (существуют ли они в компонентах).
  • Во-вторых, мы хотели эффективно использовать систему модулей TypeScript. Мы хотели создать импорт, чтобы уже вы могли выбирать, какие системы модулей вы хотите использовать. Создание импорта — это гораздо удобнее со стороны возможностей генерации кода, чем думать о require.js, system.js, Google Clojure, системе модулей и так далее.
  • В конце концов, мы также хотели применить код стандарта ES6 2016.

angular2 compiler aot output

Как нам удалось обеспечить поддержку ES6 2016?

На самом деле, если вы знакомы с компиляторами, то существует общий шаблон. Вместо создания строк создается структура данных, похожая на выводимые данные, но эту структуру данных, эту АСД, можно сериализовать в разные выходные данные.

АСД содержит такие возможности, как объявление переменной, вызов методов и так далее, плюс типы. Потом для ES5 мы просто сериализуем это все без типов, а для TypeScript сериализуем с типами.

Это выглядит примерно так: наш сгенерированный АСД вывод, внутри объявленные переменные (мы указываем declare var name EL). Это создаст код var el в TypeScript и создаст тип. В ES5 тип будет опущен.

Далее мы можем вызвать метод. Сначала мы прочитаем переменную document (поскольку это глобальная переменная). И потом для нее мы сможем вызвать метод createElement с этими аргументами.

Мы разместили literal со значением «div», потому что, если вы анализируете строки, то должны правильно их экранировать. Значение может содержать кавычки, поэтому при чтении кода нужно их экранировать, пропускать. Поэтому, именно таким образом мы можем это сделать. Хорошей новостью можно назвать то, что теперь наш сгенерированный код одинаково выглядит как на сервере, так и в браузере. Никаких различных частей кода.

Вторая проблема, с которой мы столкнулись при разработке статического компилятора, это выделение метаданных. Взгляните на этот код.

angular2 compiler aot decorator

В чем проблема этого кода? Скажем, у нас есть какая-то директива, которая имеет зависимость от cookies, и если у вас есть cookies, директива выполняет что-то другое. Это работает. Вы можете скомпилировать. Супер.

Но это не работает со статической компиляцией. Если подумать, почему так? Если это все спустить до уровня ES5, вы получите именно такой код.

Что, в конечном счете, делает декоратор? Он добавляет свойство вашему конструктору для метаданных. В конце он просто добавляет SomeDir с примечаниями.

Проблема в том, что если вы запустите это на сервере, оно не будет работать. Ведь на сервере нет document. Что же делать?

Можно предложить построить среду браузера на сервере, объявить переменную document, переменную window и так далее. В некоторых случаях это сработает, но в большинстве – нет. Второй способ (мы же теперь хорошо разбираемся в АСД, так?) – обработать АСД и вынуть из него метаданные без оценки кода. В АСД этого можно представить как-то так.

angular2 compiler aot decorator

Таким образом, наш класс SomeDir в АСД может иметь свойство decorators, которое обращается к тому элементу, который вы вызываете (это выражение, где определена директива плюс аргументы). Происходит следующее. Мы вытаскиваем метаданные в JSON файлы, дальше наш статический компилятор берет эти файлы и из них создает шаблон. Очевидно, здесь есть ограничения. Мы не оцениваем JavaScript код напрямую, поэтому вы не можете делать все то, что вы привыкли делать в браузере.

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

Хорошо, давайте снова остановимся на тестах производительности.

angular2 compiler aot benchmarks

Это – простая написанная нами программа. И время ее загрузки сократилось очень значительно. Все потому, что мы больше не проводим анализ, а также потому, что компилятор Angular 2 больше не загружается. Это почти в три раза быстрее. Размер также сократился с уже минифицированных в формате gzip 144 килобайт до 49. Для сравнения, библиотека React с улучшенной минификацией сейчас весит 46кб.

А теперь немного наглядных примеров

Допустим, у нас есть компонент Angular, у нас есть ngForm и ngModel. ngModel в качестве зависимости имеет ngForm.

angular2 compiler examples

Добавим сюда NGC – это модули _node, которые охватывают компилятор TypeScript, поскольку при вытаскивании и поддержке метаданных эти модули зависят от TypeScript. И если мы посмотрим на сгенерированный код, то увидим, что он выглядит очень знакомо. У нас есть user.name. Если его значение меняется, мы обновляем входные данные директивы. Мы просто сравниваем с предыдущим значением и устанавливаем его.

В этом есть хорошая сторона. Допустим, в своем шаблоне я меняю user.name на wrongName. Наш шаблон обращается к user.name, а не к user. wrongName. Теперь, когда мы посмотрим на сгенерированный код, TypeScript выдаст ошибку.

angular2 compiler example generated code

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

Мы хорошо справились, но мы стремимся стать еще лучше.

Наша цель – достичь размера 10 кб gzip. Размер некоторых наших прототипов составляет 25 кб и у меня есть несколько идей, как сделать компилятор еще меньше. Далее, мы хотим стать еще быстрее, чем наша отправная точка Baseline. Мы осознаем, что это еще не предел, и мы можем быть еще быстрее, чем Baseline.

Вы не заметите никаких изменений. Вы будете осуществлять изменения, генерировать разный код. Единственное – вы увидите разницу только в скорости.

В качестве заключения


Мы говорили про производительность, про разные аспекты производительности.
Мы обсуждали входные данные.
Мы узнали, что такое анализ, АСД (AST). Я рассказывал о том, как мы можем представить шаблон и как его реализовать.
Мы узнали, что document.createElement отлично подходит для фреймворка Angular.
Мы узнали, что быстрый доступ по свойствам и скрытые классы – это отличные инструменты для оптимизации вашего кода.
Мы узнали, что генерация кода (если сделать это правильно, то есть не только с помощью оценки, но и с поддержкой оффлайн, а также вывод АСД) – это отличная и мощная вещь. Это поможет вам в генерации скрытых классов.
Мы поговорили о статической (Ahead Of Time) и динамической (Just In Time) компиляции, а также о вещах, которые можно оптимизировать.
И наконец, мы посмотрели наглядный пример. На слайде есть ссылка на мою презентацию.

Огромное спасибо за внимание.

Ссылки на материалы
Видео доклада — Angular 2 — How it works
презентация — Angular2 Compiler — Tobias Bosch
твиттер Тобиаса Боша — Twitter Account — Tobias Bosch
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/329782/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 984 983 [982] 981 980 ..
.. 1 Календарь