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

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

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

 

 -Постоянные читатели

 -Статистика

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

Habrahabr








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

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

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

[Перевод] Охота на вредоносные npm-пакеты

Понедельник, 14 Августа 2017 г. 14:14 + в цитатник

Метки:  

DLP и Закон: как правильно оформить внедрение системы для защиты от утечек

Понедельник, 14 Августа 2017 г. 12:59 + в цитатник


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

В соответствии с ТК РФ, 98-ФЗ, 152-ФЗ и пр., функционирование DLP в организации включает несколько аспектов, требующих юридического оформления. Сразу оговоримся, что список документов, который мы даем ниже, несколько избыточен. Если каких-то регламентов у вас нет, это может быть не смертельно. Но у нас за годы работы в этой сфере сложилось мнение, что сопроводительных документов много не бывает, особенно если компании предстоит судиться с сотрудником, «слившим» конфиденциальные данные.

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

Информация ограниченного доступа


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

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

Разглашение информации ограниченного доступа


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

Общие:

  • Трудовой договор.
  • Правила внутреннего трудового распорядка.
  • Должностная инструкция работника.
  • Положение о подразделении работника.
  • Дополнительные соглашения с работником.

Режим защиты информации:

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

Этот список документов можно считать опорным и при формировании положений, перечисленных ниже в статье.

Далее, как мы понимаем, запрет ничего не стоит, если не прописана ответственность за его нарушение. Лица, разгласившие информацию ограниченного доступа, могут привлекаться к дисциплинарной, административной, гражданско-правовой, уголовной ответственности в порядке, установленном законодательством Российской Федерации. И, в частности, напомню, что разглашение охраняемой законом тайны (государственной, коммерческой, служебной и иной), ставшей известной работнику в связи с исполнением им трудовых обязанностей, в том числе разглашения персональных данных другого работника, является основанием для увольнения сотрудника по инициативе работодателя (ТК РФ, статья 81, пункт 6в).

Правила обработки/защиты информации и использование средств мониторинга


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

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

Также не лишними будут следующие документы:

  • Отчеты и планы по обучению/инструктажу работников.
  • Копия журналов по обучению и повышению осведомленности работников по вопросам обработки и защиты информации.

Личная информация на корпоративных ресурсах


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

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

Подразделение информационной безопасности


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

DLP-система


Система защиты информации должна соответствовать актуальным для компании угрозам, а также требованиям и рекомендациям регулирующих органов (Роскомнадзор, ФСБ России, ФСТЭК России). Что поможет офицеру безопасности подтвердить это:

  • Выписка из Модели угроз и Модели нарушителя.
  • Выписка из ТЗ и ТП на систему защиты.
  • Справка о DLP системе (функционал и сертификаты).
  • Отчеты об аудитах и проверках ИБ, копии аттестатов соответствия.

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

https://habrahabr.ru/post/335578/


Метки:  

DLP и Закон: как правильно оформить внедрение системы для защиты от утечек

Понедельник, 14 Августа 2017 г. 12:59 + в цитатник


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

В соответствии с ТК РФ, 98-ФЗ, 152-ФЗ и пр., функционирование DLP в организации включает несколько аспектов, требующих юридического оформления. Сразу оговоримся, что список документов, который мы даем ниже, несколько избыточен. Если каких-то регламентов у вас нет, это может быть не смертельно. Но у нас за годы работы в этой сфере сложилось мнение, что сопроводительных документов много не бывает, особенно если компании предстоит судиться с сотрудником, «слившим» конфиденциальные данные.

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

Информация ограниченного доступа


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

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

Разглашение информации ограниченного доступа


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

Общие:

  • Трудовой договор.
  • Правила внутреннего трудового распорядка.
  • Должностная инструкция работника.
  • Положение о подразделении работника.
  • Дополнительные соглашения с работником.

Режим защиты информации:

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

Этот список документов можно считать опорным и при формировании положений, перечисленных ниже в статье.

Далее, как мы понимаем, запрет ничего не стоит, если не прописана ответственность за его нарушение. Лица, разгласившие информацию ограниченного доступа, могут привлекаться к дисциплинарной, административной, гражданско-правовой, уголовной ответственности в порядке, установленном законодательством Российской Федерации. И, в частности, напомню, что разглашение охраняемой законом тайны (государственной, коммерческой, служебной и иной), ставшей известной работнику в связи с исполнением им трудовых обязанностей, в том числе разглашения персональных данных другого работника, является основанием для увольнения сотрудника по инициативе работодателя (ТК РФ, статья 81, пункт 6в).

Правила обработки/защиты информации и использование средств мониторинга


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

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

Также не лишними будут следующие документы:

  • Отчеты и планы по обучению/инструктажу работников.
  • Копия журналов по обучению и повышению осведомленности работников по вопросам обработки и защиты информации.

Личная информация на корпоративных ресурсах


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

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

Подразделение информационной безопасности


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

DLP-система


Система защиты информации должна соответствовать актуальным для компании угрозам, а также требованиям и рекомендациям регулирующих органов (Роскомнадзор, ФСБ России, ФСТЭК России). Что поможет офицеру безопасности подтвердить это:

  • Выписка из Модели угроз и Модели нарушителя.
  • Выписка из ТЗ и ТП на систему защиты.
  • Справка о DLP системе (функционал и сертификаты).
  • Отчеты об аудитах и проверках ИБ, копии аттестатов соответствия.

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

https://habrahabr.ru/post/335578/


Метки:  

[Из песочницы] Автоматизация рыбной ловли для World of Warcraft

Понедельник, 14 Августа 2017 г. 12:31 + в цитатник
Познакомился World of Warcraft очень давно и люблю его весь, но одна вещь больше всего не давала мне покоя — рыбная ловля. Это нудное повторяющееся действие, где ты просто нажимаешь на кнопку рыбной ловли и тыкаешь на поплавок раз в 5-15 секунд. Мой навык разработки рос, а ситуация с рыбной ловле так и не улучшалась с каждым годом что я играл, поэтому я решил убить двух зайцев сразу — начать осваивать python и всё же сделать бота для себя.

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

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

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

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

import pyscreenshot as ImageGrab

screen_size = None
screen_start_point = None
screen_end_point = None

# Сперва мы проверяем размер экрана и берём начальную и конечную точку для будущих скриншотов
def check_screen_size():
	print "Checking screen size"
	img = ImageGrab.grab()
	# img.save('temp.png')
	global screen_size
	global screen_start_point
	global screen_end_point

	# я так и не смог найти упоминания о коэффициенте в методе grab с параметром bbox, но на моем макбуке коэффициент составляет 2. то есть при создании скриншота с координатами x1=100, y1=100, x2=200, y2=200), размер картинки будет 200х200 (sic!), поэтому делим на 2
	coefficient = 2
	screen_size = (img.size[0] / coefficient, img.size[1] / coefficient) 

	# берем примерно девятую часть экрана примерно посередине.
	screen_start_point = (screen_size[0] * 0.35, screen_size[1] * 0.35)
	screen_end_point = (screen_size[0] * 0.65, screen_size[1] * 0.65)
	print ("Screen size is " + str(screen_size))

def make_screenshot():
	print 'Capturing screen'
	screenshot = ImageGrab.grab(bbox=(screen_start_point[0], screen_start_point[1], screen_end_point[0], screen_end_point[1]))
	# сохраняем скриншот, чтобы потом скормить его в OpenCV
	screenshot_name = 'var/fishing_session_' + str(int(time.time())) + '.png'
	screenshot.save(screenshot_name)
	return screenshot_name

def main():
	check_screensize()
	make_screenshot()


Получаем примерно следующую картинку:



Далее — найти поплавок. Для этого у нас должен быть сам шаблон поплавка, который мы ищем. После сотни попыток я всё таки подобрал те, которые OpenCV определяет лучше всего. Вот они:



Берём код из ссылки выше, добавляем цикл и наши шаблоны:

import cv2
import numpy as np
from matplotlib import pyplot as plt

def find_float(screenshot_name):
	print 'Looking for a float'
	for x in range(0, 7):
		# загружаем шаблон
		template = cv2.imread('var/fishing_float_' + str(x) + '.png', 0)
		# загружаем скриншот и изменяем его на чернобелый
		src_rgb = cv2.imread(screenshot_name)
		src_gray = cv2.cvtColor(src_rgb, cv2.COLOR_BGR2GRAY)
		# берем ширину и высоту шаблона
		w, h = template.shape[::-1]
		# магия OpenCV, которая и находит наш темплейт на картинке
		res = cv2.matchTemplate(src_gray, template, cv2.TM_CCOEFF_NORMED)
		# понижаем порог соответствия нашего шаблона с 0.8 до 0.6, ибо поплавок шатается и освещение в локациях иногда изменяет его цвета, но не советую ставить ниже, а то и рыба будет похожа на поплавок
		threshold = 0.6
		# numpy фильтрует наши результаты по порогу
		loc = np.where( res >= threshold)
		# выводим результаты на картинку
		for pt in zip(*loc[::-1]):
		    cv2.rectangle(src_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
		# и если результаты всё же есть, то возвращаем координаты и сохраняем картинку
		if loc[0].any():
			print 'Found float at ' + str(x) 
			cv2.imwrite('var/fishing_session_' + str(int(time.time())) + '_success.png', src_rgb)
			return (loc[1][0] + w / 2) / 2, (loc[0][0] + h / 2) / 2 # опять мы ведь помним, что макбук играется с разрешениями? поэтому снова приходится делить на 2

def main():
	check_screensize()
	img_name = make_screenshot()
	find_float(img_name)
	

Итак, у нас есть координаты поплавка, двигать курсор мыши умеет autopy буквально с помощью одной строки, подставляем свои координаты:

import autopy

def move_mouse(place):
	x,y = place[0], place[1]
	print("Moving cursor to " + str(place))
	autopy.mouse.smooth_move(int(screen_start_point[0]) + x , int(screen_start_point[1]) + y)

def main():
	check_screensize()
	img_name = make_screenshot()
	cords = find_float(img_name)
	move_mouse(cords)


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

import pyaudio
import wave
import audioop
from collections import deque
import time
import math

def listen():
	print 'Listening for loud sounds...'
	CHUNK = 1024
	FORMAT = pyaudio.paInt16
	CHANNELS = 2
	RATE = 18000 # битрейт звука, который мы хотим слушать
	THRESHOLD = 1200  # порог интенсивности звука, если интенсивность ниже, значит звук по нашим меркам слишком тихий
	SILENCE_LIMIT = 1  # длительность тишины, если мы не слышим ничего это время, то начинаем слушать заново

	# открываем стрим
	p = pyaudio.PyAudio()

	stream = p.open(format=FORMAT,
	                channels=CHANNELS,
	                rate=RATE,
	                # output=True, # на мак ос нет возможности слушать output, поэтому мне пришлось прибегнуть к использованию Soundflower, который умеет перенаправлять канал output в input, таким образом мы перехватываем звук игры будто это микрофон 
	                input=True,
	                frames_per_buffer=CHUNK) 
	cur_data = ''
	rel = RATE/CHUNK
	slid_win = deque(maxlen=SILENCE_LIMIT * rel)
	
	# начинаем слушать и по истечении 20 секунд (столько максимум длится каждый заброс поплавка), отменяем нашу слушалку.
	success = False
	listening_start_time = time.time()
	while True:
		try:
			cur_data = stream.read(CHUNK)
			slid_win.append(math.sqrt(abs(audioop.avg(cur_data, 4))))
			if(sum([x > THRESHOLD for x in slid_win]) > 0):    
				print 'I heart something!'
				success = True
				break
			if time.time() - listening_start_time > 20:
				print 'I don't hear anything during 20 seconds!'
				break
		except IOError:
			break
	# обязательно закрываем стрим
	stream.close()
	p.terminate()
	return success

def main():
	check_screensize()
	img_name = make_screenshot()
	cords = find_float(img_name)
	move_mouse(cords)
	listen()

Последнее, что осталось — споймать саму рыбку, когда мы услышим звук, снова используем autopy:

def snatch():
	print('Snatching!')
	autopy.mouse.click(autopy.mouse.RIGHT_BUTTON)

def main():
	check_screensize()
	img_name = make_screenshot()
	cords = find_float(img_name)
	move_mouse(cords)
	if listen():
		snatch()

По моим тестам, что я оставлял бота рыбачить по ночам, за неделю такого абуза он сделал около 7000 бросков и словил около 5000 рыб. Погрешность 30% вызвана тем, что иногда не получается отловить звук или найти поплавок из-за освещения или поворотов поплавка. Но результатом я доволен — впервые попробовал python, сделал бота и сэкономил себе кучу времени.

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

Буду рад любым комментариям.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335580/


Метки:  

[Из песочницы] Автоматизация рыбной ловли для World of Warcraft

Понедельник, 14 Августа 2017 г. 12:31 + в цитатник
Познакомился World of Warcraft очень давно и люблю его весь, но одна вещь больше всего не давала мне покоя — рыбная ловля. Это нудное повторяющееся действие, где ты просто нажимаешь на кнопку рыбной ловли и тыкаешь на поплавок раз в 5-15 секунд. Мой навык разработки рос, а ситуация с рыбной ловле так и не улучшалась с каждым годом что я играл, поэтому я решил убить двух зайцев сразу — начать осваивать python и всё же сделать бота для себя.

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

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

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

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

import pyscreenshot as ImageGrab

screen_size = None
screen_start_point = None
screen_end_point = None

# Сперва мы проверяем размер экрана и берём начальную и конечную точку для будущих скриншотов
def check_screen_size():
	print "Checking screen size"
	img = ImageGrab.grab()
	# img.save('temp.png')
	global screen_size
	global screen_start_point
	global screen_end_point

	# я так и не смог найти упоминания о коэффициенте в методе grab с параметром bbox, но на моем макбуке коэффициент составляет 2. то есть при создании скриншота с координатами x1=100, y1=100, x2=200, y2=200), размер картинки будет 200х200 (sic!), поэтому делим на 2
	coefficient = 2
	screen_size = (img.size[0] / coefficient, img.size[1] / coefficient) 

	# берем примерно девятую часть экрана примерно посередине.
	screen_start_point = (screen_size[0] * 0.35, screen_size[1] * 0.35)
	screen_end_point = (screen_size[0] * 0.65, screen_size[1] * 0.65)
	print ("Screen size is " + str(screen_size))

def make_screenshot():
	print 'Capturing screen'
	screenshot = ImageGrab.grab(bbox=(screen_start_point[0], screen_start_point[1], screen_end_point[0], screen_end_point[1]))
	# сохраняем скриншот, чтобы потом скормить его в OpenCV
	screenshot_name = 'var/fishing_session_' + str(int(time.time())) + '.png'
	screenshot.save(screenshot_name)
	return screenshot_name

def main():
	check_screensize()
	make_screenshot()


Получаем примерно следующую картинку:



Далее — найти поплавок. Для этого у нас должен быть сам шаблон поплавка, который мы ищем. После сотни попыток я всё таки подобрал те, которые OpenCV определяет лучше всего. Вот они:



Берём код из ссылки выше, добавляем цикл и наши шаблоны:

import cv2
import numpy as np
from matplotlib import pyplot as plt

def find_float(screenshot_name):
	print 'Looking for a float'
	for x in range(0, 7):
		# загружаем шаблон
		template = cv2.imread('var/fishing_float_' + str(x) + '.png', 0)
		# загружаем скриншот и изменяем его на чернобелый
		src_rgb = cv2.imread(screenshot_name)
		src_gray = cv2.cvtColor(src_rgb, cv2.COLOR_BGR2GRAY)
		# берем ширину и высоту шаблона
		w, h = template.shape[::-1]
		# магия OpenCV, которая и находит наш темплейт на картинке
		res = cv2.matchTemplate(src_gray, template, cv2.TM_CCOEFF_NORMED)
		# понижаем порог соответствия нашего шаблона с 0.8 до 0.6, ибо поплавок шатается и освещение в локациях иногда изменяет его цвета, но не советую ставить ниже, а то и рыба будет похожа на поплавок
		threshold = 0.6
		# numpy фильтрует наши результаты по порогу
		loc = np.where( res >= threshold)
		# выводим результаты на картинку
		for pt in zip(*loc[::-1]):
		    cv2.rectangle(src_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
		# и если результаты всё же есть, то возвращаем координаты и сохраняем картинку
		if loc[0].any():
			print 'Found float at ' + str(x) 
			cv2.imwrite('var/fishing_session_' + str(int(time.time())) + '_success.png', src_rgb)
			return (loc[1][0] + w / 2) / 2, (loc[0][0] + h / 2) / 2 # опять мы ведь помним, что макбук играется с разрешениями? поэтому снова приходится делить на 2

def main():
	check_screensize()
	img_name = make_screenshot()
	find_float(img_name)
	

Итак, у нас есть координаты поплавка, двигать курсор мыши умеет autopy буквально с помощью одной строки, подставляем свои координаты:

import autopy

def move_mouse(place):
	x,y = place[0], place[1]
	print("Moving cursor to " + str(place))
	autopy.mouse.smooth_move(int(screen_start_point[0]) + x , int(screen_start_point[1]) + y)

def main():
	check_screensize()
	img_name = make_screenshot()
	cords = find_float(img_name)
	move_mouse(cords)


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

import pyaudio
import wave
import audioop
from collections import deque
import time
import math

def listen():
	print 'Listening for loud sounds...'
	CHUNK = 1024
	FORMAT = pyaudio.paInt16
	CHANNELS = 2
	RATE = 18000 # битрейт звука, который мы хотим слушать
	THRESHOLD = 1200  # порог интенсивности звука, если интенсивность ниже, значит звук по нашим меркам слишком тихий
	SILENCE_LIMIT = 1  # длительность тишины, если мы не слышим ничего это время, то начинаем слушать заново

	# открываем стрим
	p = pyaudio.PyAudio()

	stream = p.open(format=FORMAT,
	                channels=CHANNELS,
	                rate=RATE,
	                # output=True, # на мак ос нет возможности слушать output, поэтому мне пришлось прибегнуть к использованию Soundflower, который умеет перенаправлять канал output в input, таким образом мы перехватываем звук игры будто это микрофон 
	                input=True,
	                frames_per_buffer=CHUNK) 
	cur_data = ''
	rel = RATE/CHUNK
	slid_win = deque(maxlen=SILENCE_LIMIT * rel)
	
	# начинаем слушать и по истечении 20 секунд (столько максимум длится каждый заброс поплавка), отменяем нашу слушалку.
	success = False
	listening_start_time = time.time()
	while True:
		try:
			cur_data = stream.read(CHUNK)
			slid_win.append(math.sqrt(abs(audioop.avg(cur_data, 4))))
			if(sum([x > THRESHOLD for x in slid_win]) > 0):    
				print 'I heart something!'
				success = True
				break
			if time.time() - listening_start_time > 20:
				print 'I don't hear anything during 20 seconds!'
				break
		except IOError:
			break
	# обязательно закрываем стрим
	stream.close()
	p.terminate()
	return success

def main():
	check_screensize()
	img_name = make_screenshot()
	cords = find_float(img_name)
	move_mouse(cords)
	listen()

Последнее, что осталось — споймать саму рыбку, когда мы услышим звук, снова используем autopy:

def snatch():
	print('Snatching!')
	autopy.mouse.click(autopy.mouse.RIGHT_BUTTON)

def main():
	check_screensize()
	img_name = make_screenshot()
	cords = find_float(img_name)
	move_mouse(cords)
	if listen():
		snatch()

По моим тестам, что я оставлял бота рыбачить по ночам, за неделю такого абуза он сделал около 7000 бросков и словил около 5000 рыб. Погрешность 30% вызвана тем, что иногда не получается отловить звук или найти поплавок из-за освещения или поворотов поплавка. Но результатом я доволен — впервые попробовал python, сделал бота и сэкономил себе кучу времени.

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

Буду рад любым комментариям.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335580/


Метки:  

Цифровая экономика и экосистема R

Понедельник, 14 Августа 2017 г. 11:55 + в цитатник

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



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


Почему необходимы новые подходы и инструменты?


  • Многократное увеличение объемов данных
  • Многократное увеличение источников данных
  • Многократное увеличение форматов обмена
  • Работа с неструктурированными данными
  • Смещение фокуса от исторического анализа к научному прогнозированию
  • Акцент на визуализацию и удобства восприятия
  • Многократное снижение времени на принятие решения вплоть до работы в режиме «реального времени»

High Level Design (HLD) аналитической системы на базе R


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



Ключевые компоненты решения


  • RStudio — аналитическая экосистема (импорт, обработка, визуализация) на основе платформы R
  • Yandex ClickHouse — сверхбыстрая колоночно-ориентированная БД, оптимизированная для работы с временнЫми данными
  • Appache Drill — платформа для обеспечения унифицированного SQL доступа к BigData & NoSQL данным
  • Appache Airflow — оркестратор
  • «ETL» — платформа для приема разнообразной структурированной информации в относительно «чистой» форме с применением языка Go

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


Ожидаемые бизнесом выходы от аналитической системы


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


  • генерация штатных отчетов в виде HTML (с элементами интерактива в виде встроенных htmlWidgets);
  • генерация штатных отчетов в виде PDF;
  • генерация различных выгрузок в различных форматах для M2M взаимодействия;
  • интерактивные аналитические приложения (дашборды);
  • элементы операционной аналитики (автоматическое внесение изменений в другие ИТ системы на основе полученных вычислений).

Средой существования всех упомянутых типов отчетов и АРМ является Shiny Server\Connect Server. В платной или бесплатной редакции — зависит от требований, которые выходят за рамки аналитики и определяются требованиями по нагрузке, безопасности, централизованному управлению.


5 бизнес-аргументов в пользу приведенного HLD


  1. Быстрые сроки ввода в эксплуатацию и минимальная стоимость владения за счет применения передовых апробированных open-source инструментов.
  2. Широчайший спектр функциональных возможностей по импорту, обработке и визуализации.
  3. Унифицированные высокопроизводительные технологии для данных различного масштаба данных (миллионы – сотни триллионов строк\ гигабайты – петабайты данных).
  4. Использование открытых общедоступных пакетов (>10 тыс штук), в том числе в части:
    • алгоритмической обработки, включая методы машинного обучения;
    • визуализации и создания интерактивных аналитических дашбордов на базе технологий HTML5+CSS+JS.
  5. Наличие «enterprise compliant» коммерческих версий доступных по модели подписки для ключевых open-source компонент.

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


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


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


В цифровом мире язык програмимирования становится таким же важным знанием, как язык международного общения. Интересно, что в отдельных западных компаниях, воспринимавшихся ранее как классическое производство, программирование становится важным навыком даже для менеджеров. Прекрасный пример подобной трансформации — компания GE, подразделеие GE Digital. Ролик — Discover GE Digital: The Digital Industrial Company

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

https://habrahabr.ru/post/335576/


Метки:  

Новые инструменты Safari для отладки WebRTC

Понедельник, 14 Августа 2017 г. 11:20 + в цитатник
image

Совсем недавно Apple анонсировала поддержку WebRTC в Safari. Слухи ходили несколько лет, и теперь мы знаем: осенью WebRTC будет доступна для всех основных браузерах: Chrome, Firefox, Safari и Edge. С подводными камнями и несовместимостями. Технология очень крутая и позволяет передавать peer-to-peer между браузерами голос, видео, экран или произвольные данные. Ее использует «Skype for Web», «Hangouts» и другие известные коммуникаторы. А в новой версии Safari кроме самой WebRTC добавилось много плюшек для пользующихся ей разработчиков, о которых я расскажу под катом.

Поддержка обеих версий API


За последние несколько лет API WebRTC полностью поменялся: старый вариант на коллбеках и с медиа потоками был объявлен устаревшим, а вместо него создателям браузеров предлагают сделать новый, на промисах и с медиа треками. Firefox полностью поддерживает как старый так и новый API, у Chrome пока не реализована часть методов по работе с меди треками. А разработчики Safari выбрали интересное решение: браузер поддерживает оба API, но в версии для конечных пользователей будет доступно только новое. А старое можно для отладки включить через специальное меню:



Только HTTPS


Начинающие разработчики WebRTC традиционно сталкиваются с «написал несколько строчек JavaScript как в примере — а оно не работает». Производители браузеров стараются защитить своих пользователей от потенциально опасного захвата голоса и видео с устройств. И вводят дополнительные ограничения на использование API. Например, WebRTC не будет работать в Chrome, если страница была загружена из файла. А разработчики Safari пошли дальше и запретили WebRTC для сайтов без поддержки HTTPS! Для локальной отладки это ограничение можно снять через то же меню.

Скандал с локальными IP адресами


Не так давно по интернету прошлась волна обсуждений найденной «уязвимости»: WebRTC позволяла получить локальный IP адрес компьютера до того, как пользователь дал доступ к камере, микрофону и вообще согласился устанавливать какие-то подключения. А локальный IP адрес — это еще одна возможность точнее таргетировать пользователей и показывать им больше рекламы.

В Safari это учли, и по умолчанию WebRTC не будет использовать локальный IP адрес для установки peer-to-peer подключения. Только «внешний», полученный после общение со STUN сервером. Ограничение снимается, если пользователь дал доступ к камере или микрофону. Что, в целом, логично и стимулирует разработчиков писать код про коммуникации, а не пытаться использовать WebRTC для получения лишних данных таргетирования. Это ограничение тоже можно отключить через меню разработчика.

Генератор видео и голоса для отладки


Отлаживаться собственным лицом с камеры ноута — то еще удовольствие. Поэтому разработчики Safari добавили в то же меню пункт включения «фейкового видео» или звука: вместо видео будет передаваться телевизионная заставка, вместо голоса — одна нота. Очень удобно для авто тестов и проверки связи. Кстати, в Firefox такой режим уже давно был и включался специальным флагом «fake» при инициализации WebRTC.

Картинка для привлечения внимания взята здесь, иллюстрация меню Safari взята здесь
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335570/


Метки:  

[Из песочницы] Chromebook для удаленной работы. Настраиваем VPN и RDP

Понедельник, 14 Августа 2017 г. 10:56 + в цитатник
image

Привет! Удаленную работу часто можно описать как два технических требования от исполнителя: первое, доступ в интернет, и второе, ноутбук. А если у вас есть удаленный сервер, на котором вы работаете, то все, что вам нужно: тонкий клиент для доступа к нему. В этой статье я расскажу, как я выбирал и настраивал тонкий клиент для удаленной работы, и почему хромбук отлично справляется с этой задачей.

Требования


Итак, вот основные требования, которые я определил для себя:

  • Хороший экран — в него мы будем смотреть часами
  • Автономность — жизнь на батареи более 5-6 часов
  • Вес — мобильность важный показатель для поездок и путешествий
  • Цена — разбить или потерять ноутбук за $300 будет не так накладно/обидно как за $1500

Выбор устройства


С выбором я не заморачивался, открыл Амазон и нашел все модели хромбуков в категории до 300 долларов. Мой выбор пал на модель Acer Chromebook 14 (CB3-431). Для теста выбрал восстановленный (Refurbished) ноутбук за 185 долларов. Справедливости ради нужно отметить, что восстановленный хромбук ничем не отличался от нового, кроме как отсутствием оригинальной упаковки и 3-мя месяцами гарантии.

Настройка VPN и RDP в хром ос


Итак, красивый и тонкий ноутбук в руках, настраиваем VPN и RDP для удаленной работы.

VPN проблема


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

VPN решение


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

Теперь, чтобы поднять наш VPN, нам нужно выполнить следующее.
Заходим в терминал: Ctrl+Alt+T, вводим команду shell. Далее нам нужны команды:

openvpn --mktun --dev tap0
openvpn --config /usr/local/vpn/openvpn.ovpn --dev tap0
openvpn --rmtun --dev tap0

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

RDP проблема


Для удаленного доступа можно использовать множество решений, таких как Google Remote Desktop или TeamViewer. Но для меня они не подошли, в силу разных причин, и я решил сосредоточиться на настройке RDP.

На хром ос можно запустить ChromeRDP, вроде работает, но плохо живет на медленном канале связи и настроек маловато.

RDP решение


Для решения этой задачи нам потребуется хороший RDP-клиент и линукс. Самый простой способ получить полноценный линукс на хромбуке это Crouton. Он устанавливается просто и работает параллельно с хром ос. Подробная статья о настройке Crouton хабрится здесь.

Имея доступ к apt-get в линукс, мы можем установить Remmina. Remmina — это удобный и быстрый RDP клиент.

Итак, программа минимум выполнена и мы можем работать.

Итоги


Успел поработать в таком режиме больше месяца. В целом работать достаточно удобно, хоть и понадобилось время чтобы привыкнуть к клавиатуре.

Плюсы:

  • Цена вопроса, в моем случае это ~$200 (с учетом доставки из США)
  • Достаточно хорошие характеристики для целевой задачи: 4gb RAM, 32gb SSD, IPS 14" FULL HD, 1.5kg
  • Длительное время автономной работы, в моем случае 9-10 часов от батареи
  • Возможность установки андроид приложений + полноценный линукс
  • Отсутствие каких либо тормозов в хром ос и при использовании RDP

Минусы:

  • Нужно инвестировать время в настройку системы
  • Если нужно подключение к удаленному серверу, то без интернета — работа стоит

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

https://habrahabr.ru/post/335566/


Метки:  

[Перевод] Погружение в F#. Пособие для C#-разработчиков

Понедельник, 14 Августа 2017 г. 10:54 + в цитатник

Этот пост будет не о том, как «перевести» код с C# на F#: различные парадигмы делают каждый из этих языков лучшим для своего круга задач. Однако вы сможете оценить все достоинства функционального программирования быстрее, если не будете думать о переводе кода из одной парадигмы в другую. Настало время любопытных, пытливых и готовых изучать совершенно новые вещи. Давайте начнем!



Ранее, в посте «Почему вам следует использовать F#», мы рассказали, почему F# стоит попробовать прямо сейчас. Теперь мы разберем основы, необходимые для его успешного применения. Пост предназначен для людей, знакомых с C#, Java или другими объектно-ориентированными языками. Если вы уже пишете на F#, эти понятия должны быть вам хорошо знакомы.


Сразу к различиям


Перед тем, как приступить к изучению понятий функционального программирования, давайте посмотрим на небольшой пример и определим, в чем F# отличается от C#. Это базовый пример с двумя функциями и выводом результата на экран:


let square x = x * x

let sumOfSquares n =
    [1..n] // Создадим список с элементами от 1 до n
    |> List.map square // Возведем в квадрат каждый элемент
    |> List.sum // Просуммируем их!

printfn "Сумма квадратов первых 5 натуральных чисел равна %d" (sumOfSquares 5)

Обратите внимание, что здесь нет явного указания типов, отсутствуют точки с запятой или фигурные скобки. Скобки используются в единственном месте: для вызова функции sumOfSquares с числом 5 в качестве входного значения и последующего вывода результата на экран. Конвейерный оператор |> (pipeline operator) используется так же, как конвейеры (каналы, pipes) в Unix. square — это функция, которая напрямую передается в функцию List.map как параметр (функции в F# рассматриваются как значения, first-class functions).


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


C# и F#: Соответствие ключевых понятий


Следующая таблица показывает соответствия между некоторыми ключевыми понятиями C# и F#. Это умышленно короткое и неполное описание, но так его проще запомнить в начале изучения F#.


C# и Объектно-Ориентированное Программирование F# и Функциональное Программирование
Переменные Неизменяемые значения
Инструкции Выражения
Объекты с методами Типы и функции

Быстрая шпаргалка по некоторым терминам:


  • Переменные — это значения, которые могут меняться. Это следует из их названия!


  • Неизменяемые значения — это значения, которые не могут быть изменены после присваивания.


  • Инструкции — это команды, исполняемые после запуска программы.


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


  • Типы — это классификация данных в программе.

Стоит отметить, что все указанное в столбце C# так же возможно в F# (и довольно легко реализуется). В столбце F# также есть вещи, которые можно сделать в C#, хотя и намного сложнее. Следует упомянуть, что элементы в левом столбце не являются "плохими" в F#, и наоборот. Объекты с методами отлично подходят для использования в F# и часто являются лучшим решением в зависимости от вашей ситуации.


Неизменяемые значения вместо переменных


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


let x = 1

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


let x = 1
x = x + 1 // Это выражение ничего не присваивает!

Вместо этого, вторая строка является сравнением, определяющим, является ли x равным x + 1. Хотя существует способ изменить (мутировать, mutate) x с помощью использования оператора <- и модификатора mutable (см. подробности в Mutable Variables), вы быстро поймете, что проще думать о решении задач без переприсвоения значений. Если не рассматривать F# как еще один императивный язык программирования, вы сможете использовать его самые сильные стороны.


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


Рассмотрим более конкретный пример: вы хотите возвести в квадрат числа из входного списка. Вот как это можно сделать в F#:


// Определим функцию, которая вычисляет квадрат значения
let square x = x * x

let getSquares items =
    items |> List.map square

let lst = [ 1; 2; 3; 4; 5 ] // Создать список в F#

printfn "Квадрат числа %A равен %A" lst (getSquares lst)

Заметим, что в этом примере нет цикла for. На концептуальном уровне это сильно отличается от императивного кода. Мы не возводим в квадрат каждый элемент списка. Мы применяем функцию square к входному списку и получаем значения, возведенные в квадрат. Это очень тонкое различие, но на практике оно может приводить к значительно отличающемуся коду. Прежде всего, функция getSquares на самом деле создает полностью новый список.


Неизменяемость — это гораздо более широкая концепция, чем просто иной способ управления данными в списках. Понятие ссылочной прозрачности (Referential Transparency) естественно для F#, и оказывает значительное влияние, как на разработку систем, так и на то, как части этих систем сочетаются. Функциональные характеристики системы становятся более предсказуемыми, когда значения не изменяются, если вы этого не ожидаете.


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


Выражения вместо инструкций


Как было упомянуто ранее, F# использует выражения (expressions). Это контрастирует с C#, где практически для всего используются инструкции (statements). Различие между ними может казаться на первый взгляд незначительным, однако есть одна вещь, о которой следует помнить: выражения производят значения. Инструкции — нет.


// 'getMessage' -- это функция, и `name` - ее входной параметр.
let getMessage name =
    if name = "Phillip" then   // 'if' - это выражение.
        "Hello, Phillip!"      // Эта строка тоже является выражением. Оно возвращает значение
    else
        "Hello, other person!" // То же самое с этой строкой.

let phillipMessage = getMessage "Phillip" // getMessage, при вызове, является выражением. Его значение связано с именем 'phillipMessage'.
let alfMessage = getMessage "Alf" // Это выражение связано с именем 'alfMessage'!

В предыдущем примере вы можете увидеть несколько моментов, которые отличают F# от императивных языков вроде C#:


  • if...then...else — это выражение, а не инструкция.
  • Каждая ветка выражения if возвращает значение, которое в данном случае будет являться возвращаемым значением функции getMessage.
  • Каждый вызов функции getMessage — это выражение, которое принимает строку и возвращает строку.

Этот подход сильно отличается от C#, но скорее всего он покажется вам естественным при написании кода на F#.


Если копнуть немного глубже, в F# даже инструкции описываются с помощью выражений. Такие выражения возвращают значение типа unit. unit немного похож на void в C#:


let names = [ "Alf"; "Vasily"; "Shreyans"; "Jin Sun"; "Moulaye" ]

// Цикл `for`.  Ключевое слово 'do' указывает, что выражение их внутренней области видимости должно иметь тип `unit`.
// Если это не так, то результат выражения неявно игнорируется.
for name in names do
    printfn "My name is %s" name // printfn возвращает unit.

В предыдущем примере с циклом for всё имеет тип unit. Выражения типа unit — это выражения, которые не имеют возвращаемого значения.


F#: Массивы, списки и последовательности


Предыдущие примеры кода использовали массивы и списки F#. В данном разделе разъясняются некоторые подробности.


F# предоставляет несколько типов коллекций и самые распространенные из них — это массивы, списки и последовательности.



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


// Создадим список квадратов первых 100 натуральных чисел
let first100Squares = [ for x in 1..100 -> x * x ]

// То же самое, но массив!
let first100SquaresArray = [| for x in 1..100 -> x * x |]

// Функция, которая генерирует бесконечную последовательность нечетных чисел
//
// Вызывать вместе с Seq.take!
let odds = 
    let rec loop x = // Использует рекурсивную локальную функцию
        seq { yield x
              yield! loop (x + 2) }
    loop 1

printfn "Первые 3 нечетных числа: %A" (Seq.take 3 odds)
// Вывод:  "Первые 3 нечетных числа: seq [1; 3; 5]

Соответствие между функциями F# и методами LINQ


Если вы знакомы с методами LINQ, следующая таблица поможет вам понять аналогичные функции в F#.


LINQ F# функция
Where filter
Select map
GroupBy groupBy
SelectMany collect
Aggregate fold или reduce
Sum sum

Вы также можете заметить, что такой же набор функций существует для модулей Seq, List и Array. Функции модуля Seq могут быть использованы для последовательностей, списков или массивов. Функции для массивов и списков могут быть использованы только для массивов и списков в F# соответственно. Также последовательности в F# ленивые, а списки и массивы — энергичные. Использование функций модуля Seq на списках или массивах влечет за собой ленивое вычисление, а тип возвращаемого значения будет последовательностью.


Предыдущий раздел содержит в себе довольно много информации, но по мере написания программ на F# она станет интуитивно понятной.


Функциональные конвейеры


Вы могли заметить, что оператор |> используется в предыдущих примерах кода. Он очень похож на конвейеры в unix: принимает что-то слева от себя и передает на вход чему-то справа. Этот оператор (называется «pipe» или «pipeline») используется для создания функциональных конвейеров. Вот пример:


let square x = x * x
let isOdd x = x % 2 <> 0

let getOddSquares items =
    items
    |> Seq.filter isOdd
    |> Seq.map square

В данном примере сначала items передается на вход функции Seq.filter. Затем возвращаемое значение Seq.filter (последовательность) передается на вход функции Seq.map. Результат выполнения Seq.map является выходным значением функции getOddSquares.


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


F#: типы


Поскольку F# — язык платформы .NET, в нем существуют те же примитивные типы, что и C#: string, int и так далее. Он использует объекты .NET и поддерживает четыре основных столпа объектно-ориентированного программирования. F# предоставляет кортежи (tuples), а также два основных типа, которые отсутствуют в C#: записи (records) и размеченные объединения (discriminated unions).


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


open System

// Вот так вы можете определить тип-запись.
// Можно располагать метки на новых строках
type Person =
    { Name: string
      Age: int
      Birth: DateTime }

// Создать новую запись `Person` можно примерно так.
// Если метки расположены на одной строке, они разделяются точкой с запятой
let p1 = { Name="Charles"; Age=27; Birth=DateTime(1990, 1, 1) }

// Или же можно располагать метки на новых строках
let p2 =
    { Name="Moulaye"
      Age=22
      Birth=DateTime(1995, 1, 1) }

// Записи можно сравнивать на равенство. Не нужно определять метод Equals() и GetHasCode().
printfn "Они равны? %b" (p1 = p2) // Это выведет `false`, потому что они не равны.

Другой основной тип в F# — это размеченные объединения, или РО, или DU в англоязычной литературе. РО — это типы, представляющие некоторое количество именованных вариантов. На языке теории категорий это называется типом-суммой. Они также могут быть определены рекурсивно, что значительно упрощает описание иерархических данных.


// Определим обобщенное бинарное дерево поиска.
//
// Заметим, что обобщенный тип-параметр имеет ' в начале.
type BST<'T> =
    | Empty
    | Node of 'T * BST<'T> * BST<'T> // Каждый узел имеет левый и правый BST<'T>

// Развернем BST с помощью сопоставления с образцом!
let rec flip bst =
    match bst with
    | Empty -> bst
    | Node(item, left, right) -> Node(item, flip right, flip left)

// Определим пример BST
let tree = 
    Node(10, 
        Node(3, 
            Empty, 
            Node(6, 
                Empty, 
                Empty)),
        Node(55,
            Node(16, 
                Empty,
                Empty),
            Empty))

// Развернем его!
printfn "%A" (flip tree)

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


Наверняка вы увидели странный синтаксис в определении варианта Node. Это на самом деле сигнатура кортежа. Это означает, что определенное нами BST может быть или пустым, или являться кортежем (значение, левое поддерево, правое поддерево). Более подробно про это написано в разделе о сигнатурах.


Собираем всё вместе: синтаксис F# за 60 секунд


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


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

// ======== "Переменные" (на самом деле нет) ==========
// Ключевое слово "let" определяет неизменяемое (иммутабельное) значение
let myInt = 5
let myFloat = 3.14
let myString = "привет"   // обратите внимание - указывать тип не нужно

// ======== Списки ============
let twoToFive = [ 2; 3; 4; 5 ]        // Списки создаются с помощью квадратных скобок,
                                      // для разделения значений используются точки с запятой.
let oneToFive = 1 :: twoToFive        // оператор :: создает список с новым первым элементом
// Результат: [1; 2; 3; 4; 5]

let zeroToFive = [0;1] @ twoToFive    // оператор @ объединяет два списка

// ВАЖНО: запятые никогда не используются для разделения значений, только точки с запятой!

// ======== Функции ========
// Ключевое слово "let" также определяет именованную функцию.
let square x = x * x          // Обратите внимание - скобки не используются.
square 3                      // А сейчас вызовем функцию. Снова никаких скобок.

let add x y = x + y           // не используйте add (x,y)! Это означает
                              // совершенно другую вещь.
add 2 3                       // Вызовем фукнкцию.

// чтобы определить многострочную функцию, просто используйте отступы.
// Точки с запятой не требуются.
let evens list =
   let isEven x = x % 2 = 0     // Определет "isEven" как внутреннюю ("вложенную") функцию
   List.filter isEven list      // List.filter - это библиотечная функция
                                // с двумя параметрами: предикат
                                // и список, которые требуется отфильтровать

evens oneToFive                 // Вызовем функцию

// Вы можете использовать скобки, чтобы уточнить приоритет.
// В данном примере, сначала используем "map" с двумя аргументами,
// а потом вызываем "sum" для результата.
// Без скобок "List.map" была бы передана как аргумент в "List.sum"
let sumOfSquaresTo100 =
   List.sum (List.map square [ 1 .. 100 ])

// Вы можете передать результат одной функции в следующую с помощью "|>"
// Вот та же самая функция sumOfSquares, переписанная с помощью конвейера
let sumOfSquaresTo100piped =
   [ 1 .. 100 ] |> List.map square |> List.sum  // "square" определена раньше

// вы можете определять лямбда-функции (анонимные функции) 
// с помощью ключевого слова "fun"
let sumOfSquaresTo100withFun =
   [ 1 .. 100 ] |> List.map (fun x -> x * x) |> List.sum

// В F# значения возвращаются неявно - ключевое слово "return" не используется
// Функция всегда возвращает значение последнего выражения в ее теле

// ======== Сопоставление с образцом ========
// Match..with.. - это case/switch инструкции "на стероидах".
let x = "a"
match x with
| "a" -> printfn "x - это a"
| "b" -> printfn "x - это b"
| _ -> printfn "x - это что-то другое"   // подчеркивание соответствует "чему угодно"

// Some(..) и None приблизительно соответствуют оберткам Nullable
let validValue = Some(99)
let invalidValue = None

// В данном примере match..with сравнивает с "Some" и "None"
// и в то же время распаковывает значение в "Some".
let optionPatternMatch input =
   match input with
    | Some i -> printfn "целое число %d" i
    | None -> printfn "входное значение отсутствует"

optionPatternMatch validValue
optionPatternMatch invalidValue

// ========= Сложные типы данных =========

// Кортежи - это пары, тройки значений и так далее.
// Кортежи используют запятые.
let twoTuple = (1, 2)
let threeTuple = ("a", 2, true)

// Записи имеют именованные поля. Точки с запятой являются разделителями.
type Person = { First: string; Last: string }

let person1 = { First="John"; Last="Doe" }
// Вы можете также использовать переносы на новую строку
// вместо точек с запятой.
let person2 =
    { First="Jane"
      Last="Doe" }

// Объединения представляют варианты. Разделитель - вертикальная черта.
type Temp = 
    | DegreesC of float
    | DegreesF of float

let temp = DegreesF 98.6

// Типы можно комбинировать рекурсивно различными путями.
// Например, вот тип-объединение, который содержит список
// элементов того же типа:
type Employee = 
  | Worker of Person
  | Manager of Employee list

let jdoe = { First="John"; Last="Doe" }
let worker = Worker jdoe

// ========= Вывод на экран =========
// Функции printf/printfn схожи с функциями Console.Write/WriteLine из C#.
printfn "Вывод на экран значений типа int %i, float %f, bool %b" 1 2.0 true
printfn "Строка %s, и что-то обобщенное %A" "hello" [ 1; 2; 3; 4 ]

// все сложные типы имеют встроенный красивый вывод
printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A" 
    twoTuple person1 temp worker

В дополнение, в нашей официальной документации для .NET и поддерживаемых языков есть материал «Тур по F#».


Что делать дальше


Всё описанное в данном посте — лишь поверхностные возможности F#. Мы надеемся, что после прочтения этой статьи вы сможете погрузиться в F# и функциональное программирование. Вот несколько примеров того, что можно написать в качестве упражнения для дальнейшего изучения F#:



Есть очень много других задач, для которых можно использовать F#; предыдущий список ни в коем случае не является исчерпывающим. F# используется в различных приложениях: от простых скриптов для сборки до бэкенда интернет-магазинов с миллиардной выручкой. Нет никаких ограничений по проектам, для которых вы можете использовать F#.


Дополнительные ресурсы


Для F# существует множество самоучителей, включая материалы для тех, кто пришел с опытом C# или Java. Следующие ссылки могут быть полезными по мере того, как вы будете глубже изучать F#:



Также описаны еще несколько способов, как начать изучение F#.


И наконец, сообщество F# очень дружелюбно к начинающим. Есть очень активный чат в Slack, поддерживаемый F# Software Foundation, с комнатами для начинающих, к которым вы можете свободно присоединиться. Рекомендуем вам это сделать!


Не забудьте посетить сайт русскоязычного сообщества F#! Если у вас возникнут вопросы по изучению языка, мы будем рады обсудить их в чатах:



Об авторах перевода


Статья переведена усилиями русскоязычного сообщества F#-разработчиков.
Мы также благодарим @schvepsss за подготовку данной статьи к публикации.

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

https://habrahabr.ru/post/335560/


Метки:  

Дайджест свежих материалов из мира фронтенда за последнюю неделю №275 (7 — 13 августа 2017)

Понедельник, 14 Августа 2017 г. 10:30 + в цитатник
Предлагаем вашему вниманию подборку с ссылками на новые материалы из области фронтенда и около него.


Медиа
Веб-разработка
CSS
Javascript
Браузеры
Занимательное

Медиа




Веб Разработка




CSS




JavaScript




Браузеры




Занимательное



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



Дайджест за прошлую неделю.
Материал подготовили dersmoll и alekskorovin.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335562/


Метки:  

Цифровая экономика должна быть цифровой

Понедельник, 14 Августа 2017 г. 10:29 + в цитатник

Источник
«Экономика должна быть экономной – таково требование времени»
Л.И.Брежнев (из отчетного доклада на XXVI съезде КПСС, 1981 г.)


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


Презентации конкретных решений и продуктов, относящихся к различным категориям экосистемы цифровой экономики производятся в наше время регулярно, и уже многие участники как мирового, так и отечественного рынка имеют ежедневный опыт создания элементов и продуктов онлайн-экономики. И потому нет ничего удивительного, что согласно опубликованному рейтингу самых дорогих брендов мира The BrandZ Global Top 100, на первом месте в нем расположилась компания Google со стоимостью бренда 245,6 млрд долларов США, а вслед за ней — еще четыре представителя Кремниевой долины: Apple, Microsoft, Amazon и Facebook. Российских брендов в сотне самых дорогих, правда, не оказалось. Это все интернет-гиганты, которые построены на мощных и инновационных платформах. Что касается пятерки лидеров, то за год она претерпела лишь одно изменение: теперь на четвертой строчке располагается не телекоммуникационный гигант AT&T, а крупнейший в мире онлайн-ритейлер Amazon. Что касается цифрового бизнеса, то это новая модель бизнеса, охватывающая людей/бизнес/вещи, масштабируемая глобально для всего мира за счет использования информационных технологий, интернета, и всех их свойств, предполагающая эффективное персональное обслуживание всех, везде, всегда.


Приметы нового времени


В целом так называемый Data Driven бизнес или же, говоря простым языком, — бизнес, основной движущей силой которого являются данные, сегодня становится общей практикой для множества предприятий самых разных отраслей. А управление данными лежит в основе набирающей популярность цифровой трансформации бизнеса. По оценкам экспертов к 2020 г. объем данных, ежегодно обрабатываемых ЦОДами (центрами обработки данных), достигнет отметки 15,3 Зб (зетабайт), количество бизнес-пользователей превысит 325 млн., количество подключенных к Интернету устройств достигнет 20 млрд., заметно расширится спектр типов данных, 92% трафика данных в ЦОДах придется на «облачные вычисления», а на помощь миллиарду работников придет искусственный интеллект.


В декабре прошлого года регулятор развития транспортной инфраструктуры США объявил, что все новые автомобили в стране, выпуск которых начнется в 2023 году, должны быть оснащены системами обмена данными стандарта V2V (vehicle-to-vehicle, "автомобиль-автомобиль"), который предполагает обмен данными о маршрутах и скорости движения между всеми машинами на дороге, что должно принципиально снизить аварийность на дорогах.



Источник


Разработчики из Университета штата Огайо недавно получили правительственный грант на создание "умного" шоссе на 56-километровом участке трассы в пригороде Колумбуса, столицы штата. Речь идет о трассе стандарта V2I (vehicle-to-infrastructure, "автомобиль-инфраструктура"), который предусматривает обмен данными между объектами дорожной инфраструктуры (дорожными знаками, светофорами и различными датчиками) и движущимися автомобилями. Вдоль шоссе будет проложена волоконно-оптическая линия связи, которая соединит приемопередатчики, расположенные через каждые 600 метров. Благодаря полученной информации от дороги автомобиль сможет, к примеру, предупредить водителя о заторе по маршруту движения, просчитать объезд, а также спрогнозировать время простоя на светофоре.


Или вот настоящая «звезда блокчейна», любимец банкиров и журналистов, Виталий Бутерин, создавший Ethereum — платформу для создания децентрализованных интернет-сервисов (dapps), работающих на базе умных контрактов. Платформа запустилась 30 июля 2015 года. В марте этого года рыночная капитализация Ethereum превысила 1 млрд долларов США, а созданная на ее базе криптовалюта Ether заняла второе место после биткоина. В ходе недавнего Петербургского экономического форума (ПМЭФ) президент РФ Владимир Путин встречался и с основателем Ethereum, а первый вице-премьер российского правительства Игорь Шувалов в ходе панельной сессии на ПМЭФ заявил о том, что в России в настоящее время уже работают над тремя направлениями развития технологии блокчейн. По его словам, среди задач, требующих оперативного решения — обеспечение «цифровой прослеживаемости товаров», создание общей платформы на основе блокчейна для идентификации личности и электронная защита титула собственника.


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


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


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


Зрелища без хлеба


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



Источник


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


Впрочем, возможно, что бурно развивающиеся биотехнологии со временем позволят синтезировать пищу по заказу, о чем полвека назад популярно рассказал Илья Варшавский в рассказе «Молекулярное кафе». Может быть, со временем получится и что-то более продвинутое, о чем рассказывалось, к примеру, в «Трудно быть Богом» Стругацких:
«Хрустя каблуками по битому стеклу, Румата пробрался в дальний угол и включил электрический фонарик. Там под грудой хлама стоял в прочном силикетовом сейфе малогабаритный полевой синтезатор «Мидас». Румата разбросал хлам, набрал на диске комбинацию цифр и поднял крышку сейфа. Даже в белом электрическом свете синтезатор выглядел странно среди развороченного мусора. Румата бросил в приемную воронку несколько лопат опилок, и синтезатор тихонько запел, автоматически включив индикаторную панель. Румата носком ботфорта придвинул к выходному желобу ржавое ведро. И сейчас же — дзинь, дзинь, дзинь! — посыпались на мятое жестяное дно золотые кружочки с аристократическим профилем Пица Шестого, короля Арканарского».


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


Государство и граждане


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


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



Источник


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


Прозрачность до «безобразия»


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



Источник


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


Еще лет десять назад политики и военные представить не могли, что тысячи страниц секретных материалов могут быть обнародованы вместе с их откровенными частными беседами. Сейчас подобные утечки стали обыденным делом. Взять хотя бы длящуюся уже давно истерику в США по части якобы хакерского взлома у них чего-либо. Простите, ребята, а разве это не вы в течение десятилетий гордились наличием у себя системы «Эшелон», «стригущей» любую информацию на планете, позже привлекали для этого интернет-ресурсы, создавали кибервойска и пр.? Большего саморазоблачения творцов, в том числе и цифровой экономики, и придумать сложно. Либо это ложь во спасение каких-то своих политических целей, потому что не в традициях разведок столь публично заявлять о своих провалах, либо настоящее бессилие перед выпущенным из бутылки джинном. Причем и то, и другое не внушает оптимизма по поводу перспектив цифровой экономики.


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


Последствия цифровой трансформации


Одним из последствий новой цифровой трансформации будет, в частности, более глубокое видение того, что люди делают в компаниях. Это важно, поскольку сейчас люди составляют половину активов компаний. Активы типичной компании сейчас на 25% состоят из физических активов, на 50% из сотрудников и на 25% из стоимости бренда и других нематериальных активов. Специалисты отмечают, что при цифровой экономике обязательно будут проигравшие и среди простых граждан. Какие-то специальности станут ненужными, кого-то заменит искусственный интеллект. «Новый уклад разрушает многие традиционные сектора, растут отрицательные эмоции среди тех, кто там работал. Цифровые технологии могут усугублять социально-экономическое неравенство», – признают даже во Всемирном банке.


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


Кто-то считает, что подобное развитие событий может стать реальным уже в ближайшем будущем и окажется сродни тому, что принято называть Апокалипсисом. К сведению любителей теорий катастроф в переводе с греческого Апокалипсис — это «открытие, снятие покрова, разоблачение». Иначе — всеобщее прозрение. И что самое забавное, к этому прозрению человечество толкает банальное развитие цифровой экономики, а отнюдь не только вдруг снизошедшая откуда-то способность к телепатии. Указанный перелом в истории человечества предсказан не только лишь Иисусом Христом, который, кстати, и обещал, что однажды «все тайное станет явным», но и многими пророками, которые видели приход «Золотого века» и появление нового, более честного и справедливого общества. Американский Университет Сингулярности, созданный NASA и Google, опубликовал недавно «Предсказания человечеству на следующие 20 лет», где его эксперты утверждают, что до 2020 года появятся интернет-приложения, способные с высокой вероятностью распознавать правду и ложь. И очень даже может быть, что уже через пять-семь лет такие мини-детекторы лжи начнут входить в стандартный набор функций многих смартфонов.



Источник


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


По материалам: tass.ru, ng.ru, cnews.ru, helionews.ru, pcweek.ru, forum-msk.org, nplus1.ru, dic.academic.ru, mk.ru, arb.ru, 3rm.info


Автор публикации:
Александр ГОЛЫШКО, системный аналитик ГК «Техносерв»

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

https://habrahabr.ru/post/335156/


Метки:  

Рынок источников бесперебойного питания вырос впервые за четыре года

Понедельник, 14 Августа 2017 г. 10:24 + в цитатник
Седьмого августа аналитическая компания IHS Markit поделилась результатом очередного исследования: после четырех лет спада рынок источников бесперебойного питания (ИБП) вернулся к росту в 2016 году и приблизился к оценке в $7,4 млрд. Хотя положительная динамика составила 1,6%, аналитики прогнозируют дальнейшее увеличение объема рынка в 2017 и 2018 годах. Это поднимает вопрос влияния облачных сервисов на рынок аппаратного обеспечения.

/ Flickr / Torkild Retvedt / CC

Как считают в The Register, именно рост рынка услуг облачных вычислений создал благоприятные условия для рынка ИБП. Спрос на услуги более крупных хостинговых компаний диктует необходимость операторам ЦОДов обеспечивать свои дата-центры оборудованием с показателем безотказной работы в 99%, что возможно только при оснащении современными ИБП.

Согласно IHS Markit, то, что можно наблюдать сегодня, — это результат процесса перехода от корпоративных центров обработки данных к облачным сервисам и услугам колокейшн. На сегодняшний день около 40% мощностей всех дата-центров базируются на платформах 145 лидирующих провайдеров. В компании считают, что их доля в общем объеме будет расти и дальше, создавая благоприятные условия для рынка ИБП, фактически обслуживающему эту потребность.

/ Flickr / Paradox Wolf / CC

Согласно исследовательской компании Global Industry Analysts, к 2022 году рынок ИБП должен достигнуть $13,7 млрд, то есть вырасти почти вдвое по сравнению с нынешним объемом. Точкой роста считается дефицит резервного питания в век облачных сервисов. Если этот прогноз сбудется, темпы будут рекордными.

Так или иначе, перенос значительной части вычислений в облака меняет рынок. Например, в 2015 году компания Microsoft задумалась об отказе от самой идеи центральных автономных ИБП для дата-центров в пользу мини-ИБП из соображений экономии пространства и энергоэффективности. ЦОД Stack Data Network (SDN), в котором располагаются сервера 1cloud, также использует небольшие и компактные ИБП Hitec Power Protection B.V.

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

Облака меняют рынок аппаратного обеспечения


Новый отчет от Morgan Stanley указывает на то, что индустрия аппаратного обеспечения переживет в этом году сокращение расходов, так как приоритеты в IT смещаются в сферы облачных вычислений и искусственного интеллекта. Опрос руководителей компаний продемонстрировал, что к 2020 году около половины корпоративных рабочих мощностей будут перемещены в облака.

В связи с этим мировые международные расходы на услуги облачных служб и инфраструктуру достигнут $122,5 млрд в этом году, согласно IDC, что на 24,4% больше в сравнении с 2016 годом.

В 2013 году отчет Baird Equity Research Technology описывал будущее аппаратного обеспечения следующим образом: «на каждый доллар, потраченный на [Amazon Web Services] будут приходиться как минимум 3-4 доллара, не потраченные на традиционное информационные технологии [..] Другими словами, получение AWS дохода в $10 млрд к 2016 году означает, что традиционный IT-рынок потерял не менее 30–40 млрд долларов».

В том же докладе отмечается, что вызов времени заставляет такие компании, как IBM, Hewlett-Packard, Microsoft, менять приоритеты в выпуске продуктов с физических на облачные, что в конечном счете сказывается на их традиционных источниках доходов. Как показало время, прогнозы отчасти верны.

Так, по оценкам Nasdaq, в общем объеме доходов IBM за 2016 год 22% занимали облачные услуги, в то время как в сегменте продаж серверов произошло падение доходов. И, если в этом отношении первопричиной выступает конкурентная среда, то в случае с падением продаж систем хранения на 10% «угроза» исходит именно от массовой миграции в облака.

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

Особенность рынка, так или иначе, связана с его ориентацией на нескольких крупных провайдеров. Поскольку развитие инфраструктуры публичных облачных сервисов опережает рост частных облаков, именно эти игроки и диктуют правила. Согласно Synergy Research Group, в 2016 году ведущими поставщиками облачной инфраструктуры выступали Cisco, HP Enterprise и Dell EMC, но их доходы не росли, так как некоторые большие дата-центры отдают предпочтение изготовителям изделий по оригинальному проекту без узнаваемого бренда.

Эта ситуация демонстрирует основной тренд рынка — рост зависимости продаж от запросов крупнейших компаний, которые по сути выступают посредниками между конечными пользователями инфраструктуры и производителями. Учитывая прогноз Forrester, согласно которому рост инфраструктуры как услуги в 2017 году составит 38%, зависимость производителей оборудования от провайдеров облачных услуг будет лишь расти, и такие колебания, как увеличение продаж ИБП, будут сопровождать этот рост.

P.S. Еще несколько материалов о виртуализации и инфраструктуре из нашего блога:

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

https://habrahabr.ru/post/335558/


Метки:  

Построение рекомендаций для сайта вакансий. Лекция в Яндексе

Понедельник, 14 Августа 2017 г. 10:00 + в цитатник
В последнее время мы много пишем о конкурсах по машинному обучению, в основном рассматривая их с точки зрения участников. Но организовать и правильно провести соревнование — тоже сложная задача. Компании учатся на своих ошибках и в следующие разы меняют структуру конкурсов. Например, RecSys Challenge 2017 с учётом опыта прошлых лет провели в два последовательных этапа. Андрей Остапец из компании Avito рассказывает об этих этапах, о различных признаках, основанных на истории поведения пользователей, и о том, всегда ли нужно использовать сложные модели для решения задачи. Команда Андрея заняла в RecSys Challenge седьмое место.




— Всем привет! Меня зовут Андрей, я работаю в Avito, и сегодня я расскажу про участие нашей команды в конкурсе RecSys Challenge 2017.

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

RecSys Challenge — конкурс, который проводится в рамках конференции RecSys. Это крупная конференция, в нынешнем году она будет проводиться в 11-й раз. На конференции достаточно много научных докладов, но с самого начала у организаторов была традиция проводить конкурс по рекомендациям. Каждый год какая-то компания организует конкурс, различные команды участвуют. В итоге все приезжают на воркшопы и рассказывают про свои решения. В этом есть плюс по сравнению с Kaggle: можно рассказать про свой алгоритм, опубликовать статью в отдельном журнале, посвященном воркшопу конференции, узнать какие-то подробности у организаторов конкурса и посмотреть, какие решения использовали другие участники.

В прошлом году, как и в этом, конкурс проводила компания XING. Это немецкий аналог LinkedIn, который посвящен рекомендациям работы. В прошлом году команда Avito тоже участвовала в RecSys Challenge, мы заняли седьмое место и рассказали об этом на тренировке в ШАДе. Вот ссылка на наш рассказ.

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

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

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

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

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

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

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

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

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

Как использовать рекомендации?

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

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

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

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

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



На слайде — данные, которые были предоставлены участникам.



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

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

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



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



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

Для небольшой статистики показано распределение тренировочной выборки в онлайн-стадии. В обучении был миллион пользователей, 750 тыс. вакансий, порядка 90 млн показов, около 4 млн взаимодействий. То есть пользователи кликают не так часто, причем б'oльшая часть взаимодействий — клики. На втором месте — удаление рекомендации. Пользователи довольно часто удаляют рекомендации и говорят, что не хотят их больше видеть. Остальных типов было меньше.



Какой функционал качества использовался? Он был довольно необычным. Участники должны были для каждой вакансии предоставить список рекомендаций. Итоговая сумма, которую получало решение, считалась по всем вакансиям. И оценка для каждой вакансии разбивалась на две части: user success, определяющая, насколько это успешно по пользователям, и item success — был ли этот список рекомендаций успешен для данной вакансии.

User success считался просто. Если какой-то пользователь кликнул на вакансию, получался 1 балл. Если нажал кнопку «Добавить в закладки» или «Ответить» — 5 баллов, причем если он выполнял оба действия, все равно прибавлялось только 5 баллов. Если к нему проявил интерес рекрутер, к оценке добавлялось 20 очков. Если пользователь удалил вакансию — минус 10 очков. Причем вся эта сумма умножалась на два, если пользователь являлся премиум и платил XING деньги.

С item success все немного интереснее. Для каждой вакансии был предоставлен список пользователей, и если хотя бы для одного пользователя рекомендация была успешной, то в случае, если item платный, получалось 50 очков, а если бесплатный — 25. Ну а если для вакансии не было ни одного успешного кандидата, ни один человек не кликнул и не получил сумму больше нуля, то к оценке добавлялся 0, мы не получали ничего.

Сразу может возникнуть вопрос: какую максимальную оценку можно было получить за одну пару юзер-вакансия, исходя из этого функционала? 102. Кликнул на вакансию — плюс 1, добавил в закладки — плюс 5, рекрутер проявил интерес — плюс 20, пользователь премиум — умножаем на два. Получаем 52, и этот пользователь является успешной рекомендацией для данной вакансии. Если item платный, получаем еще 50 очков, в сумме 102.

Очевидно, минимум за рекомендацию — всего 1 очко. Это если пользователь просто кликнул на вакансию и есть item, который уже является успешным для данной вакансии.

Какие вызовы со стороны организаторов?

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

Второй вызов — баланс между релевантностью и заработком. Как было показано, score сильно зависел от того, является ли пользователь и item премиум, получает ли платформа XING с них деньги.

Третье — проблема «холодного старта». Все вакансии не имели истории, и это более сложная задача, поскольку мы могли использовать только контент объявления.

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



Сначала организаторы, как и во многих конкурсах, предоставили baseline. Он был крайне простой, но показывал хороший результат. В нем было всего шесть признаков, причем пять из них были бинарными: количество совпадений по тайтлам юзера и вакансии, натуральное число, и дальше простой матчинг дисциплины, уровня карьеры, отрасли, страны и региона. Для обучения использовалось только взаимодействие. Если пользователь удалил вакансию, целевая переменная получалась равной нулю, а если пользователь произвел положительное действие — единице. Это обучалось на XGBoost и давало результат 10 000 на лидерборде. Довольно хорошо.



Если просто для всех вакансий на офлайн-стадии рекомендуем топ-100 самых активных пользователей, получаем результат 519. XGBoost дает намного больше.

Какой был объем выборки? Всего 300 млн взаимодействий, 75 млн целевых пользователей, для которых надо было построить рекомендации, и примерно 50 тыс. целевых вакансий.

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

Чтобы ускорить процесс, предсказание для пары делалось только в том случае, если есть пересечение по заголовкам. В итоге выборка, для которой XGBoost должен построить предсказание, — примерно 50 млн. Когда я пытался воспроизвести этот baseline, я столкнулся с проблемой, что на сервере не работал XGBoost, и я просто переписал на Н2О, но на решение это не оказало существенного влияния.



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

После того, как я добавил еще 19 и получилось 25, действительно удалось чуть-чуть улучшить результат. Он стал примерно 11 тыс., но дальнейшие улучшения не получались. Причем в конце были различные эксперименты: по-другому составить обучающую выборку, давать разным событиям разный вес, просто добавлять им просмотры с небольшим весом, который больше, чем вес удаления, но меньше, чем у положительного действия. Но все это приводило к тому, что score падал, пока наконец не получился результат минус 5000. Плохо, в основном рекомендуем то, что пользователи удаляют.



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

Вторая проблема — я оптимизировал среднеквадратичное отклонение в XGBoost, и наверное, это плохо. Функционал заточен на деньги, а мы оптимизируем RMSE. Но с этим надо было что-то делать.

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

Дальше строим различные интересы к параметрам, исходя из истории пользователя. Никак не используем профиль пользователя, смотрим только на то, что он кликал и что удалял.

Третья часть, которая была актуальна для офлайн-стадии: для некоторых айтемов и пользователей были указаны предыдущие взаимодействия. Их было мало, но все равно они позволяли немного поднять score.

Логично, что если есть 50 тыс. пользователей и 50 тыс. вакансий, то все их проскорить невозможно. Надо отбирать какое-то множество подходящих. Чтобы уменьшить объем предсказаний, использовалась следующая эвристика: для пары вычисляем оценку только в том случае, если есть какое-то пересечение по заголовкам вакансии и профиля пользователя, либо если пользователь просматривал объявление, которое пересекается с вакансией. Например, у пользователя указано, что он является аналитиком, и он когда-то совершил всего один клик на data scientist. Потенциальные рекомендации — это вакансии, где есть слова «аналитик», «data scientist» и всё. Очевидно, это не самая лучшая эвристика, но она позволяет существенно сократить объем той выборки, для которой надо строить предсказания.



Как считались различные близости? В качестве примера рассмотрим близость ключевых слов к заголовку вакансии. Основная идея в том, что vs можем использовать некий аналог IDF по трем словарям, то есть у нас есть слова из профиля пользователя и из заголовка айтема, а также теги айтема. Для них вычислялся аналог IDF. Мы просто берем логарифм от числа уникальных токенов на встречаемость токенов, и чем реже встречается токен, тем больший вес он получает. Когда мы считаем близость по профилю, мы просто это нормируем на количество уникальных ключевых слов пользователя. Чем меньше у него ключевых слов, тем больший вес получит данная сумма.

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



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



Как считались близости по другим признакам? По карьерному уровню все было довольно просто: он был от 1 до 6, поэтому по профилю мы можем просто рассмотреть разность. Если разность маленькая — увеличиваем вес, если большая — уменьшаем. Забавно, что пользователи, у которых было указано, что они студенты, тоже иногда смотрели вакансии, где требовались директора фирм. Очевидно, что они под эти вакансии не подходят, но какой-то интерес был. Непонятно, почему. Как следствие — в данном случае нельзя ставить нулевой вес. Мы просто использовали понижение веса.

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

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



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

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

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

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

Минусы в валидации. В последних днях не было события с типом «интерес рекрутера», непонятно, как валидироваться по этому событию. Но по факту получилось интересно: на деле этого события не было в онлайн-этапе. Либо организаторы ошиблись в каких-то данных, либо у них поехала статистика. Самое дорогое действие, которое приносило больше всего очков по user success, с какого-то момента перестало появляться на сайте. Либо статистика упала, либо пользователи не привлекали рекрутеров. И совпадение такой валидации с публичным лидербордом было примерно в 70% случаев. Поэтому валидация шла исходя из улучшения на локальной валидации, по ссылке на публичный лидерборд. Если и там, и там совпадало, то алгоритм обновлялся. Если нет — искалось что-то новое.

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



Получившиеся улучшения. Использование такого алгоритма позволило повысить скорость примерно до 20 тыс., а в дальнейшем удалось дойти до 32 тыс. Причем score не всегда улучшался, потому что локальная валидация не всегда отражала действительный порядок и улучшения.



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

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



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



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

После этого в течение семи дней меряется фидбек пользователей. Если пользователь кликнул на данную вакансию в течение 7 дней, то команда получает результат, какие-то очки, а если он кликнул на вакансию через 8 дней — команда ничего не получает. Так длится до окончания конкурса.



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

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



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



На третьей неделе, несмотря на то, что никаких изменений не было, score упал. На второй было 4800, на третьей стало 3800, причем алгоритм никак не менялся. Возможно, это связано с тем, что кусок трафика, который давался каждой команде, включал в себя примерно 50 тыс. пользователей, и каждый день нужно было строить рекомендации примерно для 10 тыс. вакансий. Уажется, что 50 тыс. пользователей — много. Все равно их поведение случайно, и в один день можно получить больше, а в другой — меньше.

Мы решали это командой Avito, но договорились идти параллельными путями: каждый делал свое решение. Мое решение с самого начала было лучше, но за две недели до конца удалось настроить линейную комбинацию решений. Василий Лексин построил решение на основе LCE, он об этом рассказывал неделю назад на Avito Data Science meetup по рекомендациям — можно перейти по ссылке и послушать.

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

Мы попытались отправлять алгоритм уже на основе линейной комбинации, но score не вырос.



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

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



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



По сумме двух недель у нас получился результат 8700 очков. У победителя довольно серьезный отрыв — почти 11 тыс. очков. Но заметно, что все команды со второго по седьмое место находятся очень близко. Второе место — 9700, у нас 8700, результаты довольно близкие. И отрыв от восьмого места в 1700 очков тоже является достаточно значительным. При этом надо понимать, что последние две недели, когда, скорее всего, все участники улучшали свои алгоритмы, пропали, и по факту можно было использовать только первые три недели. Допустим, для первой недели мы запоздали с посылкой решения и тоже получили низкий score. Являются ли эти результаты адекватными? Мы могли оказаться и выше, и ниже.

Из интересного: все шесть команд, которые оказались выше нас, на офлайн-стадии занимали места с первого по восьмое, а то, что я описал, было на 18 месте. Мы использовали его без изменений, и нас это подняло с 18 места на седьмое.



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

Что не получилось?

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

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

Третье — не удалось получать обратную связь по изменению качества работы модели на онлайн-этапе. Организаторы давали все взаимодействия за предыдущий день. Были идеи использовать некое А/В-тестирование: дается 50 тыс. пользователей, мы разбиваем их на две части, на одной запускаем один алгоритм, на другой — другой, после этого получаем обратную связь по тому, как это действует на сайте, и выборка в 25 тыс. должна показывать результаты. И уже исходя из этого использовать подстройку алгоритма. Но по факту мы пытались несколько раз воспроизвести score на лидерборде, и он отличался от того, который строился по взаимодействиям от организаторов. Так что мы решили, что невозможно им доверять, и поэтому такое тестирование не получилось.

Использование по всей выборке, когда в один день отправлялся бы один алгоритм, а в другой день — другой, не получалось, исходя из того, что score в лидерборде обновлялся за 7 предыдущих дней. Если ты поменял параметр в алгоритме, то точное улучшение ты увидишь через 7 дней. Это долго: конкурс длился всего пять недель.

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

https://habrahabr.ru/post/335526/


Интеграция Intel Threading Building Blocks в ваш CMake проект

Понедельник, 14 Августа 2017 г. 09:47 + в цитатник


Привет, уважаемые читатели habrahabr. В этом блоге мы хотели бы анонсировать, что теперь у нас появились CMake модули, которые позволяют скачивать, собирать и просто использовать Intel Threading Building Blocks (Intel TBB) в ваших CMake проектах. Модули доступны в репозитории проекта Intel TBB на GitHub, а также в бинарных пакетах для Linux* OS, Windows* OS и macOS*, начиная с релиза Intel TBB 2017 Update 7.


Использование Intel TBB CMake модулей


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

Интеграция библиотеки в проект


Конфигурационные файлы TBBConfig.cmake и TBBConfigVersion.cmake позволяют получить необходимые переменные и импортированные цели для использования Intel TBB. Файлы находятся в папке /cmake в бинарных пакетах для Linux* OS, Windows* OS или macOS*, начиная с релиза Intel TBB 2017 Update 7.
Алгоритм:
  1. Скачать и распаковать бинарный пакет.
  2. Добавить расположение корневой папки подключаемой библиотеки в переменную CMAKE_PREFIX_PATH или путь до конфигурационных файлов в переменную TBB_DIR.
  3. Вызвать функцию find_package (TBB), добавив нужные параметры при необходимости.
  4. Использовать полученные переменные и/или импортированные цели.

Необходимые компоненты библиотеки могут быть перечислены после ключевого слова COMPONENTS или REQUIRED при вызове функции find_package, например, tbb, tbbmalloc, tbb_preview и т.д. По умолчанию доступны компоненты tbb, tbbmalloc и tbbmalloc_proxy. Для каждого компонента создаётся импортированная цель формата TBB::.
Определяются следующие переменные:
TBB_FOUND
флаг успешности поиска Intel TBB
TBB__FOUND
флаг успешности поиска отдельного компонента
TBB_IMPORTED_TARGETS
все созданные импортированные цели
TBB_VERSION
версия Intel TBB (формат: .)
TBB_INTERFACE_VERSION
версия интерфейса Intel TBB

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

Сборка Intel TBB из исходного кода с помощью TBBBuild


Модуль TBBBuild.cmake предоставляет функцию tbb_build, которая позволяет собрать библиотеку из исходного кода с использованием родной инфраструктуры библиотеки (Makefile). Для сборки на Linux* OS и macOS* необходимо наличие make-утилиты, а на Windows* OS – gmake. После непосредственно сборки создаются нужные конфигурационные файлы в папке /cmake.
Функция tbb_build принимает следующие параметры:
TBB_ROOT
путь до корневой папки бибилотеки, которую нужно собрать
CONFIG_DIR
переменная, в которую запишется полный путь к папке с созданными конфигурационными файлами;
значение -NOTFOUND будет возвращено в случае ошибки при сборке
MAKE_ARGS
настраиваемые аргументы для make-команды;
следующие аргументы определяются и передаются автоматически, если они не переопределены в :
  • compiler=
  • tbb_build_dir=
  • tbb_build_prefix=
  • -j


Пример использования модуля:
include(/TBBBuild.cmake)
tbb_build(TBB_ROOT  CONFIG_DIR TBB_DIR)
find_package(TBB )


Скачивание Intel TBB с помощью TBBGet


Модуль TBBGet.cmake предоставляет функцию tbb_get, которая позволяет скачивать и распаковывать бинарные пакеты и пакеты с исходным кодом для официальных релизов Intel TBB с GitHub. Для бинарных пакетов старше Intel TBB 2017 Update 7 конфигурационные файлы создаются автоматически в папке /cmake.
Функция tbb_get принимает следующие параметры:
TBB_ROOT
переменная, в которую будет записан полный путь к корневой папке скачанного и распакованного пакета;
значение -NOTFOUND будет возвращено в случае ошибки при скачивании
RELEASE_TAG |LATEST
тег релиза для скачивания;
по умолчанию используется значение LATEST
SAVE_TO
путь для распаковки скачанного пакета;
по умолчанию используется ${CMAKE_CURRENT_BINARY_DIR}/tbb_downloaded
SYSTEM_NAME Linux|Windows|Darwin
ОС, для которой необходимо скачать бинарный пакет;
по умолчанию используется значение переменной CMAKE_SYSTEM_NAME
CONFIG_DIR
переменная, в которую будет записан полный путь до конфигурационных файлов;
параметр игнорируется, если указан флаг SOURCE_CODE
SOURCE_CODE
флаг, сигнализирующий о необходимости скачивания пакета с исходным кодом вместо бинарного пакета

Примеры использования модуля:
  1. Скачивание и подключение самого свежего бинарного пакета для текущей ОС
    include(/TBBGet.cmake)
    tbb_get(TBB_ROOT tbb_root CONFIG_DIR TBB_DIR)
    find_package(TBB )

  2. Скачивание, сборка и подключение самого свежего пакета с исходным кодом
    include(/TBBGet.cmake)
    include(/TBBBuild.cmake)
    tbb_get(TBB_ROOT tbb_root SOURCE_CODE)
    tbb_build(TBB_ROOT ${tbb_root} CONFIG_DIR TBB_DIR)
    find_package(TBB )
    


Демо-проекты на базе примера GettingStarted/sub_string_finder с подключением Intel TBB



Подключение бинарного пакета на Windows* OS
В этом примере мы создадим CMake проект на базе GettingStarted/sub_string_finder с подключением бинарного пакета Intel TBB. Пример написан для Windows* OS (Microsoft* Visual Studio), но с незначительными изменениями может быть использован для других ОС.
Ключевые слова и должны быть заменены на актуальные значения для загруженного пакета.

Минимальные требования:
  • CMake 3.0.0
  • Microsoft* Visual Studio 11 (для Intel TBB 2017 Update 7)
  • Intel TBB 2017 Update 7

Инструкция:
  1. Скачайте Intel TBB для Windows* OS и распакуйте его в C:\demo_tbb_cmake
  2. В папке C:\demo_tbb_cmake\tbb_oss\examples\GettingStarted\sub_string_finder создайте файл CMakeLists.txt следующего содержания:
    cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
    project(sub_string_finder CXX)
    add_executable(sub_string_finder sub_string_finder.cpp)
    # Функция find_package ищет TBBConfig, используя переменные
    # CMAKE_PREFIX_PATH и TBB_DIR.
    find_package(TBB REQUIRED tbb)
    # "TBB::tbb" можно использовать вместо "${TBB_IMPORTED_TARGETS}"
    target_link_libraries(sub_string_finder ${TBB_IMPORTED_TARGETS})
     
  3. Запустите CMake GUI и
    • Заполните поля (можно использовать кнопки «Browse Source...» и «Browse Build...»):
      «Where is the source сode»:
      C:/demo_tbb_cmake/tbb_oss/examples/GettingStarted/sub_string_finder
      «Where to build the binaries»:
      C:/demo_tbb_cmake/tbb_oss/examples/GettingStarted/sub_string_finder/build
    • Добавьте в кэш новую переменную кнопкой «Add Entry»:
      Name: CMAKE_PREFIX_PATH
      Type: PATH
      Value: C:/demo_tbb_cmake/tbb_oss
    • Cоздайте проект Microsoft* Visual Studio, нажав кнопку «Generate».
  4. Теперь полученный проект можно открыть в Microsoft* Visual Studio (например, нажав кнопку «Open Project» в CMake GUI) и построить. Путь до сгенерированного проекта:
    C:\demo_tbb_cmake\tbb_oss\examples\GettingStarted\sub_string_finder\build\sub_string_finder.sln.
    Окно CMake GUI после генерации проекта:



Сборка библиотеки из исходного кода и подключение в проект
В этом примере мы создадим CMake проект на базе GettingStarted/sub_string_finder, в котором произведём сборку и подключение Intel TBB с включенными Community Preview Features (CPF). Пример написан для Linux* OS, но с незначительными изменениями может быть использован для других ОС.
Минимальные требования:
  • CMake 3.0.0

Инструкция:
  1. Склонируйте репозиторий Intel TBB в папку ~/demo_tbb_cmake:
    mkdir ~/demo_tbb_cmake
    cd ~/demo_tbb_cmake
    git clone https://github.com/01org/tbb.git
    

  2. В папке ~/demo_tbb_cmake/tbb/examples/GettingStarted/sub_string_finder создайте файл CMakeLists.txt следующего содержания:
    cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
    project(sub_string_finder CXX)
    add_executable(sub_string_finder sub_string_finder.cpp)
     include(${TBB_ROOT}/cmake/TBBBuild.cmake)
     # Строим Intel TBB с включенными Community Preview Features (CPF).
    tbb_build(TBB_ROOT ${TBB_ROOT} CONFIG_DIR TBB_DIR MAKE_ARGS tbb_cpf=1)
     find_package(TBB REQUIRED tbb_preview)
     # "TBB::tbb_preview" можно использовать вместо "${TBB_IMPORTED_TARGETS}".
    target_link_libraries(sub_string_finder ${TBB_IMPORTED_TARGETS})
    

  3. Создайте папку для сборки вашего проекта и перейдите туда:
    mkdir ~/demo_tbb_cmake/tbb/examples/GettingStarted/sub_string_finder/build
    cd ~/demo_tbb_cmake/tbb/examples/GettingStarted/sub_string_finder/build
  4. Запустите CMake, указав корневую папку библиотеки Intel TBB:
    cmake -DTBB_ROOT=${HOME}/demo_tbb_cmake/tbb ..
  5. Соберите и запустите проект:
    make
    ./sub_string_finder
    



Заключение


Команда Intel TBB заинтересована в удобной интеграции библиотеки в пользовательские CMake проекты. Новые модули созданы как раз для решения этой задачи. Они предоставляют простой и гибкий интерфейс со множеством вариантов использования. Надеемся, вы попробуете эти модули, и ждём ваших отзывов.
Ссылки и контакты:


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

https://habrahabr.ru/post/335346/


Метки:  

Comedy. Встречайте акторы в Node.JS

Понедельник, 14 Августа 2017 г. 09:47 + в цитатник

Привет, хабравчане!


В этой статье я познакомлю вас с фреймворком Comedy — реализацией акторов в Node.JS.


Акторы позволяют масштабировать отдельные модули вашего Node.JS приложения без изменения кода.


Об акторах


Хотя модель акторов довольно популярна сегодня, не все про неё знают. Несмотря на несколько устрашающую статью в Википедии, акторы — это очень просто.


Что такое актор? Это такая штука, которая умеет:


  • принимать сообщения
  • отправлять сообщения
  • создавать дочерние акторы

image


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


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


Зачем это всё


… сперва мотивация.


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


С другой стороны, это ограничивает область применимости Node.JS. Он отлично подходит для network-intensive приложений с относительно небольшой вычислительной нагрузкой, а вот для CPU-intensive приложений подходит плохо, поскольку интенсивные вычисления блокируют наш драгоценный единственный поток, и всё встаёт колом. Мы это прекрасно знаем.


Знаем мы также и то, что любое реальное приложение какое-то количество CPU всё равно потребляет (даже если у нас совсем нет бизнес-логики, нам нужно обрабатывать сетевой трафик на уровне приложения — HTTP там, протоколы баз данных и прочее). И по мере роста нагрузки мы всё равно рано или поздно приходим к ситуации, когда наш единственный поток потребляет 100% мощности ядра. А что происходит в этом случае? Мы не успеваем обрабатывать сообщения, очередь задач накапливается, время отклика растёт, а потом бац! — out of memory.


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


И вот тут нам на помощь приходят акторы.


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


Для того, чтобы продемонстрировать, как работает Comedy, я набросал небольшой пример: микросервис, который находит простые числа. Доступ к сервису осуществляется через REST API.


Конечно, поиск простых чисел — это в чистом виде CPU-intensive задача. Если бы мы в реальной жизни проектировали такой сервис, нам бы стоило десять раз подумать, прежде чем выбрать Node.JS. Но в данном случае, мы как раз намеренно выбрали вычислительную задачу, чтобы было проще воспроизвести ситуацию, когда одного ядра не хватает.


Итак. Давайте начнём с самой сути нашего сервиса — реализуем актор, находящий простые числа. Вот его код:


/**
 * Actor that finds prime numbers.
 */
class PrimeFinderActor {
  /**
   * Finds next prime, starting from a given number (not inclusive).
   *
   * @param {Number} n Positive number to start from.
   * @returns {Number} Prime number next to n.
   */
  nextPrime(n) {
    if (n < 1) throw new Error('Illegal input');

    const n0 = n + 1;

    if (this._isPrime(n0)) return n0;

    return this.nextPrime(n0);
  }

  /**
   * Checks if a given number is prime.
   *
   * @param {Number} x Number to check.
   * @returns {Boolean} True if number is prime, false otherwise.
   * @private
   */
  _isPrime(x) {
    for (let i = 2; i < x; i++) {
      if (x % i === 0) return false;
    }

    return true;
  }
}

Метод nextPrime() находит простое число, следующее за указанным (не обязательно простым). В методе используется хвостовая рекурсия, которая точно поддерживается в Node.JS 8 (для запуска примера нужно будет взять Node.JS не ниже 8 версии, поскольку там ещё async-await будет). В методе используется вспомогательный метод _isPrime(), проверяющий число на простоту. Это не самый оптимальный алгоритм подобной проверки, но для нашего примера это только лучше.


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


При этом, поскольку это обычный класс, мы можем написать на него unit-тест и легко протестировать корректность его реализации.


Unit-тест может выглядеть как-то так
describe('PrimeFinderActor', () => {
  it('should correctly find next prime', () => {
    const pf = new PrimeFinderActor();

    expect(pf.nextPrime(1)).to.be.equal(2);
    expect(pf.nextPrime(2)).to.be.equal(3);
    expect(pf.nextPrime(3)).to.be.equal(5);
    expect(pf.nextPrime(30)).to.be.equal(31);
  });

  it('should only accept positive numbers', () => {
    const pf = new PrimeFinderActor();

    expect(() => pf.nextPrime(0)).to.throw();
    expect(() => pf.nextPrime(-1)).to.throw();
  });
});

Теперь у нас есть актор-искатель простых чисел.


image


Наш следующий шаг — реализовать актор REST-сервера. Вот как будет выглядеть его определение:


const restify = require('restify');
const restifyErrors = require('restify-errors');
const P = require('bluebird');

/**
 * Prime numbers REST server actor.
 */
class RestServerActor {
  /**
   * Actor initialization hook.
   *
   * @param {Actor} selfActor Self actor instance.
   * @returns {Promise} Initialization promise.
   */
  async initialize(selfActor) {
    this.log = selfActor.getLog();
    this.primeFinder = await selfActor.createChild(PrimeFinderActor);

    return this._initializeServer();
  }

  /**
   * Initializes REST server.
   *
   * @returns {Promise} Initialization promise.
   * @private
   */
  _initializeServer() {
    const server = restify.createServer({
      name: 'prime-finder'
    });

    // Set 10 minutes response timeout.
    server.server.setTimeout(60000 * 10);

    // Define REST method for prime number search.
    server.get('/next-prime/:n', (req, res, next) => {
      this.log.info(`Handling next-prime request for number ${req.params.n}`);

      this.primeFinder.sendAndReceive('nextPrime', parseInt(req.params.n))
        .then(result => {
          this.log.info(`Handled next-prime request for number ${req.params.n}, result: ${result}`);
          res.header('Content-Type', 'text/plain');
          res.send(200, result.toString());
        })
        .catch(err => {
          this.log.error(`Failed to handle next-prime request for number ${req.params.n}`, err);
          next(new restifyErrors.InternalError(err));
        });
    });

    return P.fromCallback(cb => {
      server.listen(8080, cb);
    });
  }
}

Что в нём происходит? Главное и единственное — в нём есть метод initialize(). Этот метод будет вызван Comedy при инициализации актора. В него передаётся экземпляр актора. Это та самая штука, в которую можно передавать сообщения. У экземпляра есть ещё ряд полезный методов. getLog() возвращает логгер для актора (он нам пригодится), а с помощью метода createChild() мы создаём дочерний актор — тот самый PrimeFinderActor, который мы реализовали в самом начале. В createChild() мы передаём определение актора, а получаем в ответ промис, который разрешится, как только дочерний актор будет проинициализирован, и выдаст нам экземпляр созданного дочернего актора.


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


Окей, мы создали дочерний PrimeFinderActor, дождались его инициализации и присвоили ссылку на экземпляр полю primeFinder. Осталась мелочёвка — сконфигурировать REST-сервер. Мы это делаем в методе _initializeServer() (он тоже асинхронный), используя библиотеку Restify.


Мы создаём один-единственный обработчик запроса ("ручку") — для метода GET /next-prime/:n, который вычисляет следующее за указанным целое число, отправляя сообщение дочернему PrimeFinderActor актору и получая от него ответ. Сообщение мы отправляем с помощью метода sendAndReceive(), первым параметром идёт название топика (nextPrime, по имени метода) следующим параметром — сообщение. В данном случае сообщением является просто число, но там может быть и строка, и объект с данными, и массив. Метод sendAndReceive() асинхронный, возвращает промис с результатом.


Почти готово. Нам осталась ещё одна мелочь: запустить всё это. Мы добавляем в наш пример ещё пару строк:


const actors = require('comedy');

actors({ root: RestServerActor });

Здесь мы создаём систему акторов. В качестве параметров мы указываем определение корневого (самого родительского) актора. Им у нас является RestServerActor.


Получается вот такая иерархия:


image


С иерархией нам повезло, она довольно простая!


Пример реальной иерархии

image


Ну что, запускаем приложение и тестируем?


$ nodejs prime-finder.js
Mon Aug 07 2017 15:34:37 GMT+0300 (MSK) - info: Resulting actor configuration: {}

$ curl http://localhost:8080/next-prime/30; echo
31

Работает! Давайте ещё поэкспериментируем:


$ time curl http://localhost:8080/next-prime/30
31
real    0m0.015s
user    0m0.004s
sys 0m0.000s
$ time curl http://localhost:8080/next-prime/3000000
3000017
real    0m0.045s
user    0m0.008s
sys 0m0.000s
$ time curl http://localhost:8080/next-prime/300000000
300000007
real    0m2.395s
user    0m0.004s
sys 0m0.004s
$ time curl http://localhost:8080/next-prime/3000000000
3000000019
real    5m11.817s
user    0m0.016s
sys 0m0.000s

По мере возрастания стартового числа время обработки запроса растёт. Особенно впечатляет переход с трёхсот миллионов до трёх миллиардов. Давайте попробуем параллельные запросы:


$ curl http://localhost:8080/next-prime/3000000000 &
[1] 32440
$ curl http://localhost:8080/next-prime/3000000000 &
[2] 32442

В top-е видим, что одно ядро полностью занято.


  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                                 
32401 weekens   20   0  955664  55588  20956 R 100,0  0,7   1:45.19 node    

В логе сервера видим:


Mon Aug 07 2017 16:05:45 GMT+0300 (MSK) - info: InMemoryActor(5988659a897e307e91fbc2a5, RestServerActor): Handling next-prime request for number 3000000000

То есть первый запрос выполняется, а второй просто ждёт.


$ jobs
[1]-  Выполняется  curl http://localhost:8080/next-prime/3000000000 &
[2]+  Выполняется  curl http://localhost:8080/next-prime/3000000000 &

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


Showtime!


Итак, настало время мастшабироваться. Все наши дальнейшие действия не потребуют модификации кода.


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


Мы создаём в корневой директории проекта файл actors.json вот с таким содержимым:


{
  "PrimeFinderActor": {
    "mode": "forked"
  }
}

И перезапускаем пример. Что произошло? Смотрим в список процессов:


$ ps ax | grep nodejs
12917 pts/19   Sl+    0:00 nodejs prime-finder.js
12927 pts/19   Sl+    0:00 /usr/bin/nodejs /home/weekens/workspace/comedy-examples/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor

$ pstree -a -p 12917
nodejs,12917 prime-finder.js
  +-nodejs,12927 /home/weekens/workspace/comedy-examples/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor
  |   +-{V8 WorkerThread},12928
  |   +-{V8 WorkerThread},12929
  |   +-{V8 WorkerThread},12930
  |   +-{V8 WorkerThread},12931
  |   +-{nodejs},12932
  +-{V8 WorkerThread},12918
  +-{V8 WorkerThread},12919
  +-{V8 WorkerThread},12920
  +-{V8 WorkerThread},12921
  +-{nodejs},12922
  +-{nodejs},12923
  +-{nodejs},12924
  +-{nodejs},12925
  +-{nodejs},12926

Мы видим, что процессов теперь два. Один — наш главный, "пусковой" процесс. Второй — дочерний процесс, в котором теперь крутится PrimeFinderActor, поскольку он теперь работает в режиме "forked". Мы это сконфигурировали с помощью файла actors.json, ничего не меняя в коде.


Получилась вот такая картина:


image


Запускаем тест снова:


$ curl http://localhost:8080/next-prime/3000000000 &
[1] 13240
$ curl http://localhost:8080/next-prime/3000000000 &
[2] 13242

Смотрим лог:


Tue Aug 08 2017 08:54:41 GMT+0300 (MSK) - info: InMemoryActor(5989504694b4a23275ba5d29, RestServerActor): Handling next-prime request for number 3000000000
Tue Aug 08 2017 08:54:43 GMT+0300 (MSK) - info: InMemoryActor(5989504694b4a23275ba5d29, RestServerActor): Handling next-prime request for number 3000000000

Хорошая новость: всё по-прежнему работает. Плохая новость: всё работает, почти как и раньше. Ядро по-прежнему не справляется, и запросы встают в очередь. Только теперь ядро нагружено нашим дочерним процессом (обратите внимание на PID):


  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                    
12927 weekens   20   0  907160  40892  20816 R 100,0  0,5   0:20.05 nodejs   

Давайте сделаем больше процессов: кластеризуем PrimeFinderActor до 4-х экземпляров. Меняем actors.json:


{
  "PrimeFinderActor": {
    "mode": "forked",
    "clusterSize": 4
  }
}

Перезапускаем сервис. Что видим?


$ ps ax | grep nodejs
15943 pts/19   Sl+    0:01 nodejs prime-finder.js
15953 pts/19   Sl+    0:00 /usr/bin/nodejs /home/weekens/workspace/comedy-examples/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor
15958 pts/19   Sl+    0:00 /usr/bin/nodejs /home/weekens/workspace/comedy-examples/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor
15963 pts/19   Sl+    0:00 /usr/bin/nodejs /home/weekens/workspace/comedy-examples/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor
15968 pts/19   Sl+    0:00 /usr/bin/nodejs /home/weekens/workspace/comedy-examples/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor

Дочерних процессов стало 4. Всё как мы и хотели. Простым изменением конфигурации мы поменяли иерархию, которая теперь выглядит так:


image


То есть Comedy размножил PrimeFinderActor до количества 4-х штук, каждый запустил в отдельном процессе, и между этими акторами и родительским RestServerActor-ом воткнул промежуточный актор, который будет раскидывать запросы по дочерним акторам раунд-робином.


Запускаем тест:


$ curl http://localhost:8080/next-prime/3000000000 &
[1] 20076
$ curl http://localhost:8080/next-prime/3000000000 &
[2] 20078

И видим, что теперь занято два ядра:


  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                    
15953 weekens   20   0  909096  38336  20980 R 100,0  0,5   0:13.52 nodejs                                                                     
15958 weekens   20   0  909004  38200  21044 R 100,0  0,5   0:12.75 nodejs   

В логе приложения видим два параллельно обрабатывающихся запроса:


Tue Aug 08 2017 11:51:51 GMT+0300 (MSK) - info: InMemoryActor(5989590ef554453e4798e965, RestServerActor): Handling next-prime request for number 3000000000
Tue Aug 08 2017 11:51:52 GMT+0300 (MSK) - info: InMemoryActor(5989590ef554453e4798e965, RestServerActor): Handling next-prime request for number 3000000000
Tue Aug 08 2017 11:57:24 GMT+0300 (MSK) - info: InMemoryActor(5989590ef554453e4798e965, RestServerActor): Handled next-prime request for number 3000000000, result: 3000000019
Tue Aug 08 2017 11:57:24 GMT+0300 (MSK) - info: InMemoryActor(5989590ef554453e4798e965, RestServerActor): Handled next-prime request for number 3000000000, result: 3000000019

Масштабирование работает!


Ещё больше ядер!


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


Вначале немного теории. В прошлом примере мы перевели PrimeFinderActor в режим "forked". Каждый актор может находиться в одном из трёх режимов:


  • "in-memory" (по-умолчанию): актор работает в том же процессе, что и создавший его код. Отправка сообщений такому актору сводится к вызову его методов. Накладные расходы на коммуникацию с "in-memory" актором нулевые (или близкие к нулевым);
  • "forked": актор запускается в отдельном процессе на той же машине, где работает создавший его код. Коммуникация с актором осуществляется через IPC (Unix pipes в Unix-е, named pipes в Windows).
  • "remote": актор запускается в отдельном процессе на удалённой машине. Коммуникация с актором осуществляется через TCP/IP.

Как вы поняли, теперь нам нужно перевести PrimeFinderActor из "forked" режима в "remote". Мы хотим получить такую схему:


image


Давайте отредактируем файл actors.json. Просто указать режим "remote" в данном случае недостаточно: нужно ещё указать хост, на котором мы хотим запустить актор. У меня есть по соседству машинка с адресом 192.168.1.101. Её я и использую:


{
  "PrimeFinderActor": {
    "mode": "remote",
    "host": "192.168.1.101",
    "clusterSize": 4
  }
}

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


$ ssh weekens@192.168.1.101
...
weekens@192.168.1.101 $ mkdir comedy
weekens@192.168.1.101 $ cd comedy
weekens@192.168.1.101 $ npm install comedy
...
weekens@192.168.1.101 $ node_modules/.bin/comedy-node
Thu Aug 10 2017 19:29:51 GMT+0300 (MSK) - info: Listening on :::6161

Теперь процесс-слушатель готов принимать запросы на создание акторов по известному порту 6161. Пробуем:


$ nodejs prime-finder.js

$ curl http://localhost:8080/next-prime/3000000000 &
$ curl http://localhost:8080/next-prime/3000000000 &

Смотрим top на локальной машине. Никакой активности (если не считать Chromium):


$ top

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                                 
25247 weekens   20   0 1978768 167464  51652 S  13,6  2,2  32:34.70 chromium-browse 

Смотрим на удалённой машине:


weekens@192.168.1.101 $ top

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                                 
27956 weekens   20   0  908612  40764  21072 R 100,1  0,1   0:14.97 nodejs                                                                                                                                  
27961 weekens   20   0  908612  40724  21020 R 100,1  0,1   0:11.59 nodejs   

Идёт вычисление целых чисел, всё как мы и хотели.


Остался лишь один маленький штрих: использовать ядра и на локальной, и на удалённой машине. Это очень просто: мы указываем в actors.json не один хост, а несколько:


{
  "PrimeFinderActor": {
    "mode": "remote",
    "host": ["127.0.0.1", "192.168.1.101"],
    "clusterSize": 4
  }
}

Comedy распределит акторы равномерно между указанными хостами и будет раздавать им сообщения round robin-ом. Давайте проверим.


Сперва запустим процесс слушатель дополнительно на локальной машине:


$ node_modules/.bin/comedy-node
Fri Aug 11 2017 15:37:26 GMT+0300 (MSK) - info: Listening on :::6161

Теперь запустим пример:


$ nodejs prime-finder.js

Посмотрим список процессов на локальной машине:


$ ps ax | grep nodejs
22869 pts/19   Sl+    0:00 /usr/bin/nodejs /home/weekens/workspace/comedy-examples/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor
22874 pts/19   Sl+    0:00 /usr/bin/nodejs /home/weekens/workspace/comedy-examples/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor

И на удалённой машине:


192.168.1.101 $ ps ax | grep node
5925 pts/4    Sl+    0:00 /usr/bin/nodejs /home/weekens/comedy/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor
 5930 pts/4    Sl+    0:00 /usr/bin/nodejs /home/weekens/comedy/node_modules/comedy/lib/forked-actor-worker.js PrimeFinderActor

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


$ curl http://localhost:8080/next-prime/3000000000 &
[1] 23000
$ curl http://localhost:8080/next-prime/3000000000 &
[2] 23002

Смотрим загрузку на локальной машине:


  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                                 
22869 weekens   20   0  908080  40344  21724 R 106,7  0,5   0:07.40 nodejs     

Смотрим загрузку на удалённой машине:


  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                                 
 5925 weekens   20   0  909000  40912  21044 R 100,2  0,1   0:14.17 nodejs     

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


Заключение


Мы рассмотрели пример гибкого масштабирования приложения с помощью модели акторов и её реализации в Node.JS — Comedy. Алгоритм наших действий выглядел следующим образом:


  1. Описать наше приложение в терминах акторов.
  2. Сконфигурировать акторы таким образом, чтобы равномерно распределить нагрузку по множеству доступных нам ядер CPU.

Как описывать приложение в терминах акторов? Это аналог вопроса "Как описать приложение в терминах объектов и классов?". Программирование на акторах очень похоже на ООП. Можно сказать, что это ООП++. В ООП есть различные устоявшиеся и успешные паттерны проектирования. Аналогичным образом, и для модели акторов есть свои паттерны. Вот книга по ним. Эти паттерны можно использовать, и они вам наверняка помогут, но, если вы уже владеете ООП, у вас точно не будет с акторами проблем.


Что если ваше приложение уже написано? Нужно ли "переписывать его на акторы"? Конечно, модификация кода в этом случае потребуется. Но не обязательно делать масштабный рефакторинг. Можно выделить несколько основных, "крупных" акторов, и после этого вы уже можете масштабироваться. "Крупные" акторы можно со временем раздробить на более мелкие. Опять же, если ваше приложение уже описано в терминах ООП, переход на акторы будет, скорее всего, безболезненным. Единственный момент, с которым, возможно, придётся поработать: акторы полностью изолированы друг от друга, в отличие от простых объектов.


Насчёт зрелости фреймворка. Первая рабочая версия Comedy была разработана внутри проекта SAYMON в июне 2016 года. Фреймворк с самой первой версии работал в продакшене в боевых условиях. В апреле 2017 года библиотека была выпущена в Open Source под Eclipse Public License. Comedy при этом продолжает быть частью SAYMON и используется для масштабирования системы и обеспечения её отказоустойчивости.


Список планируемых фич здесь.


В этой статье я не упомянул о целом ряде функциональный возможностей Comedy: о fault tolerance ("respawn" акторов), об инъекции ресурсов в акторы, об именованных кластерах, о маршаллинге пользовательских классов, о поддержке TypeScript. Но большую часть вышеперечисленного вы найдёте в документации, а то, что в ней ещё не описано — в тестах и примерах. Плюс, возможно, я напишу ещё статьи о Comedy и акторах в Node.JS, если тема пойдёт в массы.


Используйте Comedy! Создавайте issues! Жду ваших комментариев!

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

https://habrahabr.ru/post/334986/


Метки:  

[Перевод] Как на самом деле работает планировщик Kubernetes?

Понедельник, 14 Августа 2017 г. 09:27 + в цитатник
Прим. перев.: Эта статья написана Julia Evans — инженером международной компании Stripe, специализирующейся на интернет-платежах. Разбираться во внутренностях работы планировщика Kubernetes её побудил периодически возникающий баг с «зависанием» пода, о котором около месяца назад также сообщили специалисты из Rancher Labs (issue 49314). Проблема была решена и позволила поделиться деталями о техническом устройстве одного из базовых механизмов Kubernetes, которые и представлены в этом статье с необходимыми выдержками из соответствующего кода проекта.



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

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

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

Для чего планировщик?


Планировщик Kubernetes отвечает за назначение узлов подам (pods). Суть его работы сводится к следующему:
  • Вы создаёте под.
  • Планировщик замечает, что у нового пода нет назначенного ему узла.
  • Планировщик назначает поду узел.

Он не отвечает за реальный запуск пода — это уже работа kubelet. Всё, что от него в принципе требуется, — гарантировать, что каждому поду назначен узел. Просто, не так ли?

В Kubernetes применяется идея контроллера. Работа контроллера заключается в следующем:
  • посмотреть на состояние системы;
  • заметить, где актуальное состояние не соответствует желаемому (например, «этому поду должен быть назначен узел»);
  • повторить.

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

В общем виде работу планировщика можно представить как такой цикл:
while True:
    pods = get_all_pods()
    for pod in pods:
        if pod.node == nil:
            assignNode(pod)

Если вас не интересуют детали о том, как же работает планировщик в Kubernetes, возможно, на этом читать статью достаточно, т.к. этот цикл заключает в себе вполне корректную модель.

Вот и мне казалось, что планировщик на самом деле работает подобным образом, потому что так работает и контроллер cronjob — единственный компонент Kubernetes, код которого был мною прочитан. Контроллер cronjob перебирает все cron-задания, проверяет, что ни для одного из них не надо ничего делать, ожидает 10 секунд и бесконечно повторяет этот цикл. Очень просто!

Однако работает всё не совсем так


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

Иногда под навсегда «застревал» в состоянии Pending (когда узел не назначен на под). При перезагрузке планировщика под выходил из этого состояния (вот тикет).

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

Пришло время обратиться к коду. И вот что мне удалось выяснить — как всегда, возможно, что здесь есть ошибки, т.к. всё довольно сложно, а на изучение ушла только неделя.

Как работает планировщик: беглый осмотр кода


Начнём с scheduler.go. (Объединение всех нужных файлов доступно здесь — для удобства навигации по содержимому.)

Основной цикл планировщика (на момент коммита e4551d50e5) выглядит так:
go wait.Until(sched.scheduleOne, 0, sched.config.StopEverything)

… что означает: «Вечно запускай sched.scheduleOne». А что происходит там?
func (sched *Scheduler) scheduleOne() {
	pod := sched.config.NextPod()
    // do all the scheduler stuff for `pod`
}

Окей, а что делает NextPod()? Откуда растут ноги?
func (f *ConfigFactory) getNextPod() *v1.Pod {
	for {
		pod := cache.Pop(f.podQueue).(*v1.Pod)
		if f.ResponsibleForPod(pod) {
			glog.V(4).Infof("About to try and schedule pod %v", pod.Name)
			return pod
		}
	}
}

Окей, всё достаточно просто! Есть очередь из подов (podQueue), и следующие поды приходят из неё.

Но как поды попадают в эту очередь? Вот соответствующий код:
podInformer.Informer().AddEventHandler(
	cache.FilteringResourceEventHandler{
		Handler: cache.ResourceEventHandlerFuncs{
			AddFunc: func(obj interface{}) {
				if err := c.podQueue.Add(obj); err != nil {
					runtime.HandleError(fmt.Errorf("unable to queue %T: %v", obj, err))
				}
			},

То есть существует обработчик события, который при добавлении нового пода добавляет его в очередь.

Как работает планировщик: простым языком


Теперь, когда мы прошлись по коду, можно подвести итог:
  1. В самом начале каждый под, которому потребуется планировщик, помещается в очередь.
  2. Когда создаются новые поды, они тоже добавляются в очередь.
  3. Планировщик постоянно берёт поды из очереди и осуществляет для них планирование.
  4. Вот и всё!

Здесь есть интересная деталь: если по какой-либо причине под не попадает к планировщику, планировщик не станет предпринимать повторную попытку для него. Под будет убран из очереди, его планирование не выполнится, и всё на этом. Единственный шанс будет упущен! (Пока вы не перезапустите планировщик, в случае чего все поды снова будут добавлены в очередь.)

Конечно, в действительности планировщик умнее: если под не попал к планировщику, в общем случае вызывается обработчик ошибки вроде этого:
host, err := sched.config.Algorithm.Schedule(pod, sched.config.NodeLister)
if err != nil {
	glog.V(1).Infof("Failed to schedule pod: %v/%v", pod.Namespace, pod.Name)
	sched.config.Error(pod, err)

Вызов функции sched.config.Error снова добавляет под в очередь, поэтому для него всё-таки будет предпринята повторная попытка обработки.

Подождите. Почему же тогда «застрял» наш под?


Всё очень просто: оказалось, что эта функция Error не всегда вызывалась, когда реально происходила ошибка. Мы сделали патч (патч был опубликован в том же issueприм. перев.), чтобы вызывать её корректно, после чего восстановление стало происходить правильно. Класс!

Почему планировщик спроектирован так?


Думаю, что более надёжная архитектура выглядит следующим образом:
while True:
    pods = get_all_pods()
    for pod in pods:
        if pod.node == nil:
            assignNode(pod)

Так почему же вместо такого подхода мы видим все эти сложности с кэшами, запросами, обратными вызовами? Глядя на историю, приходишь к мнению, что основная причина — в производительности. Примеры — это обновление о масштабируемости в Kubernetes 1.6 и эта публикация CoreOS об улучшении производительности планировщика Kubernetes. В последней говорится о сокращении времени планирования для 30 тысяч подов (на 1 тысяче узлов — прим. перев.) с 2+ часов до менее 10 минут. 2 часа — это довольно долго, а производительность важна!

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

Что на самом деле использует планировщик: informers в Kubernetes


Хочу сказать ещё об одном моменте, который кажется очень важным для архитектуры всех контроллеров Kubernetes. Это идея «информаторов» (informers). К счастью, есть документация, которая находится гуглением «kubernetes informer».

Этот крайне полезный документ называется Writing Controllers и рассказывает о дизайне для тех, кто пишет свой контроллер (вроде планировщика или упомянутого контроллера cronjob). Очень здорово!

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

Итак, информаторы! Вот что говорит документация:

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

Когда контроллер запускается, он создаёт informer (например, pod informer), который отвечает за:
  1. вывод всех подов (в первую очередь);
  2. уведомления об изменениях.

Контроллер cronjob не использует информаторов (работа с ними всё усложняет, а в данном случае, думаю, ещё не стоит вопрос производительности), однако многие другие (большинство?) — используют. В частности, планировщик так делает. Настройку его информаторов можно найти в этом коде.

Повторное помещение в очередь


В той же документации (Writing Controllers) есть и инструкции по тому, как обрабатывать повторное помещение элементов в очередь:
Для надёжного повторного помещения в очередь выносите ошибки на верхний уровень. Для простой реализации с разумным откатом есть workqueue.RateLimitingInterface.

Главная функция контроллера должна возвращать ошибку, когда необходимо повторное помещение в очередь. Когда его нет, используйте utilruntime.HandleError и возвращайте nil. Это значительно упрощает изучение случаев обработки ошибок и гарантирует, что контроллер ничего не потеряет, когда это необходимо.

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

Необходимо «синхронизировать» своих информаторов (не так ли?)


И последняя интересная деталь за время моего расследования.

У informers используется концепция «синхронизации» (sync). Она немного похожа на рестарт программы: вы получаете список всех ресурсов, за которыми наблюдаете, поэтому можете проверить, что всё действительно в порядке. Вот что то же руководство говорит о синхронизации:
Watches и Informers будут «синхронизироваться». Периодически они доставляют вашему методу Update каждый подходящий объект в кластере. Хорошо для случаев, когда может потребоваться выполнить дополнительное действие с объектом, хотя это может быть нужно и не всегда.

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

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

Планировщик Kubernetes не синхронизируется повторно


Итак, после знакомства с концепцией синхронизации… приходишь к выводу, что, похоже, планировщик Kubernetes никогда её не выполняет? В этом коде всё выглядит именно так:
informerFactory := informers.NewSharedInformerFactory(kubecli, 0)
// cache only non-terminal pods
podInformer := factory.NewPodInformer(kubecli, 0)

Эти числа «0» означают «период повторной синхронизации» (resync period), что логично интерпретировать как «ресинхронизация не происходит». Интересно! Почему так сделано? Не имея уверенности на сей счёт и прогуглив «kubernetes scheduler resync», удалось найти pull request #16840 (добавляющий resync для планировщика) с двумя следующими комментариями:
@brendandburns — что здесь планируется исправить? Я действительно против таких маленьких периодов повторной синхронизации, потому что они значительно скажутся на производительности.

Согласен с @wojtek-t. Если resync вообще когда-либо и может решить проблему, это означает, что где-то в коде есть баг, который мы пытаемся спрятать. Не думаю, что resync — правильное решение.

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

Советы по чтению кода


Насколько мне известно, нигде не описана реальная работа планировщика Kubernetes изнутри (как и многие другие вещи!).

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

Работать с Kubernetes довольно-таки здорово!


Kubernetes — по-настоящему сложное программное обеспечение. Даже для того, чтобы получить работающий кластер, потребуется настроить как минимум 6 различных компонентов: api server, scheduler, controller manager, container networking вроде flannel, kube-proxy, kubelet. Поэтому (если вы хотите понимать программное обеспечение, которое запускаете, как и я) необходимо понимать, что все эти компоненты делают, как они взаимодействуют друг с другом и как настроить каждую из их 50 триллионов возможностей для получения того, что требуется.

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

Мне пришлось по-настоящему и более обычного практиковать принцип «читай документацию и, если её нет, то читай код». Но в любом случае это отличный навык, чтобы стать лучше!

P.S. от переводчика: читайте также в нашем блоге:
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335552/


Метки:  

Pygest #15. Релизы, статьи, интересные проекты из мира Python [01 августа 2017 — 14 августа 2017]

Понедельник, 14 Августа 2017 г. 07:46 + в цитатник
image Всем привет! Это уже пятнадцатый выпуск дайджеста на Хабрахабр о новостях из мира Python.

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

А теперь к делу!


Релизы


Python 3.5.4
Python 3.4.7
Django 1.11.4
PyTorch 0.2.0

Статьи


OpenDataScience и Mail.Ru Group проведут открытый курс по машинному обучению

Reverse engineer a Python object
О внутренностях объектов в Python.

Python decorators, the right way: the 4 audiences of programming languages
Интересная заметка о декораторах в Python.

The Hitchhiker’s Guide to Machine Learning in Python
Отличный вводный туториал и подборка материалов по машинному обучению для начинающих.

Clean Architecture in Django
Небольшая заметка о чистой архитектуре в Django-приложениях.

A Minimal Django Application
Туториал для начинающих работать с Django — как создать минимальное приложение на данном фреймворке.

Python __init__.py & modular Imports
О работе импорта модулей в Python.

Using K-Means to analyse hacking attacks
Статья об использовании алгоритма «к-средних» для анализа хакерских атак.

Python bytecode reverse-engineering
Крутая статья о реверс-инжениринге байт-кода Python.

Controlling Python Async Creep
Заметка о контролировании асинхронного выполнения кода в Python.

Demystifying Dynamic Programming
О том, что такое динамическое программирование с примерами на Python от freeCodeCamp.

Detecting fake banknotes using TensorFlow
Статья об использовании машинного обучения и TensorFlow для обнаружения фальшивых денег.

Building a Music Recommender with Deep Learning
Как создать свой сервис для рекомендации музыки?

Интересные проекты


Pygorithm
Библиотека для изучения алгоритмов «на лету»

tinychain
«Карманная» реализация Bitcoin

Aptos
Инструмент для валидации данных на основе JSON-схем

Domain Analyzer
Инструмент для анализа безопасности домена на основе всей доступной информации о нём

sandsifter
Инструмент для поиска скрытых инструкций и багов в процессорах x86

Видео


PyCon Australia 2017
Видео с конференции PyCon Australia 2017

Предыдущий выпуск дайджеста ищете здесь:

Pygest #14. Релизы, статьи, интересные проекты из мира Python [18 июля 2017 — 31 июля 2017]

Спасибо за внимание! Присылайте Ваши предложения для публикации в дайджесте!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335538/


Метки:  

Как распознать scam ICO? Часть II. Зрим

Понедельник, 14 Августа 2017 г. 05:28 + в цитатник
Прежде чем начать, хотелось бы сделать две ремарки:

  1. Мне хорошо известна целевая аудитория Хабра и, возможно, поэтому для неё данный материал будет не просто понятен, но и прост. Но с другой стороны, именно вы, жители одного из самого большого it-сообщества в СНГ, сможете всегда дать своим знакомым или просто встретившимся в Сети людям этот материал, чтобы наконец-то избежать очередного, искусственного пузыря.
  2. Второй аспект заключается в том, что понимание и систематизированное знание — две качественно разные категории, поэтому мне, в рамках развития единой репутационной системы (о ней — как-нибудь в следующий раз), хотелось бы начать структурировать то, что известно.



Scam — это обман

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

И вот об этом поподробней.

Скам — это мошенничество: опять же, простой запрос «scam+history» преподнесет большой список из разного рода сервисов, которые тем или иным образом решили сыграть на доверии, глупости или неосторожности пользователей. Сферы будут самыми разными: от энергетики до банковского сектора. Что касается сферы ICO, несмотря на молодость, существует она с 2013 года, в ней хватает скамов.

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

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

Во-вторых, по сложности:

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

В-третьих, по субъективной стороне, как говорят юристы:

  • Когда создатели изначально не хотят ничего, кроме сбора средств;
  • Встречаются случаи, когда создатели по тем или иным причинам приходят к скаму уже в результате ICO или работы проекта (пожалуй, один из ярчайших примеров — MtGox, а сегодня таким может стать EOS).

В первом случае мошенники сознательно делают всё, чтобы получить побольше и исчезнуть побыстрее. Во втором возможные потери «вкладчиков» связаны с безволием создателя (режим «всё надоело!»), с ссорой внутри команды (в сети можете найти один из аналогов storj & filecoin на эту тему), с банальной жадностью, которая, как известно, приходит во время еды — получения крипто-активов.

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

  1. Team — команда;
  2. Tech — технология;
  3. Theme — концепция;
  4. Token — правовой статус реализуемых крипто-активов.

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

Команду всегда нужно проверять на истинность взаимосвязей, то есть искать не просто профиль в facebook, linkedin, но выходить на людей, которые так или иначе где-то реально засвечены. Дело в том, что в онлайн-среде наверняка должны найтись персоны, которые часто сидят в социальных сетях, имеют устойчивые группы общения и вполне открыто обсуждают свою жизнь. Если таковых нет — это очень странно. Конечно, бывают группы, где люди собираются именно потому, что они интроверты, но если из всего сонма знакомых каждого из команды нет ни одного с развёрнутой историей — это должно вызывать подозрения. Теория 6 рукопожатий в этом смысле работает: не обязательно зацикливаться на самой цифре: главное, чтобы участники были связаны с реальным миром:

  • В первую очередь нужно проверять связи с адвизорами — у них репутация стоит денег и поэтому не нужно лениться писать и звонить, дабы подтвердить/опровергнуть информацию о проекте, где они участвуют.
  • Далее юридическое лицо: регистрация, местонахождение (онлайн-карты вам в подарок); если речь идёт о preICO то можно даже проверить почтовый адрес отправкой приветственного письма на бумаге (по крайне мере, дважды я так делал и чутьё меня не подвело). Ассоциации и другие объединения, где должно состоять данное юридическое лицо. Недавно, например, с командой проверял COSS и из 7 запросов получили 7 ответов, подтверждающих, что данное объединение действительно является участником ряда предпринимательских сообществ (см. пример ниже).
  • Есть ещё один момент, который часто приходится использовать в повседневной практике: поиск по номеру телефона или email. Конечно, найти личный адрес кого-то из команды не всегда просто, а телефон может быть создан под специальный проект. Но вероятность нахождения этих данных не так мала. Скажем, до 1/3 проектов так или иначе подобные данные в конце-концов раскрывали. Зачем это нужно? Дело в том, что всё имеет свойство индексироваться. Поэтому старые аккаунты в социальных сетях, на досках объявлений и во множестве других потаённых уголков Кибервселенной часто могут сказать о человеке больше, чем тысячи букв, написанных во славу.



Технологию оценить очень сложно, если вы не специалист. Правда, однажды мне помог банальный поиск исходника, который совпал со скриптом другого проекта почти на 100%. Хорошо, что Интернет создан именно как коллективный разум: задать вопрос на профильном форуме, сайте вопросов или чате (в телеграм, скажем, таких сейчас хватает) может каждый. Сделайте связку между первым и вторым «Т»: какой-нибудь банальный запрос в slack/telegram разработчикам и команде поддержки проекта, в который хотите вложиться: буквально на днях в чате https://t.me/bitfund появился «коэффициент глухоты» (по фамилии фаундера, который не ответил ни на один вопрос, но об этом ещё будет материал, скажу пока лишь, что в клиентах у него был даже Apple, который просил разработать маркетинговую стратегию). Фидбэк от мошенников и не- мошенников абсолютно разный. Мошенники не отвечают вовсе или отвечают предельно размыто на прямые вопросы. Исключения бывают, безусловно, но это уже иной уровень подготовки. К слову, вот небольшой перечень каналов, где можно задать вопрос:

  1. http://toster.ru: не удивляйтесь, т.к. Хабро-сообщество часто помогает обрисовать рамки;
  2. https://t.me/bitfund — хороший чат со специалистами и инвесторами ICO и оценке блокчейн-проектов в целом
  3. https://t.me/ICO_law — чат не такой большой, как предыдущий, но зато здесь очень много полезных ссылок и материалов для начинающих.

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

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

  • Берём Белую книгу и Дорожную карту. В первой написано: «запуск первой стадии состоится не ранее 3 марта 2018 года», Открываем Roadmap и видим: «завершение первой стадии: апрель 2018 года». Срок реализации стадии — 3 месяца. В этом смысле мне не очень нравится подход ZrCoin: «сроки окончания строительства и запуска первой линии производства намечены на весну 2018 г.». Посмотрим, но пока они выглядят завышенными.
  • А теперь давайте взглянем на развитие концепта: сколько времени прошло от момента его появления на свет до первой реализации или хотя бы описания? А сколько дней, недель, месяцев между этой самой реализацией и ICO? Вот здесь можно найти хороший пример для тренировки подобных навыков https://icotracker.net/project/skyway.
  • И самый главный вопрос: как блокчейн-проект победит, говоря условно, в гонке с классическими it? Скажем, как могут победить SONM & Golem команды, которые занимаются тем же самым, но не первый год? Это вопрос сомнения. А вот для скама вопрос стоит проще и жёстче: а вообще такая реализация есть в классическом бизнесе? Нет? Тогда почему?

В этом плане мне понравился подход команды Kickico, которая пытается унифицировать изучение проектов ДО их запуска, а не после.

Токен. Наконец-то, после SEC & MAS, люди стали понимать, что выпускать не ясно что, не понятно для кого — не просто странно, но и опасно. В итоге, если видим, что токены созданы по системе «купи дешевле — продай подороже» и за ними не стоит ничего иного: бонусов, доли участия, обратных выкупов и так далее, то это ещё один повод задуматься над ТЭО (технико-экономическое обоснование) и его адекватностью. Вот ещё несколько нюансов по теме:

  1. Есть ли соглашение о распределении токенов?
  2. Как вообще обозначен токен в разных документах: Дорожной карте, Белой книге, публичной оферте и т.д.?
  3. В этом видео вы найдёте не премер скама, а скорее пункта, который среди прочих, выглядит подозрительно: когда в White Paper написано об обратном выкупе, а документах сугубо юридических — нет. Уловка или недомолвка? Зависит от других направлений, но, как минимум, повод изучить проект подробней
  4. Сколько токенов эмитировано и какова их экономика? Скажем, чтобы поддерживать рост и ликвидность ETH необходим ежедневный оборот в 5 000 000 долларов и более. Если его нет, то идёт падение. В этом смысле EHT инфляционный токен, а btc — дефляционный. Стейблкоины же пока только на этапе становления. Зачем это знать? Затем, что Концепт должен учитывать экономическую сущность токена и исходить в показателях роста. Сегодня это делают далеко не все проекты даже из белого списка — это ещё один повод задуматься о возможности участия в них.

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

В России и странах СНГ в основном приоритет за анализом техническим. Давайте же и мы тоже не будем обходить его стороной.

Скажем, тот же . Здесь можно найти интересную информацию об одном из самых подозрительных среди последних. Кроме ICOtracker, есть и ещё ряд подобных проектов: ICOrating, где есть специальная вкладка с одноимённой закладкой, icostats и ряд других. На Golos Ден Иванов делал подборку по этому поводу — к нему и адресую.

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



Данный подход был создан Алексом Контегна (Alex Kontegna). Автор объясняет данную структуру оценки ICO следующим образом: «наша карта делит пространство на матрицу с девятью слотами: в положительных (зелёных) и отрицательных (красных) полях, определенными на разных пересечениях. Хорошее применение этой матрицы — измерение параметра риска вашего портфолио (ICO-токенов), если вы владеете несколькими монетами».

К матрице прилагаются следующие простые правила:

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

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

Скажем, регистрация домена. Если проект разрабатывался, то у него должна быть, пусть и небольшая, но история. И поэтому домен, которому от роду 1-3 месяца, даже полгода — выглядит странным (если только нет аффилированного с ним). Всегда импонирует открытость данных даже там, где делать этого не обязательно — вот всё тот же пример из последних наблюдений https://who.is/whois/coss.io. При этом: если компания заявляет некую историю по старым проектам, которые даже уже закрыты, то эти сведения можно проверить:

  1. http://web-arhive.ru/ — смотрим, то, что было до прихода ICO с проектами
  2. каталоги (раньше был DMOZ, сейчас это Яндекс и местные каталоги сайтов)
  3. обратные ссылки: когда удаляется сайт далеко не все удаляют ссылки на него, а таких может быть много: партнёры, новостные сайты, форумы
  4. есть ещё более мелкие детали: даты в sitemap старых сайтов или элементы seo-оптимизации на страницах (мошенники обычно на этом не заморачиваются, поскольку делают проекты на коленке и предельно быстро).

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

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

https://matchpool.co — социальная сеть, завязанная на блокчейне. Случилось с ней следующее (по данным Forbes): «В начале апреля 2017 года его создатели с помощью ICO получили $5,8 миллионов. Но уже через пару дней компанию покинул технический директор, которого заподозрили в незаконном выводе средств». Аналогичные истории случались и в других стартапах.

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

  1. Есть мультиподпись;
  2. Формируется некий стабфонд, который будет использован в каких-то неприятных ситуациях (случай с тем же Satoshi Fond);
  3. Существуют смарт-контракты на возврат сумм при определённых ситуациях (не прохождении нижнего порога ICO, форс-мажор и т.п.). Почитать о примерах можно в книге.

В заключение хотелось бы выделить следующие аспекты:

Прежде, чем рваться в бой, обратите внимание на уже существующие scam’ы — изучите, проанализируйте, сделайте обобщающие выводы:

  1. https://nodio.net/ — 2016 год, Украина; сайт не работает.
  2. https://www.ebitz.org/ — 2016 год, Анонимно; сайт работает номинально.
  3. http://www.tithecoin.com/ — 2016 год, США; сайт работает.
  4. https://ascendancy.io/#/ — 2016, Не выяснено; сайт не работает.

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

Нужно понимать, что ICO — начинающий, а значит высокорискованный бизнес. Тем более в рамках последних заявлений SEC & MAS.

Чтобы найти скам нужны не какие-то сверх-методики, машинное обучение и работа с большими данными (хотя это, безусловно, пригодилось бы каждому), а усердие, внимание к деталям и затраченное пропорционально вложениям время на исследование ICO-проектов. Нет времени тратить силы на это? Или не заходите вообще в проекты, или обратитесь хотя бы к тому же https://www.kickico.com/ru/ — ребята, по крайне мере, стараются.

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

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

  1. Сервис для вас лично должен быть понятен в принципах работы и близок по целям;
  2. Спекулятивная составляющая не должна быть единственной (в этом плане Мавро — как раз пример обратного);
  3. И, наконец, безопасно вкладывать можно только те доходы, которые идут свыше ваших личных расходов, о какой бы конкретной сумме ни шла речь.

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

  • По критерию восприятия: положительно или отрицательно;
  • По уровню восприятия: сложно или просто;
  • По бальной шкале:
    Десятибалльная — одна из самых простых и понятных: всё, что ниже нуля — ближе к скаму; всё, что выше — дальше от скама;
    Стобалльная. Если в вашем личном наборе оценок сто и более элементов: подход хорош для полуавтоматической оценки;
    Также можно использовать смешанную систему: скажем отрицательным факторам присваивать до 10 баллов в минус, а положительным, соответственно, в плюс. Каждый проект изначально берём за 100% и далее начинаем разбор: если итоговая оценка ниже 33-66%, то это подозрение на скам, 66-75% — норма, далее уже хорошие и отличные проекты.
  • По иным критериям, например, используя систему оценку ценных бумаг или же применяя подход эмоциональной окраски (негативно, нейтрально-негативно, нейтрально, нейтрально-положительно, положительно).

Таким образом, систему выявления скамов можно выстроить, но единственное, что всегда остаётся за скобками — это наша общечеловеческая жадность: если она свойственна вам в критичные моменты, то моя лично позиция проста: «ICO не для вас».

В завершении — небольшая подборка для расширения понимания темы:

  1. Книга об ICO. Часть 1.
  2. Книга об ICO. Часть 2.
  3. Общие вопросы ICO
  4. ICO и легализация средств
  5. ICO: основные риски
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335548/


Метки:  

Как распознать scam ICO? Часть II. Зрим

Понедельник, 14 Августа 2017 г. 05:28 + в цитатник
Прежде чем начать, хотелось бы сделать две ремарки:

  1. Мне хорошо известна целевая аудитория Хабра и, возможно, поэтому для неё данный материал будет не просто понятен, но и прост. Но с другой стороны, именно вы, жители одного из самого большого it-сообщества в СНГ, сможете всегда дать своим знакомым или просто встретившимся в Сети людям этот материал, чтобы наконец-то избежать очередного, искусственного пузыря.
  2. Второй аспект заключается в том, что понимание и систематизированное знание — две качественно разные категории, поэтому мне, в рамках развития единой репутационной системы (о ней — как-нибудь в следующий раз), хотелось бы начать структурировать то, что известно.



Scam — это обман

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

И вот об этом поподробней.

Скам — это мошенничество: опять же, простой запрос «scam+history» преподнесет большой список из разного рода сервисов, которые тем или иным образом решили сыграть на доверии, глупости или неосторожности пользователей. Сферы будут самыми разными: от энергетики до банковского сектора. Что касается сферы ICO, несмотря на молодость, существует она с 2013 года, в ней хватает скамов.

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

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

Во-вторых, по сложности:

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

В-третьих, по субъективной стороне, как говорят юристы:

  • Когда создатели изначально не хотят ничего, кроме сбора средств;
  • Встречаются случаи, когда создатели по тем или иным причинам приходят к скаму уже в результате ICO или работы проекта (пожалуй, один из ярчайших примеров — MtGox, а сегодня таким может стать EOS).

В первом случае мошенники сознательно делают всё, чтобы получить побольше и исчезнуть побыстрее. Во втором возможные потери «вкладчиков» связаны с безволием создателя (режим «всё надоело!»), с ссорой внутри команды (в сети можете найти один из аналогов storj & filecoin на эту тему), с банальной жадностью, которая, как известно, приходит во время еды — получения крипто-активов.

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

  1. Team — команда;
  2. Tech — технология;
  3. Theme — концепция;
  4. Token — правовой статус реализуемых крипто-активов.

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

Команду всегда нужно проверять на истинность взаимосвязей, то есть искать не просто профиль в facebook, linkedin, но выходить на людей, которые так или иначе где-то реально засвечены. Дело в том, что в онлайн-среде наверняка должны найтись персоны, которые часто сидят в социальных сетях, имеют устойчивые группы общения и вполне открыто обсуждают свою жизнь. Если таковых нет — это очень странно. Конечно, бывают группы, где люди собираются именно потому, что они интроверты, но если из всего сонма знакомых каждого из команды нет ни одного с развёрнутой историей — это должно вызывать подозрения. Теория 6 рукопожатий в этом смысле работает: не обязательно зацикливаться на самой цифре: главное, чтобы участники были связаны с реальным миром:

  • В первую очередь нужно проверять связи с адвизорами — у них репутация стоит денег и поэтому не нужно лениться писать и звонить, дабы подтвердить/опровергнуть информацию о проекте, где они участвуют.
  • Далее юридическое лицо: регистрация, местонахождение (онлайн-карты вам в подарок); если речь идёт о preICO то можно даже проверить почтовый адрес отправкой приветственного письма на бумаге (по крайне мере, дважды я так делал и чутьё меня не подвело). Ассоциации и другие объединения, где должно состоять данное юридическое лицо. Недавно, например, с командой проверял COSS и из 7 запросов получили 7 ответов, подтверждающих, что данное объединение действительно является участником ряда предпринимательских сообществ (см. пример ниже).
  • Есть ещё один момент, который часто приходится использовать в повседневной практике: поиск по номеру телефона или email. Конечно, найти личный адрес кого-то из команды не всегда просто, а телефон может быть создан под специальный проект. Но вероятность нахождения этих данных не так мала. Скажем, до 1/3 проектов так или иначе подобные данные в конце-концов раскрывали. Зачем это нужно? Дело в том, что всё имеет свойство индексироваться. Поэтому старые аккаунты в социальных сетях, на досках объявлений и во множестве других потаённых уголков Кибервселенной часто могут сказать о человеке больше, чем тысячи букв, написанных во славу.



Технологию оценить очень сложно, если вы не специалист. Правда, однажды мне помог банальный поиск исходника, который совпал со скриптом другого проекта почти на 100%. Хорошо, что Интернет создан именно как коллективный разум: задать вопрос на профильном форуме, сайте вопросов или чате (в телеграм, скажем, таких сейчас хватает) может каждый. Сделайте связку между первым и вторым «Т»: какой-нибудь банальный запрос в slack/telegram разработчикам и команде поддержки проекта, в который хотите вложиться: буквально на днях в чате https://t.me/bitfund появился «коэффициент глухоты» (по фамилии фаундера, который не ответил ни на один вопрос, но об этом ещё будет материал, скажу пока лишь, что в клиентах у него был даже Apple, который просил разработать маркетинговую стратегию). Фидбэк от мошенников и не- мошенников абсолютно разный. Мошенники не отвечают вовсе или отвечают предельно размыто на прямые вопросы. Исключения бывают, безусловно, но это уже иной уровень подготовки. К слову, вот небольшой перечень каналов, где можно задать вопрос:

  1. http://toster.ru: не удивляйтесь, т.к. Хабро-сообщество часто помогает обрисовать рамки;
  2. https://t.me/bitfund — хороший чат со специалистами и инвесторами ICO и оценке блокчейн-проектов в целом
  3. https://t.me/ICO_law — чат не такой большой, как предыдущий, но зато здесь очень много полезных ссылок и материалов для начинающих.

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

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

  • Берём Белую книгу и Дорожную карту. В первой написано: «запуск первой стадии состоится не ранее 3 марта 2018 года», Открываем Roadmap и видим: «завершение первой стадии: апрель 2018 года». Срок реализации стадии — 3 месяца. В этом смысле мне не очень нравится подход ZrCoin: «сроки окончания строительства и запуска первой линии производства намечены на весну 2018 г.». Посмотрим, но пока они выглядят завышенными.
  • А теперь давайте взглянем на развитие концепта: сколько времени прошло от момента его появления на свет до первой реализации или хотя бы описания? А сколько дней, недель, месяцев между этой самой реализацией и ICO? Вот здесь можно найти хороший пример для тренировки подобных навыков https://icotracker.net/project/skyway.
  • И самый главный вопрос: как блокчейн-проект победит, говоря условно, в гонке с классическими it? Скажем, как могут победить SONM & Golem команды, которые занимаются тем же самым, но не первый год? Это вопрос сомнения. А вот для скама вопрос стоит проще и жёстче: а вообще такая реализация есть в классическом бизнесе? Нет? Тогда почему?

В этом плане мне понравился подход команды Kickico, которая пытается унифицировать изучение проектов ДО их запуска, а не после.

Токен. Наконец-то, после SEC & MAS, люди стали понимать, что выпускать не ясно что, не понятно для кого — не просто странно, но и опасно. В итоге, если видим, что токены созданы по системе «купи дешевле — продай подороже» и за ними не стоит ничего иного: бонусов, доли участия, обратных выкупов и так далее, то это ещё один повод задуматься над ТЭО (технико-экономическое обоснование) и его адекватностью. Вот ещё несколько нюансов по теме:

  1. Есть ли соглашение о распределении токенов?
  2. Как вообще обозначен токен в разных документах: Дорожной карте, Белой книге, публичной оферте и т.д.?
  3. В этом видео вы найдёте не премер скама, а скорее пункта, который среди прочих, выглядит подозрительно: когда в White Paper написано об обратном выкупе, а документах сугубо юридических — нет. Уловка или недомолвка? Зависит от других направлений, но, как минимум, повод изучить проект подробней
  4. Сколько токенов эмитировано и какова их экономика? Скажем, чтобы поддерживать рост и ликвидность ETH необходим ежедневный оборот в 5 000 000 долларов и более. Если его нет, то идёт падение. В этом смысле EHT инфляционный токен, а btc — дефляционный. Стейблкоины же пока только на этапе становления. Зачем это знать? Затем, что Концепт должен учитывать экономическую сущность токена и исходить в показателях роста. Сегодня это делают далеко не все проекты даже из белого списка — это ещё один повод задуматься о возможности участия в них.

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

В России и странах СНГ в основном приоритет за анализом техническим. Давайте же и мы тоже не будем обходить его стороной.

Скажем, тот же . Здесь можно найти интересную информацию об одном из самых подозрительных среди последних. Кроме ICOtracker, есть и ещё ряд подобных проектов: ICOrating, где есть специальная вкладка с одноимённой закладкой, icostats и ряд других. На Golos Ден Иванов делал подборку по этому поводу — к нему и адресую.

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



Данный подход был создан Алексом Контегна (Alex Kontegna). Автор объясняет данную структуру оценки ICO следующим образом: «наша карта делит пространство на матрицу с девятью слотами: в положительных (зелёных) и отрицательных (красных) полях, определенными на разных пересечениях. Хорошее применение этой матрицы — измерение параметра риска вашего портфолио (ICO-токенов), если вы владеете несколькими монетами».

К матрице прилагаются следующие простые правила:

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

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

Скажем, регистрация домена. Если проект разрабатывался, то у него должна быть, пусть и небольшая, но история. И поэтому домен, которому от роду 1-3 месяца, даже полгода — выглядит странным (если только нет аффилированного с ним). Всегда импонирует открытость данных даже там, где делать этого не обязательно — вот всё тот же пример из последних наблюдений https://who.is/whois/coss.io. При этом: если компания заявляет некую историю по старым проектам, которые даже уже закрыты, то эти сведения можно проверить:

  1. http://web-arhive.ru/ — смотрим, то, что было до прихода ICO с проектами
  2. каталоги (раньше был DMOZ, сейчас это Яндекс и местные каталоги сайтов)
  3. обратные ссылки: когда удаляется сайт далеко не все удаляют ссылки на него, а таких может быть много: партнёры, новостные сайты, форумы
  4. есть ещё более мелкие детали: даты в sitemap старых сайтов или элементы seo-оптимизации на страницах (мошенники обычно на этом не заморачиваются, поскольку делают проекты на коленке и предельно быстро).

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

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

https://matchpool.co — социальная сеть, завязанная на блокчейне. Случилось с ней следующее (по данным Forbes): «В начале апреля 2017 года его создатели с помощью ICO получили $5,8 миллионов. Но уже через пару дней компанию покинул технический директор, которого заподозрили в незаконном выводе средств». Аналогичные истории случались и в других стартапах.

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

  1. Есть мультиподпись;
  2. Формируется некий стабфонд, который будет использован в каких-то неприятных ситуациях (случай с тем же Satoshi Fond);
  3. Существуют смарт-контракты на возврат сумм при определённых ситуациях (не прохождении нижнего порога ICO, форс-мажор и т.п.). Почитать о примерах можно в книге.

В заключение хотелось бы выделить следующие аспекты:

Прежде, чем рваться в бой, обратите внимание на уже существующие scam’ы — изучите, проанализируйте, сделайте обобщающие выводы:

  1. https://nodio.net/ — 2016 год, Украина; сайт не работает.
  2. https://www.ebitz.org/ — 2016 год, Анонимно; сайт работает номинально.
  3. http://www.tithecoin.com/ — 2016 год, США; сайт работает.
  4. https://ascendancy.io/#/ — 2016, Не выяснено; сайт не работает.

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

Нужно понимать, что ICO — начинающий, а значит высокорискованный бизнес. Тем более в рамках последних заявлений SEC & MAS.

Чтобы найти скам нужны не какие-то сверх-методики, машинное обучение и работа с большими данными (хотя это, безусловно, пригодилось бы каждому), а усердие, внимание к деталям и затраченное пропорционально вложениям время на исследование ICO-проектов. Нет времени тратить силы на это? Или не заходите вообще в проекты, или обратитесь хотя бы к тому же https://www.kickico.com/ru/ — ребята, по крайне мере, стараются.

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

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

  1. Сервис для вас лично должен быть понятен в принципах работы и близок по целям;
  2. Спекулятивная составляющая не должна быть единственной (в этом плане Мавро — как раз пример обратного);
  3. И, наконец, безопасно вкладывать можно только те доходы, которые идут свыше ваших личных расходов, о какой бы конкретной сумме ни шла речь.

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

  • По критерию восприятия: положительно или отрицательно;
  • По уровню восприятия: сложно или просто;
  • По бальной шкале:
    Десятибалльная — одна из самых простых и понятных: всё, что ниже нуля — ближе к скаму; всё, что выше — дальше от скама;
    Стобалльная. Если в вашем личном наборе оценок сто и более элементов: подход хорош для полуавтоматической оценки;
    Также можно использовать смешанную систему: скажем отрицательным факторам присваивать до 10 баллов в минус, а положительным, соответственно, в плюс. Каждый проект изначально берём за 100% и далее начинаем разбор: если итоговая оценка ниже 33-66%, то это подозрение на скам, 66-75% — норма, далее уже хорошие и отличные проекты.
  • По иным критериям, например, используя систему оценку ценных бумаг или же применяя подход эмоциональной окраски (негативно, нейтрально-негативно, нейтрально, нейтрально-положительно, положительно).

Таким образом, систему выявления скамов можно выстроить, но единственное, что всегда остаётся за скобками — это наша общечеловеческая жадность: если она свойственна вам в критичные моменты, то моя лично позиция проста: «ICO не для вас».

В завершении — небольшая подборка для расширения понимания темы:

  1. Книга об ICO. Часть 1.
  2. Книга об ICO. Часть 2.
  3. Общие вопросы ICO
  4. ICO и легализация средств
  5. ICO: основные риски
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335548/


Метки:  

PHP-Дайджест № 114 – свежие новости, материалы и инструменты (1 – 14 августа 2017)

Понедельник, 14 Августа 2017 г. 02:21 + в цитатник


Свежая подборка со ссылками на новости и материалы. В выпуске: PHP 7.2.0 Beta 2, об истории и безопасности unserialize(), старт PSR HTTP Client, StackOverflow Driven Development, видео с конференций и митапов, и многое другое.
Приятного чтения!



Новости и релизы


  • PHP 7.2.0 Beta 2 — Список новых возможностей ветки 7.2 тут, а протестировать можно из подготовленного Docker-образа. Третий и последний бета-релиз запланирован на 17 августа.
  • Composer 1.5.0
  • PHP 7.0.22
  • PHP 7.1.8
  • [PSR] HTTP Client — Согласно принятому процессу, новые предложения для PSR должны пройти входное голосование, прежде чем будет разработан черновик. Такое голосование прошло для стандарта HTTP Client, а значит в ближайшем будущем группа начнет работу над документом.


Инструменты


  • mihaeu/dephpend — Инструмент статического анализа, который поможет выявить проблемы в архитектуре.
  • spatie/phpunit-watcher — Инструмент для автоматического запуска тестов когда изменен код. Пост в поддержку.
  • Imangazaliev/DiDOM — Простая и быстрая библиотека для парсинга HTML.
  • hirak/prestissimo — Плагин Composer для параллельной установки пакетов. Значительно ускоряет установку зависимостей. Прислал chilic.
  • clue/php-commander — Инструмент для создания простых консольных удобным с интерфейсом.
  • thephpleague/json-reference — Библиотека для работы с JSON-ссылками.
  • paragonie/easydb — Простая и лаконичная обертка над PDO.
  • hjr3/php-rpm — Менеджер процессов для PHP на Rust.


Материалы для обучения




Аудио и видеоматериалы




Занимательное



Спасибо за внимание!

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

Прислать ссылку
Быстрый поиск по всем дайджестам
<- Предыдущий выпуск: PHP-Дайджест № 113

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

https://habrahabr.ru/post/335546/


Метки:  

Поиск сообщений в rss_rss_hh_full
Страницы: 1824 ... 1476 1475 [1474] 1473 1472 ..
.. 1 Календарь