Русский
Русский
English
Статистика
Реклама

Блог компании otus. онлайн-образование

Перевод Kotlin vs Java

24.06.2020 18:08:11 | Автор: admin
И снова здравствуйте. В преддверии старта нового курса Backend-разработка на Kotlin, мы подготовили для вас перевод статьи, в которой рассказывается о том, чем же Kotlin отличается от Java.




Kotlin новый язык программирования, который заставит вас отказаться от Java. На европейской конференции Zebra APPFORUM 2017 в Праге наш Android-разработчик Питер Оттен вдохновлял других начать писать на Kotlin. Расстроены, что пропустили? Не переживайте! Питер расскажет вам, почему он стал большим поклонником этого языка.

Подъем


Kotlin это язык программирования, разработанный компанией Jetbrains, которая знаменита IntelliJ, WebStorm, PhpStorm и плагином ReSharper для Visual Studio. Они занялись поисками нового языка программирования, который был бы лучше, чем Java, но все еще функционально совместим с ним. Вдохновляясь языками Java, C#, Scala и Groovy, ребята из Jetbrains собрали команду для разработки нового языка программирования. Kotlin проектировался людьми, которые испытали всю боль Java.

Так что же такое Kotlin?


Kotlin был впервые представлен в 2011 году, а в феврале 2016 года появилась его версия 1.0 stable release, затем 1.1 в марте. Язык программирования с открытым исходным кодом компилируется в JVM (Java Virtual Machine), Android и JavaScript. Таким образом, Kotlin может использоваться одновременно на JVM и Android-устройствах (интероперабельность). Также он может запускаться на фронтенде с помощью JavaScript. Google официально объявила на своей конференции I/O в мае, что Kotlin стал официально поддерживаемым языком для Android-разработки. С тех пор интерес к языку, его применение и сообщество выросли в разы.



По сравнению с Java


Для сравнения Java и Kotlin на презентации был приведен в пример класс POJO и то, как его можно использовать (рисунок выше). Здесь можно увидеть всю силу и лаконичность Kotlin, когда простой класс Person (с именем, геттером/сеттером и стандартными методами POJO) заменяется ключевым словом data. Также, глядя на использование класса Person можно заметить следующие различия:

  • Методы в Kotlin называются fun (это сразу же делает программирование веселее);
  • Если метод ничего не возвращает, то тип возвращаемого значения указывать не надо (в Java нужно писать void);
  • В Kotlin есть интерференция типов, поэтому указывать, что name имеет тип String не нужно. Простой используйте val.
  • Также эта особенность делает переменную неизменяемой. Если вы захотите изменить переменную name, нужно использовать var. Так Kotlin заставляет вас при написании кода заранее думать о переменных/полях и т.д.
  • Для создания нового экземпляра класса ключевое слово new не нужно;
  • Kotlin и Java совместимы. Kotlin без проблем может использовать класс Person, написанный на Java.
  • Геттеры и сеттеры из кода на Java автоматически станут свойствами, то есть getName() в Kotlin будет недоступно, но можно использовать свойство name из Person.



Выводы Mediaan об использовании Kotlin


После посещения других докладов о Kotlin на Droidcon в 2015 и 2016 в Лондоне и GDG DevFest 2016 в Амстердаме наша команда мобильных разработчиков решила, что пришло время взглянуть на новый язык. Мы начали использовать его в октябре 2016 года и просто влюбились в него. Первый новый проект под Android уже был на 100% написан на Kotlin. С тех пор мы не возвращались к Android-разработке на Java.

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

  • Код более лаконичен, то есть вы сможете писать и поддерживать меньшее количество кода;
  • Код более безопасный, поскольку язык заставляет вас думать о (не)изменяемости, nullability и т.д. во время написания кода;
  • Вышесказанное также ускоряет развитие. Вам становится проще делать сложны вещи.
  • Отличная поддержка IDE (мы пользуемся Android Studio);
  • Большое и растущее сообщество. Существующие библиотеки поддерживаются или мигрируют в Kotlin, интернет переполнен постами в блогах, видео, презентациями и, конечно же, вопросами/ответами на
    StackOverflow.
  • Kotlin уже готов к продакшену. Мы используем его на продакшене также, как и многие компании, такие как Square, Pinterest, Trello и Google.

Теперь Google объявила, что Kotlin официальный язык для разработки под Android, и у вас практически нет причин, чтобы не взглянуть на этот язык и не начать его использовать.

Итак, начнете ли вы с Kotlin или перейдете на него?


Есть множество ссылок, которые помогут вам в его освоении:


Кроме того, в плагине для Android Studio есть возможность быстро конвертировать ваш текущий открытый файл на Java в Kotlin. Работает достаточно хорошо. Возможно, вам потребуется подправить кое-какие мелочи в коде, но вы мгновенно получите Kotlin-версию вашего кода на Java для сравнения и изучения. Есть еще одна удивительная возможность: когда вы работаете в файле на Kotlin и вставляете в него фрагмент кода на Java, он автоматически преобразуется в код на Kotlin при вставке.

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

  • Используйте интероперабельность (Kotlin и Java могут работать бок о бок);
  • Используйте плагин для конвертации файлов и фрагментов кода.
  • Все новые функции пишите на Kotlin;
  • Все, что вы редактируете, конвертируйте из Java в Kotlin.

О будущем


Помимо поддержки JVM, Android и JavaScript, Kotlin работает над поддержкой большего числа платформ. Поддержка машинного кода это следующий большой шаг. Например, запустить код на RaspBerry Pi уже можно (в бета версии). Jetbrains упорно работает над добавлением поддержки для iOS, MacOS и Windows. Это значит, что Kotlin может однажды стать основной нового кроссплатформенного решения для приложений. Больше информации о дальнейшем развитии вы сможете узнать на KotlinConf, их собственной конференции в конце этого года в Сан-Франциско.



Узнать подробнее о курсе.


Подробнее..

Перевод Управление несколькими JDK в Mac OS, Linux и Windows WSL2

23.06.2020 16:19:11 | Автор: admin
И снова здравствуйте. В преддверии старта курса Разработчик Java подготовили для вас перевод интересной статьи.



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



В наши дни установка, управление и переключение между JDK при разработке становится непростой задачей, потому что большое количество разработчиков все еще работает с Java 8, хотя многие уже переходят на Java 11. Эта проблема может быть решена разными способами. В этой статье мы рассмотрим некоторые из них.

Ручной способ


Вы можете скачать дистрибутивы с сайта вендора JDK и установить их все вручную (или просто распаковать их в какую-нибудь папку вроде $user/jdks) и все. Но тогда вам придется каждый раз проверять и обновлять JAVA_HOME, чтобы там была нужная вам JDK.

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

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

Лучший способ


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



Давайте посмотрим на их совместное использование.

Установка нескольких JDK



После установки SDKMAN! наберите:

$ sdk list java


Найдите нужного вендора, версию и введите:

$ sdk install java <id>


Давайте установим четыре JDK: две последние версии Oracle OpenJDK и две LTS-версии AdoptOpenJDK.

При установке не выбирайте JDK по умолчанию.

  1. AdoptOpenJDK сборка OpenJDK 8u252 LTS
  2. AdoptOpenJDK сборка OpenJDK 11.0.7 LTS
  3. Oracle OpenJDK 14 Последний GA
  4. Oracle OpenJDK 15 Early Access сборка


Эти четыре версии должны отвечать вашим потребностям для легаси-проектов на Java 8, для современных проектов на Java 11, а также для экспериментов с нововведениями в Java 14 и Java 15.

Отлично. У вас есть четыре JDK, установленные локально с помощью SDKMAN! Я думаю, что эта утилита действительно удобна для установки JDK и, я надеюсь, она вам тоже понравилась.

Все установленные JDK можно найти в следующем каталоге:

$ cd /Users/bruno/.sdkman/candidates/java$ ls11.0.7.hs-adpt  14.0.1-open     15.ea.20-open   8.0.252.hs-adpt


Если у вас нет необходимости часто переключаться между разными JDK, то этого будет достаточно. Вы можете использовать SDKMAN! для выбора JDK:

$ sdk current javaUsing java version 15.ea.19-open$ sdk default java 15.ea.20-openDefault java version set to 15.ea.20-open


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

Управление несколькими JDK с помощью jEnv




Несмотря на то что SDKMAN! удобен для установки JDK, но он не помогает при автоматическом переключении между разными JDK при переходе от одного проекта к другому. Здесь нам поможет jEnv.

После того как вы установите несколько JDK, с помощью SDKMAN! или любыми другими способами, вам нужно будет добавить их в jEnv:

$ cd ~/.sdkman/candidates/java$ ls -111.0.7.hs-adpt 14.0.1-open    15.ea.20-open8.0.252.hs-adpt$ jenv add 15.ea.20-openopenjdk64-15-ea added15-ea added15-ea added...$ jenv versions system 1.8 1.8.0.252 11.0 11.0.7 14.0 14.0.1* 15-ea (set by /Users/bruno/.jenv/version) openjdk64-1.8.0.252 openjdk64-11.0.7 openjdk64-14.0.1 openjdk64-15-ea


Повторите команду jenv add для оставшихся трех версий JDK.

jEnv особенно удобен для тех, кто постоянно использует командную строку. Он позволит вам:

  1. Установить версию Java глобально для вашей системы.
  2. Установить версию Java для текущего каталога / проекта, в котором вы находитесь.
  3. Установить версию Java для текущего shellа.


jEnv использует shim и автоматически управляет переменной окружения JAVA_HOME. Таким образом, после того как вы настроите вашу систему, jEnv будет переключать версию JDK на наиболее подходящую, на основе вышеуказанных приоритетов и текущей директории. Круто! У него есть и другие полезные функции дополнительную информацию смотрите на сайте.

Автоматическое переключение между JDK


Теперь у вас установлены Java 8, 11, 14 и 15-EA. Итак, как же переключаться между ними? Давайте настроим версии и протестируем переключение.

Сначала нужно указать дефолтную глобальную JDK в системе. Для этого я обычно использую ранние сборки (Early Access). Всякий раз, когда я начинаю работать с новым проектом, я автоматически использую предстоящий релиз, что помогает мне выявить потенциальные проблемы, которые я могу сообщить в проект OpenJDK. Вы же тоже так делаете

$ jenv global 15


Теперь для любой папки, в которой вы находитесь, при выполнении java -version вы получите OpenJDK 15 EA.
Если у вас есть проект, который должен использовать Java 8, то перейдите в папку и запустите:

$ jenv local 1.8


В результате будет создан файл под названием .java-version со следующим содержимым:

$ cat .java-version1.8


Этот файл сообщает jEnv, какую JDK использовать, когда вы находитесь в этой папке.

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

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

После публикации статьи на Reddit были несколько интересных комментариев, о которых стоит здесь сказать:

  • SDKMAN! с версии 5.8.1+ поддерживает sdk env и там тоже доступно автоматическое переключение.
  • direnv очень хорош и не привязан к java. Делает то же самое, что и jEnv, за исключением того, что не помогает вам легко переключать JDK. Вы должны редактировать файлы вручную.
  • autoenv еще одна альтернатива direnv с теми же ограничениями.
  • jabba наиболее перспективная альтернатива сочетанию SDKMAN + jEnv, поскольку поддерживает весь их функционал и работает в Windows (PowerShell), что не поддерживается другими, упомянутыми выше, инструментами.

Надеюсь, вам понравилось прочитанное. Если у вас есть вопросы, просто свяжитесь со мной в Твиттере.



УПРАВЛЯЕМ ВЕРСИЯМИ БАЗ ДАННХ ЧЕРЕЗ FLYWAY




Еще по теме


Подробнее..

Перевод Дебажим PHP-контейнер с помощью Xdebug и PhpStorm

24.06.2020 16:09:31 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Backend-разработчик на PHP.




Инструкция Docker #9: xdebug

Я создам очень простую php-страницу и подебажу ее с помощью xdebug и PhpStorm.

Исходные файлы можно найти здесь:
github.com/ikknd/docker-study в папке recipe-09

1. Создайте файл Dockerfile в папке docker:

FROM php:7.2-fpm#Install xdebugRUN pecl install xdebug-2.6.1 && docker-php-ext-enable xdebugCMD ["php-fpm"]

Выполните эту команду из папки docker для создания образа:

docker build -t php-xdebug-custom -f Dockerfile .

2. Создайте файл docker-compose.yml в папке docker:

version: "3.7"services:  web:    image: nginx:1.17    ports:      - 80:80    volumes:      - /var/www/docker-study.loc/recipe-09/php:/var/www/myapp      - /var/www/docker-study.loc/recipe-09/docker/site.conf:/etc/nginx/conf.d/site.conf    depends_on:      - php  php:    image: php-xdebug-custom    volumes:      - /var/www/docker-study.loc/recipe-09/php:/var/www/myapp      - /var/www/docker-study.loc/recipe-09/docker/php.ini:/usr/local/etc/php/php.ini

Здесь я использую образ php-xdebug-custom вместо php:7.2-fpm

3. Внесите в файл php.ini следующие настройки:

[xdebug]zend_extension=xdebug.soxdebug.profiler_enable=1xdebug.remote_enable=1xdebug.remote_handler=dbgpxdebug.remote_mode=reqxdebug.remote_host=host.docker.internalxdebug.remote_port=9000xdebug.remote_autostart=1xdebug.remote_connect_back=1xdebug.idekey=PHPSTORM

4. Настройте сервер в PhpStorm:

File -> Settings -> Languages и Frameworks -> PHP -> Servers
Добавьте новый сервер с помощью иконки + и настройте его, как показано на следующем скриншоте:



Убедитесь, что вы отметили Использовать сопоставление путей (Use path mappings) и сопоставили папку php с /var/www/myapp.

5. Настройте удаленный дебагер PHP в PhpStorm:

Run -> Edit configurations -> PHP Remote Debug

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



6. Выберите конфигурацию дебага на панели дебага PhpStorm



7. Перейдите в /var/www/docker-study.loc/recipe-09/docker/ и выполните:

docker-compose up -d

Если я сейчас введу myapp.loc/ в браузере, я увижу результаты из файла index.php.

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

Удачного дебага!



Узнать о курсе подробнее.



Еще по теме


Подробнее..

Перевод Введение в асинхронное программирование на Python

03.07.2020 14:20:11 | Автор: admin
Всем привет. Подготовили перевод интересной статьи в преддверии старта базового курса Разработчик Python.



Введение


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



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

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

Асинхронность это одна из основных причин популярности выбора Node.js для реализации бэкенда. Большое количество кода, который мы пишем, особенно в приложениях с тяжелым вводом-выводом, таком как на веб-сайтах, зависит от внешних ресурсов. В нем может оказаться все, что угодно, от удаленного вызова базы данных до POST-запросов в REST-сервис. Как только вы отправите запрос в один из этих ресурсов, ваш код будет просто ожидать ответа. С асинхронным программированием вы позволяете своему коду обрабатывать другие задачи, пока ждете ответа от ресурсов.

Как Python умудряется делать несколько вещей одновременно?




1. Множественные процессы

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

from multiprocessing import Processdef print_func(continent='Asia'):    print('The name of continent is : ', continent)if __name__ == "__main__":  # confirms that the code is under main function    names = ['America', 'Europe', 'Africa']    procs = []    proc = Process(target=print_func)  # instantiating without any argument    procs.append(proc)    proc.start()    # instantiating process with arguments    for name in names:        # print(name)        proc = Process(target=print_func, args=(name,))        procs.append(proc)        proc.start()    # complete the processes    for proc in procs:        proc.join()


Вывод:

The name of continent is :  AsiaThe name of continent is :  AmericaThe name of continent is :  EuropeThe name of continent is :  Africa


2. Множественные потоки

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

import threading def print_cube(num):    """    function to print cube of given num    """    print("Cube: {}".format(num * num * num)) def print_square(num):    """    function to print square of given num    """    print("Square: {}".format(num * num)) if __name__ == "__main__":    # creating thread    t1 = threading.Thread(target=print_square, args=(10,))    t2 = threading.Thread(target=print_cube, args=(10,))     # starting thread 1    t1.start()    # starting thread 2    t2.start()     # wait until thread 1 is completely executed    t1.join()    # wait until thread 2 is completely executed    t2.join()     # both threads completely executed    print("Done!")


Вывод:

Square: 100Cube: 1000Done!


3. Корутины и yield:

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

def print_name(prefix):    print("Searching prefix:{}".format(prefix))    try :         while True:                # yeild used to create coroutine                name = (yield)                if prefix in name:                    print(name)    except GeneratorExit:            print("Closing coroutine!!") corou = print_name("Dear")corou.__next__()corou.send("James")corou.send("Dear James")corou.close()


Вывод:

Searching prefix:DearDear JamesClosing coroutine!!


4. Асинхронное программирование

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

Ответ: asyncio

Asyncio модуль асинхронного программирования, который был представлен в Python 3.4. Он предназначен для использования корутин и future для упрощения написания асинхронного кода и делает его почти таким же читаемым, как синхронный код, из-за отсутствия callback-ов.

Asyncio использует разные конструкции: event loop, корутины и future.

  • event loop управляет и распределяет выполнение различных задач. Он регистрирует их и обрабатывает распределение потока управления между ними.
  • Корутины (о которых мы говорили выше) это специальные функции, работа которых схожа с работой генераторов в Python, с помощью await они возвращают поток управления обратно в event loop. Запуск корутины должен быть запланирован в event loop. Запланированные корутины будут обернуты в Tasks, что является типом Future.
  • Future отражает результат таска, который может или не может быть выполнен. Результатом может быть exception.


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

Переключение контекста в asyncio представляет собой event loop, который передает поток управления от одной корутины к другой.

В следующем примере, мы запускаем 3 асинхронных таска, которые по-отдельности делают запросы к Reddit, извлекают и выводят содержимое JSON. Мы используем aiohttp клиентскую библиотеку http, которая гарантирует, что даже HTTP-запрос будет выполнен асинхронно.

import signal  import sys  import asyncio  import aiohttp  import jsonloop = asyncio.get_event_loop()  client = aiohttp.ClientSession(loop=loop)async def get_json(client, url):      async with client.get(url) as response:        assert response.status == 200        return await response.read()async def get_reddit_top(subreddit, client):      data1 = await get_json(client, 'https://www.reddit.com/r/' + subreddit + '/top.json?sort=top&t=day&limit=5')    j = json.loads(data1.decode('utf-8'))    for i in j['data']['children']:        score = i['data']['score']        title = i['data']['title']        link = i['data']['url']        print(str(score) + ': ' + title + ' (' + link + ')')    print('DONE:', subreddit + '\n')def signal_handler(signal, frame):      loop.stop()    client.close()    sys.exit(0)signal.signal(signal.SIGINT, signal_handler)asyncio.ensure_future(get_reddit_top('python', client))  asyncio.ensure_future(get_reddit_top('programming', client))  asyncio.ensure_future(get_reddit_top('compsci', client))  loop.run_forever()


Вывод:

50: Undershoot: Parsing theory in 1965 (http://personeltest.ru/away/jeffreykegler.github.io/Ocean-of-Awareness-blog/individual/2018/07/knuth_1965_2.html)12: Question about best-prefix/failure function/primal match table in kmp algorithm (http://personeltest.ru/aways/www.reddit.com/r/compsci/comments/8xd3m2/question_about_bestprefixfailure_functionprimal/)1: Question regarding calculating the probability of failure of a RAID system (http://personeltest.ru/aways/www.reddit.com/r/compsci/comments/8xbkk2/question_regarding_calculating_the_probability_of/)DONE: compsci336: /r/thanosdidnothingwrong -- banning people with python (http://personeltest.ru/aways/clips.twitch.tv/AstutePluckyCocoaLitty)175: PythonRobotics: Python sample codes for robotics algorithms (http://personeltest.ru/aways/atsushisakai.github.io/PythonRobotics/)23: Python and Flask Tutorial in VS Code (http://personeltest.ru/aways/code.visualstudio.com/docs/python/tutorial-flask)17: Started a new blog on Celery - what would you like to read about? (http://personeltest.ru/aways/www.python-celery.com)14: A Simple Anomaly Detection Algorithm in Python (http://personeltest.ru/aways/medium.com/@mathmare_/pyng-a-simple-anomaly-detection-algorithm-2f355d7dc054)DONE: python1360: git bundle (http://personeltest.ru/aways/dev.to/gabeguz/git-bundle-2l5o)1191: Which hashing algorithm is best for uniqueness and speed? Ian Boyd's answer (top voted) is one of the best comments I've seen on Stackexchange. (http://personeltest.ru/aways/softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed)430: ARM launches Facts campaign against RISC-V (http://personeltest.ru/aways/riscv-basics.com/)244: Choice of search engine on Android nuked by Anonymous Coward (2009) (http://personeltest.ru/aways/android.googlesource.com/platform/packages/apps/GlobalSearch/+/592150ac00086400415afe936d96f04d3be3ba0c)209: Exploiting freely accessible WhatsApp data or Why does WhatsApp web know my phones battery level? (http://personeltest.ru/aways/medium.com/@juan_cortes/exploiting-freely-accessible-whatsapp-data-or-why-does-whatsapp-know-my-battery-level-ddac224041b4)DONE: programming


Использование Redis и Redis Queue RQ


Использование asyncio и aiohttp не всегда хорошая идея, особенно если вы пользуетесь более старыми версиями Python. К тому же, бывают моменты, когда вам нужно распределить задачи по разным серверам. В этом случае можно использовать RQ (Redis Queue). Это обычная библиотека Python для добавления работ в очередь и обработки их воркерами в фоновом режиме. Для организации очереди используется Redis база данных ключей/значений.

В примере ниже мы добавили в очередь простую функцию count_words_at_url с помощью Redis.

from mymodule import count_words_at_urlfrom redis import Redisfrom rq import Queueq = Queue(connection=Redis())job = q.enqueue(count_words_at_url, 'http://nvie.com')******mymodule.py******import requestsdef count_words_at_url(url):    """Just an example function that's called async."""    resp = requests.get(url)    print( len(resp.text.split()))    return( len(resp.text.split()))


Вывод:

15:10:45 RQ worker 'rq:worker:EMPID18030.9865' started, version 0.11.015:10:45 *** Listening on default...15:10:45 Cleaning registries for queue: default15:10:50 default: mymodule.count_words_at_url('http://nvie.com') (a2b7451e-731f-4f31-9232-2b7e3549051f)32215:10:51 default: Job OK (a2b7451e-731f-4f31-9232-2b7e3549051f)15:10:51 Result is kept for 500 seconds


Заключение


В качестве примера возьмем шахматную выставку, где один из лучших шахматистов соревнуется с большим количеством людей. У нас есть 24 игры и 24 человека, с которыми можно сыграть, и, если шахматист будет играть с ними синхронно, это займет не менее 12 часов (при условии, что средняя игра занимает 30 ходов, шахматист продумывает ход в течение 5 секунд, а противник примерно 55 секунд.) Однако в асинхронном режиме шахматист сможет делать ход и оставлять противнику время на раздумья, тем временем переходя к следующему противнику и деля ход. Таким образом, сделать ход во всех 24 играх можно за 2 минуты, и выиграны они все могут быть всего за один час.

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

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

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



Узнать о курсе подробнее.


Подробнее..

Перевод Понимаем JIT в PHP 8

05.07.2020 04:21:30 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Backend-разработчик на PHP



TL;DR


Компилятор Just In Time в PHP 8 реализован как часть расширения Opcache и призван компилировать операционный код в инструкции процессора в рантайме.

Это означает, что с JIT некоторые операционные коды не должны интерпретироваться Zend VM, такие инструкции будут выполняться непосредственно как инструкции уровня процессора.

JIT в PHP 8


Одной из наиболее комментируемых фич PHP 8 является компилятор Just In Time (JIT). Он на слуху во множестве блогов и сообществ вокруг него много шума, но пока я нашел не очень много подробностей о работе JIT в деталях.

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

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

В этом вся идея.

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

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

Как выполняется PHP-код?


Мы все знаем, что php интерпретируемый язык. Но что это на самом деле означает?

Всякий раз, когда вы хотите выполнить код PHP, будь то фрагмент или целое веб-приложение, вам придется пройти через интерпретатор php. Наиболее часто используемые из них PHP FPM и интерпретатор CLI. Их работа очень проста: получить код php, интерпретировать его и выдать обратно результат.

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

  1. Код PHP читается и преобразуется в набор ключевых слов, известных как токены (Tokens). Этот процесс позволяет интерпретатору понять, в какой части программы написан каждый фрагмент кода. Этот первый шаг называется лексирование (Lexing) или токенизация (Tokenizing).
  2. Имея на руках токены, интерпретатор PHP проанализирует эту коллекцию токенов и постарается найти в них смысл. В результате абстрактное синтаксическое дерево (Abstract Syntax Tree AST) генерируется с помощью процесса, называемого синтаксическим анализом (parsing). AST представляет собой набор узлов, указывающих, какие операции должны быть выполнены. Например, echo 1 + 1 должно фактически означать вывести результат 1 + 1 или, более реалистично, вывести операцию, операция 1 + 1.
  3. Имея AST, например, гораздо проще понять операции и их приоритет. Преобразование этого дерева во что-то, что может быть выполнено, требует промежуточного представления (Intermediate Representation IR), которое в PHP мы называем операционный код (Opcode). Процесс преобразования AST в операционный код называется компиляцией.
  4. Теперь, когда у нас есть опкоды, происходит самое интересное: выполнение кода! PHP имеет движок под названием Zend VM, который способен получать список опкодов и выполнять их. После выполнения всех опкодов программа завершается.


Чтобы сделать это немного нагляднее, я составил диаграмму:


Упрощенная схема процесса интерпретации PHP.

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

В конце концов, нас интересуют только опкоды, верно? Правильно! Вот зачем существует расширение Opcache.

Расширение Opcache


Расширение Opcache поставляется с PHP, и, как правило, нет особых причин его деактивировать. Если вы используете PHP, вам, вероятно, следует включить Opcache.

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

Вот схема того же процесса с учетом расширения Opcache:


Поток интерпретации PHP с Opcache. Если файл уже был проанализирован, php извлекает для него кэшированный операционный код, а не анализирует его заново.

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

Вы можете начать задумываться, а куда сюда можно прилепить JIT, верно?! По крайней мере я на это надеюсь, именно поэтому я и пишу эту статью

Что делает компилятор Just In Time?


Прослушав объяснение Зива в эпизоде подкастов PHP и JIT от PHP Internals News, мне удалось получить некоторое представление о том, что на самом деле должен делать JIT

Если Opcache позволяет быстрее получать операционный код, чтобы он мог переходить непосредственно к Zend VM, JIT предназначить заставить его работать вообще без Zend VM.

Zend VM это программа, написанная на C, которая действует как слой между операционным кодом и самим процессором. JIT генерирует скомпилированный код во время выполнения, поэтому php может пропустить Zend VM и перейти непосредственно к процессору. Теоретически мы должны выиграть в производительности от этого.

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

Реализация JIT в PHP использует библиотеку DynASM (Dynamic Assembler), которая отображает набор команд ЦП в конкретном формате в код сборки для многих различных типов ЦП. Таким образом, компилятор Just In Time преобразует операционный код в машинный код для конкретной архитектуры, используя DynASM.

Хотя одна мысль все-таки не давала мне покоя

Если предварительная загрузка способна парсить php-код в операционный перед выполнением, а DynASM может компилировать операционный код в машинный (компиляция Just In Time), почему мы, черт возьми, не компилируем PHP сразу же на месте, используя Ahead of Time компиляцию?!

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

Это можно понять, посмотрев на тип объединения zend_value, который имеет много указателей на различные представления типов для переменной. Всякий раз, когда виртуальная машина Zend пытается извлечь значение из zend_value, она использует макросы, подобные ZSTR_VAL, которые пытаются получить доступ к указателю строки из объединения значений.

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

Дублирование такой логики вывода типов с помощью машинного кода неосуществимо и потенциально может сделать работу еще медленнее.

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

Как ведет себя компилятор Just In Time?


Теперь мы знаем, что не можем вывести типы, чтобы генерировать достаточно хорошую опережающую компиляцию. Мы также знаем, что компиляция во время выполнения стоит дорого. Чем же может быть полезен JIT для PHP?

Чтобы сбалансировать это уравнение, JIT PHP пытается скомпилировать только несколько опкодов, которые, по его мнению, того стоят. Для этого он профилирует коды операций, выполняемые виртуальной машиной Zend, и проверяет, какие из них имеет смысл компилировать. (в зависимости от вашей конфигурации).

Когда определенный опкод компилируется, он затем делегирует выполнение этому скомпилированному коду вместо делегирования на Zend VM. Это выглядит как на диаграмме ниже:


Поток интерпретации PHP с JIT. Если они уже скомпилированы, опкоды не выполняются через Zend VM.

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

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

Кстати, эта беседа Бенуа Жакемона о JIT от php ОЧЕНЬ помогла мне разобраться во всем этом.

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

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


Я надеюсь, что сейчас гораздо понятнее, ПОЧЕМУ все говорят, что большинство приложений php не получат больших преимуществ в производительности от использования компилятора Just In Time. И почему рекомендация Зива для профилирования и эксперимента с различными конфигурациями JIT для вашего приложения лучший путь.

Скомпилированные опкоды обычно будут распределены между несколькими запросами, если вы используете PHP FPM, но это все равно не изменит правила игры.

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

Если только...

Вы делаете что-то не завязанное на ввод/вывод, например, обработку изображений или машинное обучение. Все, что не касается ввода/вывода, получит пользу от компилятора Just In Time. Это также причина, по которой люди сейчас говорят, что они склоняются больше к написанию нативных функций PHP, написанных на PHP, а не на C. Накладные расходы не будут разительно отличаться, если такие функции будут скомпилированы в любом случае.

Интересное время быть программистом PHP

Я надеюсь, что эта статья была полезна для вас, и вам удалось лучше разобраться, что такое JIT в PHP 8. Не стесняйтесь связываться со мной в твиттере, если вы хотите добавить что-то, что я мог забыть здесь, и не забудьте поделиться этим со своими коллегами-разработчиками, это, несомненно, добавит немного пользы вашим беседам!-- @nawarian



PHP: статические анализаторы кода


Подробнее..

Сортировка выбором

06.07.2020 02:17:13 | Автор: admin
Всем привет. Эту статью я написал специально к запуску курса Алгоритмы и структуры данных от OTUS.



Введение


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

Постановка задачи


Традиционно стоит начать изложение решений задачи с ее постановки. Обычно задача сортировки предполагает упорядочивание некоторого массива целых чисел по возрастанию. Но на самом деле, это является некоторым упрощением. Излагаемые в этом разделе алгоритмы можно применять для упорядочивания массива любых объектов, между которыми установлено отношение порядка (то есть про любые два элемента можно сказать: первый больше второго, второй больше первого или они равны). Упорядочивать можно как по возрастанию, так и по убыванию. Мы же воспользуемся стандартным упрощением.

Сортировка выбором


Одной из простейших сортировок является сортировка выбором.

Описание алгоритма


Сортировка массива выбором осуществляется так: массив делится на две части. Одна из частей называется отсортированной, а другая неотсортированной. Алгоритм предполагает проход по всему массиву с тем, чтобы длина отсортированной части стала равна длине всего массива. В рамках каждой итерации мы находим минимум в неотсортированной части массива и меняем местами этот минимум с первым элементом неотсортированной части массива. После чего мы увеличиваем длину отсортированной части массива на единицу. Пример осуществления одной итерации представлен ниже:
1 3 5 | 8 9 6 -> 1 3 5 6 | 9 8

Реализация


Предлагаю посмотреть на реализацию данного алгоритма на языке C:
void choiseSortFunction(double A[], size_t N){    for(size_t tmp_min_index = 0; tmp_min_index < N;                                  tmp_min_index++) {        //ищем минимум        for(size_t k = tmp_min_index + 1; k < N; k++) {            if (A[k] < A[tmp_min_index]) {                double min_value = A[k];                A[k] = A[tmp_min_index];                A[tmp_min_index] = min_value;            }        }    }}


Анализ


Предлагаю проанализировать данный алгоритм. Тело внутреннего цикла само по себе выполняется за O(1), то есть не зависит от размера сортируемого массива. Это означает, что для понимания асимптотики алгоритма необходимо посчитать сколько раз выполняется это тело. На первой итерации внешнего цикла имеют место (n 1) итераций внутреннего цикла. На второй итерации внешнего цикла (n 2) итерации внутреннего цикла. Продолжая это рассуждение и далее, мы приходим к следующему:

$T(n) = (n - 1) * O(1) + (n - 2) * O(1) + ... + O(1) = O((n - 1) + (n - 2) + ... + 1) = O((n - 1) * n / 2) = O(n ^ 2)$



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

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

$M(n) = O(1)$



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

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

Двусторонняя сортировка выбором


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

Рекурсивная сортировка выбором


В качестве упражнения можно попробовать написать алгоритм не с использованием цикла, а с использованием рекурсии. На java это может выглядеть следующим образом:
public static int findMin(int[] array, int index){    int min = index - 1;    if(index < array.length - 1) min = findMin(array, index + 1);    if(array[index] < array[min]) min = index;    return min;}  public static void selectionSort(int[] array){    selectionSort(array, 0);}  public static void selectionSort(int[] array, int left){    if (left < array.length - 1) {        swap(array, left, findMin(array, left));        selectionSort(array, left+1);    }}  public static void swap(int[] array, int index1, int index2) {    int temp = array[index1];    array[index1] = array[index2];    array[index2] = temp;}


Итоги


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



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


Подробнее..

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

22.06.2020 18:15:30 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Team Lead 2.0.



Как я отмечал в статье Why metrics dont matter in software development unless you pair them with business goals", выбор метрик нужно продумывать очень тщательно, чтобы дать ответы на вопросы, которые ставит перед собой бизнес. Вот эта критическая точка: измерения должны быть спроектированы так, чтобы отвечать на вопросы бизнеса. И эти вопросы никогда не будут звучать как Сколько у нас сейчас тысяч строк кода в проекте?

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

Начните с измерения правильных вещей


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

Метрики Agile-процесса


Для agile и lean-процессов основными метриками будут leadtime, cycle time, velocity команды, и open/close коэффициент. Эти показатели помогают в планировании и принятии решений по улучшению процессов. Несмотря на то, что они не измеряют успешность или добавочную ценность, не имеют ничего общего с объективным качеством программного обеспечения, вам все равно нужно их отслеживать. Ниже я объясню почему.

  • Leadtime время, которое проходит от появления идеи до поставки программного обеспечения. Если вы хотите быстрее реагировать на нужды своих клиентов, работайте над уменьшением leadtime, зачастую посредством упрощения процесса принятия решений и сокращения времени ожидания. Leadtime включает в себя cycle time.
  • Сycle time количество времени, которое требуется на внесение изменений в систему ПО и доставку этих изменений на продакшн. Команды, использующие continuous delivery, могут измерять cycle time в минутах или даже секундах вместо месяцев.
  • Velocity команды количество единиц программного обеспечения, которое команда обычно выполняет в одну итерацию (спринт). Это число следует использовать только для планирования итераций. Сравнивать команды по показателю velocity идея бессмысленная, поскольку метрика основана на необъективных оценках. Рассматривать velocity как показатель успешности тоже бесполезно, да и постановка цели вроде придерживаться определенной velocity искажает ценность этой метрики для мероприятий по оценке и планированию.
  • open/close коэффициент количество появившихся и закрытых issue в единицу времени. Общая тенденция будет иметь большее значение, чем конкретные цифры.

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

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

Аналитика продакшена


  • Средняя наработка на отказ (Mean time between failures, MTBF)
  • Среднее время восстановления (Mean time to recover/repair, MTTR)

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

Частота сбоев приложения количество раз, которое приложение падает, деленное на количество использований. Этот показатель напрямую связан с MTBF и MTTR.

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

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

Помимо MTBF и MTTR, более точные метрики основаны на отдельных транзакциях, приложениях и т.д., и они отражают доставленную бизнес-ценность, а также стоимость устранения сбоев. Если ваше приложение для обработки транзакций падает один раз из ста, но при этом поднимается через 1-2 секунды без критических потерь информации, то и с частотой сбоев в 1% можно жить. Но если с такой частотой падает приложение, которое обрабатывает 100 000 транзакций в день, теряет по 100$ за сбой и восстановление стоит 50$, то исправление этого 1% будет в приоритете. И такое исправление в итоге сильно повлияет на итоговую ситуацию.

Метрики безопасности


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

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

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

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

Вы найдете больше способов применения метрик безопасности в разработке программного обеспечения в статьях Application Security for Agile Projects и Security Threat Models: An Agile Introduction.

Заметка о метриках исходного кода


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

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

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

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

Соберем все вместе: Успех универсальная метрика


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

Как использовать метрики для достижения успеха


У бизнеса есть цели. В целях кроются вопросы, например: Как выглядит успех? или Как продукт повлияет на поведение клиентов?. Правильно сформулированные вопросы таят в себе метрики.

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

Разве не все у всех проектов есть некоторый набор инвариантных целей, вопросов и гипотез, а следовательно, и метрик?

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

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

Как сформулировать ценностную гипотезу


Ценностная гипотеза это утверждение о том, что, по вашему мнению, произойдет в результате добавления определенной функции. Взаимосвязь между программным обеспечением, желаемым результатом и метриками формирует ценностную гипотезу для функции (или системы, истории, обновления и т.д.). Гипотеза должна выражать ожидаемое изменение целевой метрики в течение определённого промежутка времени, а также понятие о ее эффективности. Вам нужно будет поговорить с командой и с Product Owner-ом, чтобы как минимум выяснить, что именно это функция или история может создать или улучшить применительно к бизнесу, чтобы сформулировать относительно нее ценностную гипотезу. Возможно, задать вопрос почему вам придется несколько раз (как ребенку), чтобы избавиться от невысказанных предположений, поэтому будьте терпеливы. Когда вы поймете, какой должна быть ценность для бизнеса, вы можете начать задавать вопросы, которые приведут вас к метрикам, дающим на них ответы.

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

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

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

Шесть эвристик для эффективного использования метрик


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

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

Еще





Узнать подробнее о курсе
Подробнее..

Перевод Экономим на облачных затратах Kubernetes на AWS

03.07.2020 14:20:11 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Инфраструктурная платформа на основе Kubernetes.




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

Я написал эту статью с оглядкой на Kubernetes для AWS, но она будет применима (почти) точно так же и для других облачных провайдеров. Я предполагаю, что ваш кластер(ы) уже имеет настроенное автоматическое масштабирование (cluster-autoscaler). Удаление ресурсов и уменьшение масштаба развертывания позволит сэкономить только в том случае, если это также сократит ваш парк рабочих узлов (EC2 инстансов).

В этой статье будут рассмотрены:

  • очистка неиспользуемых ресурсов (kube-janitor)
  • уменьшение масштабирования в нерабочее время (kube-downscaler)
  • использование горизонтального автомасштабирования (HPA),
  • уменьшение избыточного резервирования ресурсов (kube-resource-report, VPA)
  • использование Spot инстансов


Очистка неиспользуемых ресурсов


Работа в быстро меняющейся среде это здорово. Мы хотим, чтобы технические организации ускорялись. Более быстрая доставка программного обеспечения также означает большее количество PR-развертываний, сред предварительного просмотра, прототипов и аналитических решений. Все разворачиваемое на Kubernetes. У кого есть время, чтобы чистить тестовые развертывания вручную? Легко забыть об удалении эксперимента недельной давности. Счет за облако в конечном итоге будет расти из-за того, что мы забыли закрыть:



(Хеннинг Джейкобс:
Жиза:
(цитирует) Кори Куинн:
Миф: Ваш AWS счет это функция зависимости от количества ваших пользователей.
Факт: Ваш AWS счет это функция зависимости от количества ваших инженеров.

Иван Курносов (в ответ):
Настоящий факт: Ваш AWS счет это функция зависимости от количества вещей, которые вы забыли отключить/удалить.)



Kubernetes Janitor (kube-janitor) помогает очистить ваш кластер. Конфигурация janitor является гибкой как для глобального, так и для локального использования:

  • Общие правила для всего кластера могут определять максимальное время жизни (TTL time-to-live) для PR/тестовых развертываний.
  • Отдельные ресурсы могут быть аннотированы с помощью janitor/ttl, например, для автоматического удаления spike/прототипа через 7 дней.


Общие правила определяются в YAML файле. Его путь передается через параметр --rules-file в kube-janitor. Вот пример правила для удаления всех пространств имен с -pr- в имени через два дня:

- id: cleanup-resources-from-pull-requests  resources:    - namespaces  jmespath: "contains(metadata.name, '-pr-')"  ttl: 2d


Следующий пример регламентирует использования метки application на Deployment и StatefulSet подах для всех новых Deployments/StatefulSet в 2020 году, но в то же время позволяет выполнение тестов без этой метки в течении недели:

- id: require-application-label  # удалить deployments и statefulsets без метки "application"  resources:    - deployments    - statefulsets  # см. http://jmespath.org/specification.html  jmespath: "!(spec.template.metadata.labels.application) && metadata.creationTimestamp > '2020-01-01'"  ttl: 7d


Запуск ограниченного по времени демо в течение 30 минут в кластере, где работает kube-janitor:

kubectl run nginx-demo --image=nginxkubectl annotate deploy nginx-demo janitor/ttl=30m


Еще одним источником растущих затрат являются постоянные тома (AWS EBS). При удалении Kubernetes StatefulSet не удаляются его постоянные тома (PVC PersistentVolumeClaim). Неиспользованные объемы EBS могут легко привести к затратам в сотни долларов в месяц. Kubernetes Janitor имеет функцию для очистки неиспользованных PVC. Например, это правило удалит все PVC, которые не смонтированы модулем и на которые не ссылается StatefulSet или CronJob:

# удалить все PVC, которые не смонтированы и на которые не ссылаются StatefulSets- id: remove-unused-pvcs  resources:  - persistentvolumeclaims  jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"  ttl: 24h


Kubernetes Janitor может помочь вам сохранить ваш кластер в чистоте и предотвратить медленно накапливающиеся затраты на облачные вычисления. За инструкциями по развертыванию и настройке следуйте в README kube-janitor.

Уменьшение масштабирования в нерабочее время


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

Kubernetes Downscaler (kube-downscaler) позволяет пользователям и операторам уменьшать масштаб системы в нерабочее время. Deployments и StatefulSets можно масштабировать до нулевых реплик. CronJobs могут быть приостановлены. Kubernetes Downscaler настраивается для всего кластера, одного или нескольких пространств имен или отдельных ресурсов. Можно установить либо время простоя, либо наоборт время работы. Например, чтобы максимально уменьшить масштабирование в течение ночи и выходных:

image: hjacobs/kube-downscaler:20.4.3args:  - --interval=30  # не отключать компоненты инфраструктуры  - --exclude-namespaces=kube-system,infra  # не отключать kube-downscaler, а также оставить Postgres Operator, чтобы исключенными БД можно было управлять  - --exclude-deployments=kube-downscaler,postgres-operator  - --default-uptime=Mon-Fri 08:00-20:00 Europe/Berlin  - --include-resources=deployments,statefulsets,stacks,cronjobs  - --deployment-time-annotation=deployment-time


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



Уменьшение масштаба с ~13 до 4 рабочих узлов, безусловно, дает ощутимую разницу в AWS счете.

Но что если мне нужно работать во время простоя кластера? Определенные развертывания можно навсегда исключить из масштабирования, добавив аннотацию downscaler/exclude: true. Развертывания могут быть временно исключены с помощью аннотации downscaler/exclude-until с абсолютным таймстемпом в формате ГГГГ-ММ-ДД ЧЧ: ММ (UTC). При необходимости весь кластер может быть масштабирован обратно путем развертывания пода с аннотацией downscaler/force-uptime, например, путем запуска nginx болванки:

kubectl run scale-up --image=nginxkubectl annotate deploy scale-up janitor/ttl=1h # удалить развертывание через часkubectl annotate pod $(kubectl get pod -l run=scale-up -o jsonpath="{.items[0].metadata.name}") downscaler/force-uptime=true


Смотрите README kube-downscaler, если вас интересует инструкция по развертыванию и дополнительные опции.

Используйте горизонтальное автомасштабирование


Многие приложения/сервисы имеют дело с динамической схемой загрузки: иногда их модули простаивают, а иногда они работают на полную мощность. Работа с постоянным парком подов, чтобы справиться с максимальной пиковой нагрузкой, не экономична. Kubernetes поддерживает горизонтальное автоматическое масштабирование через ресурс HorizontalPodAutoscaler (HPA). Использование ЦП часто является хорошим показателем для масштабирования:

apiVersion: autoscaling/v2beta2kind: HorizontalPodAutoscalermetadata:  name: my-appspec:  scaleTargetRef:    apiVersion: apps/v1    kind: Deployment    name: my-app  minReplicas: 3  maxReplicas: 10  metrics:  - type: Resource    resource:      name: cpu      target:        averageUtilization: 100        type: Utilization


Zalando создал компонент для простого подключения пользовательских метрик для масштабирования: Kube Metrics Adapter (kube-metrics-adapter) это универсальный адаптер метрик для Kubernetes, который может собирать и обслуживать пользовательские и внешние метрики для горизонтального автомасштабирования подов. Он поддерживает масштабирование на основе метрик Prometheus, очередей SQS и других настроек. Например, чтобы масштабировать развертывание для пользовательской метрики, представленной самим приложением в виде JSON в /metrics используйте:

apiVersion: autoscaling/v2beta2kind: HorizontalPodAutoscalermetadata:  name: myapp-hpa  annotations:    # metric-config.<metricType>.<metricName>.<collectorName>/<configKey>    metric-config.pods.requests-per-second.json-path/json-key: "$.http_server.rps"    metric-config.pods.requests-per-second.json-path/path: /metrics    metric-config.pods.requests-per-second.json-path/port: "9090"spec:  scaleTargetRef:    apiVersion: apps/v1    kind: Deployment    name: myapp  minReplicas: 1  maxReplicas: 10  metrics:  - type: Pods    pods:      metric:        name: requests-per-second      target:        averageValue: 1k        type: AverageValue


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

Уменьшение избыточного резервирования ресурсов


Рабочие нагрузки Kubernetes определяют их потребности в ЦП/памяти через запросы ресурсов (resource requests). Ресурсы ЦП измеряются в виртуальных ядрах или чаще в милликорах (millicores), например, 500m подразумевает 50% vCPU. Ресурсы памяти измеряются в байтах, и можно использовать обычные суффиксы, например, 500Mi, что означает 500 мегабайт. Запросы ресурсов блокируют объем на рабочих узлах, то есть модуль с запросом ЦП в 1000m на узле с 4 виртуальными ЦП оставит только 3 виртуальных ЦП доступными для других модулей. [1]

Slack (избыток резерва) это разница между запрашиваемыми ресурсами и реальным использованием. Например, под, который запрашивает 2 GiB памяти, но использует только 200 MiB, имеет ~ 1,8 GiB избыточной памяти. Избыток стоит денег. Можно грубо оценить, что 1 GiB избыточной памяти стоит ~ 10 долларов в месяц. [2]

Kubernetes Resource Report (kube-resource-report) отображает излишние резервы и может помочь вам определить потенциал экономии:



Kubernetes Resource Report показывает избыток, агрегированный приложением и командой. Это позволяет найти места, где запросы ресурсов могут быть снижены. Сгенерированный HTML отчет предоставляет только снапшот использования ресурса. Вы должны смотреть на использование процессора/памяти с течением времени, чтобы определить адекватные запросы ресурсов. Вот диаграмма Grafana для типичной службы с большой нагрузкой на ЦП: все поды используют значительно меньше 3 запрошенных ядер ЦП:



Сокращение запроса ЦП с 3000m до ~400m высвобождает ресурсы для других рабочих нагрузок и позволяет уменьшить кластер.

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

Но действительно ли мы хотим, чтобы люди меняли значения в YAML файлах? Нет, машины могут сделать это намного лучше! Kubernetes Vertical Pod Autoscaler (VPA) как раз этим и занимается: адаптирует запросы ресурсов и ограничения в соответствии с рабочей нагрузкой. Вот пример графика запросов ЦП Prometheus (тонкая синяя линия), адаптированных VPA с течением времени:



Zalando использует VPA во всех своих кластерах для компонентов инфраструктуры. Некритические приложения также могут использовать VPA.

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



Я написал небольшой блогпост о VPA в 2019 году, и недавно в CNCF End User Community обсуждался вопрос VPA.

Использование EC2 Spot инстансов


Наконец, что не менее важно, затраты AWS EC2 можно снизить, используя Spot инстансы в качестве рабочих узлов Kubernetes [3]. Spot инстансы доступны со скидкой до 90% по сравнению с ценами по требованию. Запуск Kubernetes на EC2 Spot хорошая комбинация: вам нужно указать несколько разных типов инстансов для более высокой доступности, то есть вы можете получить больший узел за ту же или более низкую цену, а увеличенная емкость может быть использована контейнерными рабочими нагрузками Kubernetes.

Как запустить Kubernetes на EC2 Spot? Существует несколько вариантов: использовать сторонний сервис, такой как SpotInst (теперь он называется Spot, не спрашивайте меня, почему), или просто добавить Spot AutoScalingGroup (ASG) в ваш кластер. Например, вот фрагмент CloudFormation для оптимизированной по емкости Spot ASG с несколькими типами экземпляров:

MySpotAutoScalingGroup: Properties:   HealthCheckGracePeriod: 300   HealthCheckType: EC2   MixedInstancesPolicy:     InstancesDistribution:       OnDemandPercentageAboveBaseCapacity: 0       SpotAllocationStrategy: capacity-optimized     LaunchTemplate:       LaunchTemplateSpecification:         LaunchTemplateId: !Ref LaunchTemplate         Version: !GetAtt LaunchTemplate.LatestVersionNumber       Overrides:         - InstanceType: "m4.2xlarge"         - InstanceType: "m4.4xlarge"         - InstanceType: "m5.2xlarge"         - InstanceType: "m5.4xlarge"         - InstanceType: "r4.2xlarge"         - InstanceType: "r4.4xlarge"   LaunchTemplate:     LaunchTemplateId: !Ref LaunchTemplate     Version: !GetAtt LaunchTemplate.LatestVersionNumber   MinSize: 0   MaxSize: 100   Tags:   - Key: k8s.io/cluster-autoscaler/node-template/label/aws.amazon.com/spot     PropagateAtLaunch: true     Value: "true"


Некоторые замечания по использованию Spot с Kubernetes:

  • Вам нужно обрабатывать завершения Spot, например путем слива узла на остановке инстанса
  • Zalando использует форк официального автомасштабирования кластера с приоритетами пула узловl
  • Узлы Spot можно заставить принимать регистрации рабочих нагрузок для запуска в Spot


Резюме


Я надеюсь, что вы найдете некоторые из представленных инструментов полезными для сокращения вашего счета за облачные вычисления. Вы можете найти большую часть содержимого статьи также в моем выступлении на DevOps Gathering 2019 на YouTube и в виде слайдов.
Каковы ваши лучшие практики для экономии облачных затрат на Kubernetes? Пожалуйста, дайте знать в Twitter (@try_except_).


[1] Фактически менее 3 виртуальных ЦП останутся пригодными для использования, поскольку пропускная способность узла уменьшается за счет зарезервированных системных ресурсов. Kubernetes различает физическую емкость узла и выделяемые ресурсы (Node Allocatable).

[2] Пример расчета: один экземпляр m5.large с 8 GiB памяти составляет ~84 доллара США в месяц (eu-central-1, On-Demand), т.е. блокировка 1/8 узла составляет примерно ~10 долларов США в месяц.

[3] Есть еще много способов уменьшить ваш EC2 счет, например, зарезервированные экземпляры, план сбережений и т. д. я не буду освещать эти темы здесь, но вы обязательно должны про них разузнать!



Узнать подробнее о курсе.


Подробнее..

Перевод Обратная связь по грантам памяти (memory grant feedback) в SQL Server 2019

25.06.2020 18:18:39 | Автор: admin
Всем привет! В преддверии старта курса MS SQL Server разработчик, подготовили для вас еще один интересный перевод.



Если оптимизатор неправильно вычисляет необходимый объем памяти для выполнения запроса, то это будет либо пустая трата памяти, которую мог бы использовать другой процесс, либо будет слив данных на диск (disk spill). Для решения этой проблемы Microsoft добавила обратную связь по грантам памяти (Memory Grant Feedback). В этой статье Грег Ларсен (Greg Larsen) объясняет, как это работает.

Обратная связь по грантам памяти (Memory Grant Feedback) в более ранних версиях SQL Server (до SQL Server 2019 или 15.x) была реализована только для запросов, выполняющихся в пакетном режиме (batch mode). Запросы в пакетном режиме выполняют сканирование и вычисление до 900 строк одновременно, в отличие от запросов в строковом режиме (row mode), когда за раз обрабатывается только одна строка. В версии 15.x обратная связь по грантам памяти была расширена для поддержки запросов в строковом режиме.

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

Функциональность Memory Grant Feedback (и в пакетном, и в строковом режимах) является частью семейства функций Intelligent Query Processing (IQP, интеллектуальная обработка запросов). На рисунке 1 представлена диаграмма, показывающая все средства IQP, присутствующие в Azure SQL Database и SQL Server 2019, а также функции, которые изначально были частью Adaptive Query Processing (адаптивной обработки запросов), включенной в предыдущие версии Azure SQL Database и SQL Server 2017.


Рисунок 1. Intelligent Query Processing (интеллектуальная обработка запросов)

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

Смотрим как гранты памяти изменяются со временем


Чтобы посмотреть, как изменяется выделение памяти со временем, будем выполнять один и тот же запрос несколько раз. При каждом запуске будем смотреть сколько памяти было выделено и сколько использовано, а также дополнительную информацию обратной связи, помогающую Database Engine корректировать требования к памяти. Для теста будем использовать базу данных WideWorldImporters, которую можно скачать отсюда. Тестовый запрос для проверки обратной связи по грантам памяти в строковом режиме приведен в листинге 1.

USE WideWorldImporters;GOSELECT * FROM Sales.OrdersORDER BY OrderDate;

Листинг 1. Тестовый запрос

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

Почему оценка необходимой памяти может быть ошибочной


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

  • Кардинальность таблиц, участвующих в запросе
  • Выбираемые колонки
  • Ориентировочный размер строки
  • Есть ли необходимость в сортировке и / или соединении (join) данных
  • Выполняется ли запрос параллельно


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

SQL Server не всегда хорошо справляется с вычислением объема памяти с первого раза. Устаревшая или неточная статистика наиболее распространенная причина, из-за которой SQL Server вычисляет неправильный объем памяти. Но даже если статистика верна, SQL Server может переоценить или недооценить необходимый объем памяти по какой-либо другой причине. Одна из этих причин заключается в том, что SQL Server неправильно оценивает размер строки (Estimated Row Size) для возвращаемых столбцов. Далее на примере мы увидим как завышение размера строки приводит к тому, что запрос получает предупреждение об избыточном выделении памяти (excessive grant warning) из-за трех столбцов NVARCHAR (MAX), которые всегда равны NULL.

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

Настройка для первого запуска


Для того чтобы продемонстрировать, как со временем выделение памяти подстраивается под запрос, нужно сделать некоторые подготовительные работы. Первое изменить уровень совместимости базы данных WideWorldImporters на 150. Это нужно сделать, так как обратная связь по грантам памяти в строковом режиме (Memory Grant Feedback Row Mode) доступна только для баз данных с уровнем совместимости 150. Код в листинге 2 изменяет уровень совместимости базы данных на 150.

ALTER DATABASE WideWorldImporters SET COMPATIBILITY_LEVEL = 150;GO

Листинг 2. Установка уровня совместимости на 150

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

USE WideWorldImporters;GOALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;GO

Листинг 3. Очистка кэша процедур

После предварительной настройки можно выполнить запрос первый раз (листинг 1).

Первое выполнение запроса


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

При первом запуске получаем план выполнения, показанный на рисунке 2.


Рисунок 2. План выполнения для первого запуска запроса из листинга 1

Как вы видите, на операторе SELECT есть предупреждающий знак. При наведении курсора мыши на SELECT отображается информация, показанная на рисунке 3.


Рисунок 3. Свойства SELECT при первом запуске первого исполнения.

Для SELECT есть предупреждение ExcessiveGrant. Запросу было выделено 1 234 880 КБ памяти, но он использовал только 11 296 КБ. Это означает, что запросу было выделено гораздо больше памяти, чем требовалось.

В SQL Server 15.x в свойствах оператора SELECT в раздел MemoryGrantInfo были добавлены два новых атрибута: IsMemoryGrantFeedbackAdjusted и LastRequestedMemory. Эти два атрибута обеспечивают обратную связь, необходимую для корректировки выделяемой памяти при последующих выполнениях запроса. Вы можете увидеть эти два новых атрибута, просмотрев MemoryGrantInfo в графическом плане выполнения. Для этого в плане выполнения наведите курсор мыши на значок SELECT, щелкните правой кнопкой мыши и выберите Properties (Свойства) в появившемся меню. Эти новые свойства запроса отображаются в разделе MemoryGrantInfo, показанном на рисунке 4.


Рисунок 4. Информация о выделении памяти

Свойство IsMemoryGrantFeedbackAdjusted при первом выполнении равно NoFirstExecution, а свойство LastRequestedMemory равно нулю. Параметр RequestedMemory имеет значение 1 234 880. Это объем памяти, который был запрошен при выполнении запроса в первый раз. Для того чтобы разобраться как работают новые свойства обратной связи, давайте посмотрим на значения, которые они могут принимать.

Новые свойства обратной связи MemoryGrantInfo


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

Свойство IsMemoryGrantFeedbackAdjusted может принимать пять различных значений, которые перечислены таблице 1.

Таблица 1. Возможные значения IsMemoryGrantFeedbackAdjusted
Значение IsMemoryGrantFeedbackAdjusted Описание
No: firstexecution Обратная связь не используется для первой компиляции и связанным с ней выполнением.
No: accurate grant Если слива данных на диск нет и запрос использует не менее 50% выделенной памяти, то обратная связь по грантам памяти не используется.
No: feedback disabled Если обратная связь непрерывно активируется и происходит постоянное увеличение и уменьшение памяти, то обратная связь для данного запроса отключается.
Yes: adjusting Была применена обратная связь и она может быть подкорректирована при последующих выполнениях.
Yes: stable Была применена обратная связь и объем выделенной памяти стабилен. это означает, что выделенная память для предыдущего запуска совпадает с выделенной памятью для текущего выполнения.


По таблице 1 видно, что наше предыдущее выполнение запроса было первым, так как значение равно FirstExecution.

Свойство LastRequestedMemory показывает объем запрошенной памяти в килобайтах (КБ) при предыдущем выполнении запроса. Поскольку запрос выполнялся впервые, то значение было равным нулю.
Давайте запустим запрос второй раз и посмотрим как будут использоваться эти свойства для улучшения выделения памяти.

Второе выполнение запроса


Как видно на рисунке 5, после второго запуска исчез предупреждающий знак, присутствовавший при первом выполнении.


Рисунок 5. План для второго выполнения запроса

При втором запуске MemoryGrantInfo показывает, что изменились некоторые значения свойств обратной связи, а также значение RequestedMemory. Свойства MemoryGrantInfo для второго запуска показаны на рисунке 6.


Рисунок 6. Свойства MemoryGrantInfo для второго выполнения

Свойство IsMemoryGrantFeedbackAdjusted теперь принимает значение YesAdjusting. Этот статус говорит о том, что для второго выполнения была применена обратная связь. Кроме того, LastRequestedMemory теперь принимает значение 1 234 880 это запрашиваемая память (RequestedMemory) для первого выполнения запроса. Свойство RequestedMemory показывает, что при втором выполнении запроса запрашивается только 21 120 КБ памяти. Это значение значительно меньше объема памяти, запрашиваемого при первом выполнении.

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

Третье выполнение запроса


На рисунке 7 показано значение MemoryGrantInfo для третьего выполнения запроса.


Рисунок 7. Третье выполнение

IsMemoryGrantFeedbackAdjusted теперь равно YesStable. Это означает, было выделено столько же памяти, как и при втором выполнении. Это можно проверить, сравнив значения LastRequestedMemory и RequestedMemory. Они совпадают. Для нашего запроса обратная связь о грантах памяти позволила запросу скорректировать необходимый объем памяти после трех выполнений.

Когда необходимый объем памяти не стабилен


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

Чтобы воспроизвести эту ситуацию, когда SQL Server отключает обратную связь по грантам памяти, выполним несколько раз хранимую процедуру с разными параметрами. Таким образом, при каждом выполнении запрос внутри процедуры будет требовать разного объема памяти из-за разного количества возвращаемых записей, зависящих от параметра. Код хранимой процедуры приведен в листинге 4.

USE WideWorldImporters;GOCREATE OR ALTER PROC TestProc (@KeyValue int)ASSELECT * FROM Sales.OrdersWHERE OrderID > 1 and OrderID < @KeyValueORDER BY OrderDate

Листинг 4. Тестовая хранимая процедура

Хранимая процедура принимает параметр с именем @KeyValue. Код для тестирования хранимой процедуры приведен в листинге 5.

DECLARE @I INT = 1;DECLARE @TestKeyValue INT;WHILE @I < 35BEGINIF @I % 2 = 0 EXEC TestProc @KeyValue = 20000;ELSE EXEC TestProc @KeyValue = 100;SET @I = @I + 1;END

Листинг 5. Код для вызова хранимой процедуры

Взглянув на код в листинге 5, вы видите, что хранимая процедура выполняется 35 раз. При каждом запуске хранимой процедуры значение параметра @KeyValue чередуется между 20 000 и 100. Когда для параметра установлено значение 20 000, запрос возвращает 19 998 строк, но если значение параметра равно 100, то возвращается только 98 строк. Как вы можете догадаться, при каждом выполнении будет требоваться разный объем памяти, потому что количество строк сильно отличается.

Запустим код из листинга 5 в SSMS и посмотрим фактический план выполнения. Видно, что для запусков со второго до 32-го значение IsMemoryGrantFeedbackAdjust было YesAdjusting. Но при 33-ем выполнении SQL Server прекратил попытки корректировать память для хранимой процедуры и отключил обратную связь. На рисунке 8 вы можете увидеть свойства MemoryGrantInfo для 33-го выполнения хранимой процедуры.


Рисунок 8. Обратная связь по выделению памяти отключена при 33-ем выполнении

Как видно, параметр IsMemoryGrantFeedbackAdjusted имеет значение NoFeedbackDisabled. Это означает, что Database Engine не смог использовать обратную связь для получения стабильного выделения памяти для хранимой процедуры и было решено отключить обратную связь для этого запроса. Для всех последующих выполнений хранимой процедуры (после 33-го запуска) обратная связь отключена.

Не всем запросам нужна обратная связь


Иногда SQL Server правильно определяет объем памяти с первого раза, поэтому обратная связь не используется. Давайте посмотрим на примере кода в листинге 6.

USE WideWorldImporters;GOSELECT * FROM Sales.OrdersWHERE OrderID < 3ORDER BY OrderDate;

Листинг 6. Пример с правильным выделением памяти

При запуске получаем следующий план выполнения.


Рисунок 9. План выполнения при запуске кода из листинга 6.

Свойство IsMemoryGrantFeedback показывает, что это первое выполнение. Кроме того, запрос запросил 1024 КБ памяти, что видно в RequestedMemory (рисунок 10).


Рисунок 10. MemoryGrantInfo для первого выполнения запроса

Информация о выделении памяти для второго выполнения показана на рисунке 11.


Рисунок 11. MemoryGrantInfo для второго выполнения

Для второго выполнения IsMemoryGrantFeedbackAdjusted имеет значение NoAccurateGrant. Это означает, что для второго выполнения не потребовалось большее количество памяти, поэтому обратная связь не используется. Это можно проверить, посмотрев на то, что RequestedMemory одинаковая на рисунках 10 и 11.

Отключение Memory Grant Feedback


Если по какой-либо причине вы хотите отключить обратную связь о грантах памяти в строковом режиме (Memory Grant Feedback Row Mode), то для этого есть несколько способов. Первый установить для базы данных уровень совместимости менее 150. С этим способом только одна проблема: также будут отключены все другие функции, которые появились в версии 15.x. Или, вы можете отключить обратную связь на уровне базы данных через опцию ROW_MODE_MEMORY_GRANT_FEEDBACK.

USE WideWorldImporters;GOALTER DATABASE SCOPED CONFIGURATION SET ROW_MODE_MEMORY_GRANT_FEEDBACK = OFF;GO

Листинг 7. Отключение обратной связи по выделению памяти для базы данных

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

USE WideWorldImporters;GOSELECT * FROM Sales.OrdersORDER By  OrderDateOPTION(USE HINT ('DISABLE_ROW_MODE_MEMORY_GRANT_FEEDBACK'));

Листинг 8. Использование HINT для отключения обратной связи

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

Оптимизация вычисления необходимой памяти для запроса


Обратная связь по грантам памяти в пакетном режиме (batch mode) существует уже довольно давно. Но только в версии 15.x эта обратная связь стала доступна для запросов в строковом режиме (row mode). Все, что нужно для включения обратной связи для запросов в строковом режиме это установить уровень совместимости базы данных в 150. Это, конечно, заработает, если вы используете текущую версию Azure SQL Database или SQL Server 2019. Когда включен функционал обратной связи о грантах памяти в строковом режиме, то SQL Server использует информацию о выделении памяти при предыдущих выполнениях кэшированного запроса, чтобы скорректировать выделение памяти для текущего выполнения. Корректировка необходимой памяти с помощью обратной связи при каждом выполнении запроса рано или поздно автоматически приведет к вычислению правильного объема памяти.



Узнать подробнее о курсе.


Подробнее..

Почему вам нужен личный бренд мануал для ленивых

06.07.2020 12:10:38 | Автор: admin


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


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


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


Если лень читать, у меня есть видео на эту тему


Зачем нужен личный бренд


1. Он облегчает поиск вас как специалиста HR-у или рекрутеру. Вас проще найти, сложно потерять и невозможно отказать.


Я думаю, что HeadHunter ужа становится, как Одноклассники, для совсем дубовых ребят. Рекрутеры давно не живут в одном HH, и при поиске кандидатов он не занимает первое место.


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


3. Впечатление вещь сильная.


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


Это только основные причины задуматься о личном бренде, у вас могут быть еще какие-то свои. Например, у кого-то просто может чесаться ЧСВ, а кому-то интересно побыть блогером.


Конечно, не стоит думать, что все это даст вам +300% выхлопа в части дополнительной стоимости, но пользу вы получите в любом случае. Тем более, что


Личный бренд это не сложно


Чтобы его поддерживать, вам даже не нужно дуться и носить пиджаки (если только вы не метите в определенные круги).


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


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


Отношение к личному бренду


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


1. Ребята, которые любят крайности.


Ерунда это все, пустословы, аррргхх! говорят одни. Я звязда! говорят другие. Эта статья не для них. Первым в принципе невозможно угодить, а вторым нужны немного другие инструменты.


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


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


3. Ребята, которые хотят себя показать, активные, динамичные, коммуникабельные. Их цель не просто почистить свой образ, а управлять им конкретно.


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


Соцсети и GitHub


Банально? Да. Но давайте к сути.


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


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


2. О боже, опять соцсети! Скорее всего и аккаунты у вас закрыты.


Не парьтесь. Если вам лень и некогда, делайте это СУХО. Например, вы были на конфе, ходили там, ели булочки, слушали умных людей и попались фотографу. Возьмите фотку, запостите в LinkedInи напишите Конференция + название. ВСЕ. Вот ваш личный бренд.


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


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


Конференции


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


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


Преподавание


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


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


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


Мое выступление на тему проблем в образовании и зачем крутым спецам учить других (за качество извиняюсь)

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


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


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


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


Ведение блогов


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


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


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


Начать, в любом случае, просто: выбираете удобную площадку, интересную тему и пишите-пишите-пишите (ну или снимаете-снимаете-снимаете).


Заключение


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


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


Если у вас остались вопросы, задавайте в комментариях. А если понравилась статья, то можно и плюсануть :) Спасибо за внимание!


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

Перевод Простое управление ACL в Symfony

26.06.2020 16:08:22 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Symfony Framework.



Не секрет, что ACL (access control lists) могут быть достаточно сложны в использовании. Поскольку Symfony рекомендует избирателей (voters) в качестве альтернативы ACL, я недавно решил, что напишу свой собственный простой в использовании Symfony 5 бандл для управления списками контроля доступа (ACL) в моих приложениях.

programarivm/easy-acl-bundle изначально был написан для использования в JWT-аутентифицированном API для одностраничных приложений (single page applications SPA), но он также может быть полезен в ряде других сценариев, когда не требуется Security компонент что в большинстве случаев, по моему скромному мнению, особенно подходит для сеансов обработки многостраничных приложений (multi-page applications MPA).
EasyAclBundle

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

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

// src/EventSubscriber/TokenSubscriber.phpnamespace App\EventSubscriber;use App\Controller\AccessTokenController;use Doctrine\ORM\EntityManagerInterface;use Firebase\JWT\JWT;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpKernel\Event\ControllerEvent;use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;use Symfony\Component\HttpKernel\KernelEvents;class TokenSubscriber implements EventSubscriberInterface{    public function __construct(EntityManagerInterface $em)    {        $this->em = $em;    }    public function onKernelController(ControllerEvent $event)    {        $controller = $event->getController();        // когда класс контроллера определяет несколько action методов, контроллер        // возвращается как [$controllerInstance, 'methodName']        if (is_array($controller)) {            $controller = $controller[0];        }        if ($controller instanceof AccessTokenController) {            $jwt = substr($event->getRequest()->headers->get('Authorization'), 7);            try {                $decoded = JWT::decode($jwt, getenv('JWT_SECRET'), ['HS256']);            } catch (\Exception $e) {                throw new AccessDeniedHttpException('Whoops! Access denied.');            }            $user = $this->em->getRepository('App:User')                        ->findOneBy(['id' => $decoded->sub]);            $identity = $this->em->getRepository('EasyAclBundle:Identity')                            ->findBy(['user' => $user]);            $rolename = $identity[0]->getRole()->getName();            $routename = $event->getRequest()->get('_route');            $isAllowed = $this->em->getRepository('EasyAclBundle:Permission')                            ->isAllowed($rolename, $routename);            if (!$isAllowed) {                throw new AccessDeniedHttpException('Whoops! Access denied.');            }        }    }    public static function getSubscribedEvents()    {        return [            KernelEvents::CONTROLLER => 'onKernelController',        ];    }}


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

...$user = $this->em->getRepository('App:User')        ->findOneBy(['id' => $decoded->sub]);$identity = $this->em->getRepository('EasyAclBundle:Identity')            ->findBy(['user' => $user]);$rolename = $identity[0]->getRole()->getName();$routename = $event->getRequest()->get('_route');$isAllowed = $this->em->getRepository('EasyAclBundle:Permission')            ->isAllowed($rolename, $routename);...


Достаточно только двух easy ACL-репозиториев (Identity и Permission) для определения того, может ли пользователь получить доступ к текущему маршруту.

Конфигурация


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

# config/routes.yamlapi_post_create:    path:       /api/posts    controller: App\Controller\Post\CreateController::index    methods:    POSTapi_post_delete:    path:       /api/posts/{id}    controller: App\Controller\Post\DeleteController::index    methods:    DELETEapi_post_edit:    path:       /api/posts/{id}    controller: App\Controller\Post\EditController::index    methods:    PUT


А также разрешений:

# config/packages/programarivm_easy_acl.yamlprogramarivm_easy_acl:  target: App\Entity\User  permission:    -      role: Superadmin      routes:        - api_post_create        - api_post_delete        - api_post_edit    -      role: Admin      routes:        - api_post_create        - api_post_edit    -      role: Basic      routes:        - api_post_create


Итак, теперь, если ваша схема базы данных обновлена:

php bin/console doctrine:schema:update --force


Четыре пустые таблицы будут добавлены в вашу базу данных:

  • easy_acl_identity
  • easy_acl_permission
  • easy_acl_role
  • easy_acl_route


Эта четверка идет рука об руку со следующими сущностями:

  • Programarivm\EasyAclBundle\Entity\Identity
  • Programarivm\EasyAclBundle\Entity\Permission
  • Programarivm\EasyAclBundle\Entity\Role
  • Programarivm\EasyAclBundle\Entity\Route


И репозиториями:

  • Programarivm\EasyAclBundle\Repository\IdentityRepository
  • Programarivm\EasyAclBundle\Repository\PermissionRepository
  • Programarivm\EasyAclBundle\Repository\RoleRepository
  • Programarivm\EasyAclBundle\Repository\RouteRepository


Наконец, консольная команда easy-acl:setup предназначена для заполнения таблиц easy ACL.

php bin/console easy-acl:setupThis will reset the ACL. Are you sure to continue? (y) y


Консоль MySQL:

mysql> select * from easy_acl_identity;Empty set (0.01 sec)mysql> select * from easy_acl_permission;+----+------------+-----------------+| id | rolename   | routename       |+----+------------+-----------------+|  1 | Superadmin | api_post_create ||  2 | Superadmin | api_post_delete ||  3 | Superadmin | api_post_edit   ||  4 | Admin      | api_post_create ||  5 | Admin      | api_post_edit   ||  6 | Basic      | api_post_create |+----+------------+-----------------+6 rows in set (0.00 sec)mysql> select * from easy_acl_role;+----+------------+| id | name       |+----+------------+|  1 | Superadmin ||  2 | Admin      ||  3 | Basic      |+----+------------+3 rows in set (0.00 sec)mysql> select * from easy_acl_route;+----+-----------------+---------+-----------------+| id | name            | methods | path            |+----+-----------------+---------+-----------------+|  1 | api_post_create | POST    | /api/posts      ||  2 | api_post_delete | DELETE  | /api/posts/{id} ||  3 | api_post_edit   | PUT     | /api/posts/{id} |+----+-----------------+---------+-----------------+3 rows in set (0.00 sec)


Добавление идентификаторов пользователей


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

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

// src/DataFixtures/EasyAcl/IdentityFixtures.phpnamespace App\DataFixtures\EasyAcl;use App\DataFixtures\UserFixtures;use Doctrine\Bundle\FixturesBundle\Fixture;use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface;use Doctrine\Common\DataFixtures\DependentFixtureInterface;use Doctrine\Common\Persistence\ObjectManager;use Programarivm\EasyAclBundle\EasyAcl;use Programarivm\EasyAclBundle\Entity\Identity;class IdentityFixtures extends Fixture implements FixtureGroupInterface, DependentFixtureInterface{    private $easyAcl;    public function __construct(EasyAcl $easyAcl)    {        $this->easyAcl = $easyAcl;    }    public function load(ObjectManager $manager)    {        for ($i = 0; $i < UserFixtures::N; $i++) {            $index = rand(0, count($this->easyAcl->getPermission())-1);            $user = $this->getReference("user-$i");            $role = $this->getReference("role-$index");            $manager->persist(                (new Identity())                    ->setUser($user)                    ->setRole($role)            );        }        $manager->flush();    }    public static function getGroups(): array    {        return [            'easy-acl',        ];    }    public function getDependencies(): array    {        return [            RoleFixtures::class,            UserFixtures::class,        ];    }}


Для получения более подробной информации читайте документацию, которая проведет вас через процесс установки и настройки бандла easy ACL.

На этом все. Был ли этот пост полезен? Я надеюсь, что да. Расскажите нам в комментариях ниже!

Возможно, вас также заинтересует...






Узнать о курсе подробнее.


Подробнее..

Перевод REST API в Symfony (без FosRestBundle) с использованием JWT аутентификации. Часть 1

06.07.2020 18:16:50 | Автор: admin

Перевод статьи подготовлен в преддверии старта курса Symfony Framework.





В первой части статьи мы рассмотрим самый простой способ реализации REST API в проекте Symfony без использования FosRestBundle. Во второй части, которую я опубликую следом, мы рассмотрим JWT аутентификацию. Прежде чем мы начнем, сперва мы должны понять, что на самом деле означает REST.


Что означает Rest?


REST (Representational State Transfer передача состояния представления) это архитектурный стиль разработки веб-сервисов, который невозможно игнорировать, потому что в современной экосистеме существует большая потребность в создании Restful-приложений. Это может быть связано с уверенным подъемом позиций JavaScript и связанных фреймворков.


REST API использует протокол HTTP. Это означает, что когда клиент делает какой-либо запрос к такому веб-сервису, он может использовать любой из стандартных HTTP-глаголов: GET, POST, DELETE и PUT. Ниже описано, что произойдет, если клиент укажет соответствующий глагол.


  • GET: будет использоваться для получения списка ресурсов или сведений о них.
  • POST: будет использоваться для создания нового ресурса.
  • PUT: будет использоваться для обновления существующего ресурса.
  • DELETE: будет использоваться для удаления существующего ресурса.

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


Создание проекта Symfony:


Во-первых, мы предполагаем, что вы уже установили PHP и менеджер пакетов Сomposer для создания нового проекта Symfony. С этим всем в наличии создайте новый проект с помощью следующей команды в терминале:


composer create-project symfony/skeleton demo_rest_api


Создание проекта Symfony


Мы используем базовый скелет Symfony, который рекомендуется для микросервисов и API. Вот как выглядит структура каталогов:



Структура проекта


Config: содержит все настройки бандла и список бандлов в bundle.php.
Public: предоставляет доступ к приложению через index.php.
Src: содержит все контроллеры, модели и сервисы
Var: содержит системные логи и файлы кэша.
Vendor: содержит все внешние пакеты.


Теперь давайте установим некоторые необходимые пакеты с помощью Сomposer:


composer require symfony/orm-packcomposer require sensio/framework-extra-bundle

Мы установили sensio/framework-extra-bundle, который поможет нам упростить код, используя аннотации для определения наших маршрутов.


Нам также необходимо установить symphony/orm-pack для интеграции с Doctrine ORM, чтобы соединиться с базой данных. Ниже приведена конфигурация созданной мной базы данных, которая может быть задана в файле .env.



.env файл конфигурации


Теперь давайте создадим нашу первую сущность. Создайте новый файл с именем Post.php в папке src/Entity.


<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /**  * @ORM\Entity  * @ORM\Table(name="post")  * @ORM\HasLifecycleCallbacks()  */ class Post implements \JsonSerializable {  /**   * @ORM\Column(type="integer")   * @ORM\Id   * @ORM\GeneratedValue(strategy="AUTO")   */  private $id;  /**   * @ORM\Column(type="string", length=100   *   */  private $name;  /**   * @ORM\Column(type="text")   */  private $description;  /**   * @ORM\Column(type="datetime")   */  private $create_date;  /**   * @return mixed   */  public function getId()  {   return $this->id;  }  /**   * @param mixed $id   */  public function setId($id)  {   $this->id = $id;  }  /**   * @return mixed   */  public function getName()  {   return $this->name;  }  /**   * @param mixed $name   */  public function setName($name)  {   $this->name = $name;  }  /**   * @return mixed   */  public function getDescription()  {   return $this->description;  }  /**   * @param mixed $description   */  public function setDescription($description)  {   $this->description = $description;  }  /**   * @return mixed   */  public function getCreateDate(): ?\DateTime  {   return $this->create_date;  }  /**   * @param \DateTime $create_date   * @return Post   */  public function setCreateDate(\DateTime $create_date): self  {   $this->create_date = $create_date;   return $this;  }  /**   * @throws \Exception   * @ORM\PrePersist()   */  public function beforeSave(){   $this->create_date = new \DateTime('now', new \DateTimeZone('Africa/Casablanca'));  }  /**   * Specify data which should be serialized to JSON   * @link https://php.net/manual/en/jsonserializable.jsonserialize.php   * @return mixed data which can be serialized by <b>json_encode</b>,   * which is a value of any type other than a resource.   * @since 5.4.0   */  public function jsonSerialize()  {   return [    "name" => $this->getName(),    "description" => $this->getDescription()   ];  } }

И после этого выполните команду: php bin/console doctrine:schema:create для создания таблицы базы данных в соответствии с нашей сущностью Post.


Теперь давайте создадим PostController.php, куда мы добавим все методы, взаимодействующие с API. Он должен быть помещен в папку src/Controller.


<?php /**  * Created by PhpStorm.  * User: hicham benkachoud  * Date: 02/01/2020  * Time: 22:44  */ namespace App\Controller; use App\Entity\Post; use App\Repository\PostRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; /**  * Class PostController  * @package App\Controller  * @Route("/api", name="post_api")  */ class PostController extends AbstractController {  /**   * @param PostRepository $postRepository   * @return JsonResponse   * @Route("/posts", name="posts", methods={"GET"})   */  public function getPosts(PostRepository $postRepository){   $data = $postRepository->findAll();   return $this->response($data);  }  /**   * @param Request $request   * @param EntityManagerInterface $entityManager   * @param PostRepository $postRepository   * @return JsonResponse   * @throws \Exception   * @Route("/posts", name="posts_add", methods={"POST"})   */  public function addPost(Request $request, EntityManagerInterface $entityManager, PostRepository $postRepository){   try{    $request = $this->transformJsonBody($request);    if (!$request || !$request->get('name') || !$request->request->get('description')){     throw new \Exception();    }    $post = new Post();    $post->setName($request->get('name'));    $post->setDescription($request->get('description'));    $entityManager->persist($post);    $entityManager->flush();    $data = [     'status' => 200,     'success' => "Post added successfully",    ];    return $this->response($data);   }catch (\Exception $e){    $data = [     'status' => 422,     'errors' => "Data no valid",    ];    return $this->response($data, 422);   }  }  /**   * @param PostRepository $postRepository   * @param $id   * @return JsonResponse   * @Route("/posts/{id}", name="posts_get", methods={"GET"})   */  public function getPost(PostRepository $postRepository, $id){   $post = $postRepository->find($id);   if (!$post){    $data = [     'status' => 404,     'errors' => "Post not found",    ];    return $this->response($data, 404);   }   return $this->response($post);  }  /**   * @param Request $request   * @param EntityManagerInterface $entityManager   * @param PostRepository $postRepository   * @param $id   * @return JsonResponse   * @Route("/posts/{id}", name="posts_put", methods={"PUT"})   */  public function updatePost(Request $request, EntityManagerInterface $entityManager, PostRepository $postRepository, $id){   try{    $post = $postRepository->find($id);    if (!$post){     $data = [      'status' => 404,      'errors' => "Post not found",     ];     return $this->response($data, 404);    }    $request = $this->transformJsonBody($request);    if (!$request || !$request->get('name') || !$request->request->get('description')){     throw new \Exception();    }    $post->setName($request->get('name'));    $post->setDescription($request->get('description'));    $entityManager->flush();    $data = [     'status' => 200,     'errors' => "Post updated successfully",    ];    return $this->response($data);   }catch (\Exception $e){    $data = [     'status' => 422,     'errors' => "Data no valid",    ];    return $this->response($data, 422);   }  }  /**   * @param PostRepository $postRepository   * @param $id   * @return JsonResponse   * @Route("/posts/{id}", name="posts_delete", methods={"DELETE"})   */  public function deletePost(EntityManagerInterface $entityManager, PostRepository $postRepository, $id){   $post = $postRepository->find($id);   if (!$post){    $data = [     'status' => 404,     'errors' => "Post not found",    ];    return $this->response($data, 404);   }   $entityManager->remove($post);   $entityManager->flush();   $data = [    'status' => 200,    'errors' => "Post deleted successfully",   ];   return $this->response($data);  }  /**   * Returns a JSON response   *   * @param array $data   * @param $status   * @param array $headers   * @return JsonResponse   */  public function response($data, $status = 200, $headers = [])  {   return new JsonResponse($data, $status, $headers);  }  protected function transformJsonBody(\Symfony\Component\HttpFoundation\Request $request)  {   $data = json_decode($request->getContent(), true);   if ($data === null) {    return $request;   }   $request->request->replace($data);   return $request;  } }

Здесь мы определили пять маршрутов:


GET /api/posts: вернет список постов.



api получения всех постов


POST /api/posts: создаст новый пост.



api добавления нового поста


GET /api/posts/id: вернет пост, соответствующий определенному идентификатору,



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


PUT /api/posts/id: обновит пост.



обновление поста


Это результат после обновления:



пост после обновления


DELETE /api/posts/id: удалит пост.



удаление поста


Это результат получения всех постов после удаления поста с идентификатором 3:



все посты после удаления


Исходный код можно найти здесь


Заключение


Итак, теперь мы понимаем, что такое REST и Restful. Restful API должен быть без состояний. Мы знаем, как создать Restful-приложение, используя HTTP-глаголы. В общем, теперь мы хорошо понимаем REST и готовы профессионально создавать Restful-приложения.


В следующей статье мы рассмотрим, как обеспечить секьюрность API с помощью JWT аутентификации.




Узнать подробнее о курсе Symfony Framework



Подробнее..

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

02.07.2020 16:18:36 | Автор: admin


Автор статьи: Елена Ленсу (Психотерапевт).
Специализации: организационное консультирование, долговременная терапия, работа с травмой, сексология.

Бизнес консультант, ex.HRD Pravo.Tech и Rocket10. Автор статей и преподаватель онлайн-курса IT-Recruiter в OTUS.


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

Критика указание только на недостатки в том, что было сделано.

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

1) Низкая самооценка.

Внутренний лозунг: Я недостаточно хорош!

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

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

Базовая мысль: Я не достаточно хорош, все что делаю плохо.

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

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

Эмоции: печаль, грусть, беспомощность.

2) Синдром самозванца.

Внутренний лозунг: Я недостаточно хорош? Все об этом узнают

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

Человек отрицает свою роль и влияние на ситуации. Синдрому самозванца постоянно сопутствуют тревога и страх: а вдруг разоблачат?

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

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

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

Эмоции: страх, ужас, тревога

3) Неумение выносить чужой дискомфорт.

Внутренний лозунг: Кому-то неприятно и это все из-за меня!

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

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

Реакция на критику: Я все испортил, из-за меня теперь человеку сложно и неприятно, он испытывает дискомфорт.

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

Чувства: вина, страх, печаль, бессилие, беспомощность.

4) Нарциссизм

Внутренний лозунг: Сейчас объясню, почему не правы!

У каждого человека есть нарциссическая часть, она помогает поддерживать самоуважение.

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

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

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

5) Перфекционизм

Внутренний лозунг: Как я мог об этом НЕ подумать?

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

Реакция на критику: Перфекционист сталкивается со своим несовершенством, и в этот момент возникает ужас, тут пропадает возможность быть достаточно хорошим. Это невыносимо больно, жить без такой иллюзии невозможно. Внешняя критика для перфекциониста невыносима, а внутренней он сам себя постоянно изводит:КАК ошибка! Я не идеален. Если ошибка появилась, значит я недостаточно хорошо старался.

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

Эмоции: ужас, разочарование, беспомощность.

Психологическая травма

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

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

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

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

Есть много способов, как с этим работать и жить об этом мы расскажем в новых статьях.



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

Какие опоры бывают:

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


Чек-лист для успокоения


  • комфортно ли я сижу (устойчиво на стуле, ноги упираются в пол)
  • спокойно ли я дышу
  • что чувствую
  • отделяю ли критику от своей личности
  • критика НЕ ОЦЕНКА МЕНЯ
  • неконструктивные слова отскакивают от меня
  • подумай, что обидчику сейчас гораздо тяжелее, чем мне, посочувствуй и отпусти его с миром
  • слышу ли я конкретные кейсы, или только обобщения
  • я в позиции взрослого
  • все свои мысли и описать все свои чувства на бумаге, прежде чем отвечать


Что вы чувствуете? Что вы думаете? Выплесните это на бумагу, а не на человека



2 самых важных вопроса:

1) Что происходит со мной в данный момент?

-что делаю?
-о чем думаю?
-что чувствую?
-как дышу?

2) А чего же я хочу?



Остались вопросы? Задайте их на бесплатном онлайн-вебинаре, в рамках которого наш преподаватель подробно расскажет о курсе.


Подробнее..

Перевод Алгоритм MADDPG OpenAI

29.06.2020 14:12:48 | Автор: admin
Начинаем неделю с продолжения серии статей, подготовленных специально для базового и продвинутого курсов Математика для Data Science.

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




Новый подход


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

  • Нестационарности между независимыми агентами;
  • Экспоненциального роста пространств действий и состояний.


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

Централизованное планирование


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

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

Децентрализованное выполнение


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

OpenAI


Исследователи из OpenAI, Калифорнийского университета в Беркли и Университета Макгилла, представили новый подход к мультиагентным настройкам с помощью Multi-Agent Deep Deterministic Policy Gradient. Такой подход, вдохновленный своим одноагентным аналогом DDPG, использует обучение вида актер-критик и показывает очень многообещающие результаты.

Архитектура


Данная статья предполагает, что вы знакомы с одноагентной версией MADDPG: Deep Deterministic Policy Gradients или DDPG. Чтобы освежить память, вы можете прочитать замечательную статью Криса Юна.

У каждого агента есть пространство наблюдений и непрерывное пространство действий. Также у каждого агента есть три компонента:

  • Сеть актеров, который использует локальные наблюдения для детерминированных действий;
  • Целевая сеть актеров с аналогичным функционалом для стабильного обучения;
  • Сеть критиков, которая использует совместные пары состояние-действие для оценки Q-значений.


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

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


Архитектура MADDPG (Lowe, 2018)

Обучение


Во-первых, MADDPG использует воспроизведение опыта (experience replay) для эффективного off-policy обучения. На каждом промежутке времени агент хранит следующий переход:



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

Обновления критика


Для обновления центрального критика агента мы используем lookahead TD-ошибку:



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

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

Обновления актеров


Подобно одноагентной DDPG мы используем deterministic policy gradient для обновления каждого параметра актера агента.



Где это актер агента.

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

Выводы из политик и ансамбли политик


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



Где мы видим функцию потерь для i-ого агента, оценивающего политику j-ого агента с помощью регуляризатора энтропии. В результате, наше целевое Q-значение становится немного другим, когда мы заменяем действия агента своими прогнозируемыми действиями!



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

Ансамбли политик


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

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



Вернемся на шаг назад


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

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


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

Результаты


MADDPG был апробирован во многих средах. Полный обзор его работы можно найти в статье [1]. Здесь мы поговорим только о задаче кооперативной коммуникации.

Обзор среды


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

Сравнение


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

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

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

Заключение


Вот и все. Здесь мы рассмотрели новый подход к мультиагентному обучению с подкреплением. Конечно, существует бесконечное количество методов, относящихся к MARL, однако MADDPG обеспечивает прочный фундамент для методов, которые решают самые глобальные проблемы мультиагентных систем.

Источники


[1] R. Lowe, Y. Wu, A. Tamar, J. Harb, P. Abbeel, I. Mordatch, Multi-Agent Actor-Critic for Mixed Cooperative-Competitive Environments (2018).



Список полезных статей






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


Подробнее..

Перевод Нагрузочное тестирование производительности вашего сайта

19.06.2020 20:14:58 | Автор: admin
И снова здравствуйте. В июле Otus запускает новый курс Нагрузочное тестирование. В преддверии старта курса традиционно делимся с вами полезным материалом.




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

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

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

Лучшие советы для успешного тестирования производительности


1. Запускайте нагрузочные тесты из производственной среды


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

2. Масштабируйте свои тесты от маленького к большому и далее к огромному


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

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

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



3. Запланируйте тесты


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

Нагрузочные тесты нагрузочные тесты предназначены для определения поведения системы при ожидаемой нагрузке.

Стресс-тесты стресс-тесты могут помочь вам понять пределы прочности системы.

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

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

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

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

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

4. Мониторинг внутренних результатов нагрузочного теста


Нагрузочное тестирование позволяет просматривать и анализировать KPI производительности, такие как время отклика и латентность, а также корреляции между ними. Но также важно просмотреть ключевые показатели эффективности, такие как Cache Hits и DB Queries, просмотреть лог ошибок на предмет исключений, а также просмотреть стандартные характеристики оборудования, такие как загрузка ЦП/памяти/сети и состояние автоматического масштабирования.

Различные решения расширяют возможности анализа результатов испытаний. DX APM, New Relic, App Dynamics и другие решения обеспечивают мониторинг производительности приложений и мониторинг конечных пользователей, а Amazon Cloud Watch отслеживает облачные ресурсы AWS.

5. Включите отслеживание производительности конечного пользователя в бэкэнд-тестирование


Автоматический или вручную анализируйте то, что испытывают ваши пользователи, благодаря уникальной функции BlazeMeter мониторингу опыта конечных пользователей. Новые возможности функционального тестирования выполняют тест Selenium в фоновом режиме, пока выполняется нагрузочный тест, через Taurus. Тест Selenium создает Waterfall Report, который показывает, что пользователь будет видеть в своем веб-браузере в разные моменты во время нагрузочного теста. Это может быть особенно полезно при отладке, например, из-за того, что определенная страница не была загружена должным образом с точки зрения пользователя в определенный момент нагрузочного теста.

6. Настройте резервные серверы и локации


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

7. Проверьте ваши сторонние интеграции


Когда вы вносите изменения в свое приложение или сайт, вы не просто влияете на свой собственный продукт. Вы также можете влиять на сторонние сценарии в своем приложении или на сайте или же можете вызвать сбой сторонних устройств и серверов, если не подготовите их должным образом. Например, для разных CDN требуются разные подходы, а для балансировки нагрузки AWS (ELB) требуется прогрев перед балансировкой.

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

8. Внедрить мониторинг API


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

Скрытый текст
Хотите прокачать свое тестирование? Подпишитесь на бесплатную онлайн-аккредитацию в университете BlazeMeter здесь.

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



Узнать подробнее о курсе.


Подробнее..

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

05.07.2020 02:06:52 | Автор: admin
Данная статья написана специально для OTUS преподавателем курса QA Lead Анастасией Шариковой.





Всем привет! Меня зовут Анастасия Шарикова, я руковожу отделом тестирования в Bookmate и веду телеграм канал Yet another QA.

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

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

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

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

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

Основные параметры, влияющие на подбор:


  • Внешняя аналитика: тут нам на помощь могут прийти как международные подборки по самым популярным устройствам (такие, как, например deviceatlas.com), так и банальные варианты типа сортировки в яндекс.маркете по самым популярным устройствам. Тут важно не купиться на удочку самых лучших телефонов, т.к мнение экспертов зачастую очень расходится с мнением обычных потребителей. Главное помнить про то, на какую страну и ЦА ориентирован ваш продукт, и основываться на этом условии.
  • Внутренняя аналитика: в этом случае у нас огромное количество вариантов, на что можно опираться, к тому же это самые четкие данные и именно по нашему продукту. Что же мы тут можем использовать? Данные систем аналитики, таких как Firebase или информацию по устройствам из Google Play. И важно не забывать брать в расчет не только устройства и оси, которыми пользуются ваши сотрудники, но и те, на которых система чаще всего ловит ошибки и креши.
  • Тенденции на рынке: каждый месяц на рынок выходят новые игроки и устройства, появляются обновления осей и новые лидеры рынка, и все это важно учитывать. Примеры то, насколько стало больше за последний год устройств со шторкой/бровкой или санкции США против Huawei.


Не забываем про особенности нашей аудитории:


Всегда важно помнить об особенностях конкретно вашего продукта и его ЦА и стараться избегать субъективности даже если вам кажется, что iPhone 11 Pro венец творения компании Apple, это не принесет вам особой пользы в работе, если аудитория вашего приложения для обработки фотографий школьники, которым родители подарили шестой или седьмой айфон. Это же работает и в обратную сторону если вы знаете, что вашим сервисом пользуются обеспеченные люди и оно будет установлено в основном на iPad Pro новейшей модели то придется раскошелиться на него, иначе жди беды.
Особенно важно заметить про страны пользования почти у всех стран есть свои фишки, так что аудитория приложения для условной Индии в среднем будет отличаться от пользователей из Скандинавии.

Важные особенности и фишки на примере iOS и Android:


Конечно, в рамках статьи не охватить все-все сложности и особенности, но я постараюсь упомянуть основные:

iOS


  • В сравнении с андроидом, мало устройств, и они не так уж и часто выходят, аналогично и с осями, которые надо учитывать.
  • Проще держать адекватный усредненный набор типов экранов и не забывать что у некоторых есть retina, это может быть важно для некоторых типов тестов. Но, конечно, не всегда. Тем не менее, основные баги по верстке можно словить на комбинации четырех-пяти айфонов от пятого до одиннадцатого. И не забывайте про шторку!
  • Учитывайте, какие вы поддерживаете версии iOS и старайтесь сделать так, чтобы они равномерно распределялись по устройствам.
  • Не забывайте про магию Split View режима и старайтесь держать хотя бы одно устройство, которое его поддерживает
  • Проблемой при закупке может всегда возникнуть цена, особенно, если вы стараетесь выпускать адаптированные версии в первую же неделю продаж но, с другой стороны айфоны и долго не протухают, так что это можно считать долгосрочным вложением. Конечно, кто-то тут может со мной поспорить, но на моей практике именно техника Apple жила дольше при постоянном использовании для нужд тестирования.


Android


  • Очень много устройств и это боль. И тут точно никуда без аналитики потому что именно на ней и должна в случае андроида оцениваться ваша аудтория, иначе придется покупать что попало, а это не приводит к продуктивным результатам. Опять же, есть соблазн тестировать на том, что модно, современно и быстро работает, но если ваши юзеры сидят на китайских Oppo то вы можете и не узнать, что там, оказывается, ничего и не запускается.
  • Учитывайте особенности оболочек андроида и сторов особенно внимательно надо работать с теми, которые отключают по умолчанию сервисы Google Play, в том числе и стор. Старайтесь держать в парке разные варианты, в том числе и голый андроид.
  • Если с планшетами в Apple все довольно просто, то в андроиде это чистое безумие, потому что большинство из них имеют старые оси, плохого качества экраны и очень медленное железо. Конечно, этого и стоило ожидать от планшетов за 1999 рублей, но если ваша аудитория ими пользуется, а вы делаете тяжелую игрушку, то ее может вырубать прямо на старте. Пример из жизни: компания, в которой я работала, заключила контракт с одним из производителей телефонов о том, что они предустанавливают наше приложение к ним, но когда телефоны пришли в офис оказалось, что в них настолько мало памяти, что не запускаются даже предустановленные приложения из коробки. Пришлось, конечно, упрощать наш сервис.
  • Помните, что несмотря на традиционное отношение к андроиду, как дешевым телефонам, в последние годы их флагманы стоят сравнимо с флагманами Apple, а то и больше, к тому же у них часто появляются такие экспериментальные особенности, как скошенные экраны, раскладушки и прочее.


Где покупать?


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

  • Официальные представители: да, часто это может быть дороже, но зато скорее всего это более надежно и лучше гарантия. И лайфхак для тех, кто дочитал до этой части статьи: не всегда, но часто, если написать письмо в представительство определенного производителя о том, насколько вам нужно определенное устройство, объяснив, как вы будете его использовать, вам могут выслать его или бесплатно и навсегда, или во временное пользование. А это часто очень актуально.
  • Розничные магазины: тут я объединяю все магазины, которые продают не левак, с чеками и гарантией, например, своей. Серый не всегда плохой, особенно это может касаться айфонов, например. Главное покупать в проверенных местах, а не в палатке на рынке.
  • Avito и прочие: конечно, тут я объединяю все варианты покупки б/у у частников. Конечно, этого стоит избегать, но если вы осознаете, что вам кровь из носа нужен телефон, который не выпускают уже 3 года, а ваши юзеры упорно им пользуются то иногда стоит пойти на риск.
  • Сотрудники: и еще один лайфхак если спросить у ваших коллег, то наверняка выяснится, что у пары-тройки сотрудников в тумбочке валяется ненужный телефон, который они благородно могут отдать во временное или бессрочное пользование вашему отделу!


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



Узнать подробнее о курсе QA Lead от OTUS.


Подробнее..

Перевод Настраиваем DRBD для репликации хранилища на два CentOS 7 сервера

06.07.2020 02:17:13 | Автор: admin
Перевод статьи подготовлен в преддверии старта курса Администратор Linux. Виртуализация и кластеризация.



DRBD (Distributed Replicated Block Device распределённое реплицируемое блочное устройство) представляет собой распределенное, гибкое и универсально реплицируемое решение хранения данных для Linux. Оно отражает содержимое блочных устройств, таких как жесткие диски, разделы, логические тома и т.д. между серверами. Оно создает копии данных на двух устройствах хранения для того, чтобы в случае сбоя одного из них можно было использовать данные на втором.

Можно сказать, что это нечто вроде сетевой конфигурации RAID 1 с дисками, отражаемыми на разные сервера. Однако оно работает совсем не так, как RAID (даже сетевой).

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

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

Тестовая среда


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

  • Узел 1: 192.168.56.101 tecmint.tecmint.lan
  • Узел 2: 192.168.56.102 server1.tecmint.lan


Шаг 1: Установка пакетов DRBD


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

DRBD может быть установлен из ELRepo или EPEL. Начнем с импорта ключа подписи пакета ELRepo и подключения репозитория на обоих узлах, как показано ниже.

# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org# rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm


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

# yum install -y kmod-drbd84 drbd84-utils


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

# semanage permissive -a drbd_t

Кроме того, если в вашей системе работает файрвол (firewalld), вам необходимо добавить порт DRBD 7789, чтобы разрешить синхронизацию данных между двумя узлами.

Запустите эти команды для первого узла:

# firewall-cmd --permanent --add-rich-rule='rule family="ipv4"  source address="192.168.56.102" port port="7789" protocol="tcp" accept'# firewall-cmd --reload


Затем запустите эти команды для второго узла:

# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.56.101" port port="7789" protocol="tcp" accept'# firewall-cmd --reload


Шаг 2. Подготовка низкоуровневого хранилища


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

Для этой статьи мы создадим тестовое блочное устройство размером 2 ГБ с помощью команды dd.

# dd if=/dev/zero of=/dev/sdb1 bs=2024k count=1024


Предположим, что это неиспользуемый раздел (/dev/sdb1) на втором блочном устройстве (/dev/sdb), подключенном к обоим узлам.

Шаг 3. Настройка DRBD


Основной файл конфигурации DRBD /etc/drbd.conf, а дополнительные файлы конфигурации можно найти в каталоге /etc/drbd.d.

Чтобы реплицировать хранилище, нам нужно добавить необходимые для этого конфигурации в файл /etc/drbd.d/global_common.conf, который содержит глобальные и общие разделы конфигурации DRBD, а определять ресурсы нам нужно в .res файлах.

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

# mv /etc/drbd.d/global_common.conf /etc/drbd.d/global_common.conf.orig# vim /etc/drbd.d/global_common.conf 


Добавьте в оба файла следующие строки:

global { usage-count  yes;}common { net {  protocol C; }}


Сохраните файл, а затем закройте редактор.

Давайте ненадолго остановимся на строке protocol C. DRBD поддерживает три различных режима репликации (т.е. три степени синхронности репликации), а именно:

  • protocol A: протокол асинхронной репликации; чаще всего используется в сценариях репликации на больших расстояниях.
  • protocol B: протокол полусинхронной репликации или протокол синхронной памяти.
  • protocol C: обычно используется для узлов в сетях с небольшими расстояниями; это безусловно, наиболее часто используемый протокол репликации в настройках DRBD.


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

Шаг 4. Добавление ресурса


Ресурс (Resource) это собирательный термин, который относится ко всем аспектам конкретного реплицируемого набора данных. Мы определим наш ресурс в файле /etc/drbd.d/test.res.

Добавьте следующее в файл на обоих узлах (не забудьте заменить переменные фактическими значениями для вашей среды).

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

resource test {        on tecmint.tecmint.lan { device /dev/drbd0;       disk /dev/sdb1;        meta-disk internal;                address 192.168.56.101:7789;        }        on server1.tecmint.lan  {device /dev/drbd0;        disk /dev/sdb1;        meta-disk internal;                address 192.168.56.102:7789;        }}}


где:

  • on hostname: раздел on, к которому относится вложенный оператор конфигурации.
  • test: это имя нового ресурса.
  • device /dev/drbd0: указывает новое виртуальное блочное устройство, управляемое DRBD.
  • disk /dev/sdb1: это раздел блочного устройства, который является резервным устройством для устройства DRBD.
  • meta-disk: определяет, где DRBD хранит свои метаданные. Internal означает, что DRBD хранит свои метаданные на том же физическом низкоуровневом устройстве, что и фактические данные на продакшене.
  • address: указывает IP-адрес и номер порта соответствующего узла.


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

Например, приведенная выше конфигурация может быть реструктурирована в:

resource test {device /dev/drbd0;disk /dev/sdb1;        meta-disk internal;        on tecmint.tecmint.lan { address 192.168.56.101:7789;        }        on server1.tecmint.lan  {address 192.168.56.102:7789;        }}


Шаг 5. Инициализация и запуск ресурса


Для взаимодействия с DRBD мы будем использовать следующие инструменты администрирования (которые взаимодействуют с модулем ядра для настройки и администрирования ресурсов DRBD):

  • drbdadm: инструмент администрирования высокого уровня DRBD.
  • drbdsetup: инструмент администрирования более низкого уровня для подключения устройств DRBD к их устройствам резервного копирования, настройки пар устройств DRBD для отражения их устройств резервного копирования и для проверки конфигурации работающих устройств DRBD.
  • Drbdmeta: инструмент управления метаданными.

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

# drbdadm create-md test



Инициализация хранилища метаданных

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

# drbdadm up test


Теперь, если вы запустите команду lsblk, вы заметите, что устройство/том DRBD drbd0 связан с резервным устройством /dev/sdb1:

# lsblk



Список блочных устройств

Чтобы отключить ресурс, запустите:

# drbdadm down test


Чтобы проверить состояние ресурса, выполните запустите следующую команду (обратите внимание, что на этом этапе ожидается состояние дисков Inconsistent/Inconsistent):

# drbdadm status testOR# drbdsetup status test --verbose --statistics #for  a more detailed status



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


Шаг 6: Установка основного ресурса/источника начальной синхронизации устройств


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

Запустите следующую команду только на одном узле, чтобы начать первоначальную полную синхронизацию:

# drbdadm primary --force test# drbdadm status test



Установка основного узла в качестве начального устройства
После завершения синхронизации состояние обоих дисков должно быть UpToDate.

Шаг 7: Тестирование DRBD сетапа


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

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

# mkfs -t ext4 /dev/drbd0



Создаем файловую систему на томе Drbd

Затем смонтировать ее как показано (вы можете дать точке монтирования подходящее имя):

# mkdir -p /mnt/DRDB_PRI/# mount /dev/drbd0 /mnt/DRDB_PRI/


Теперь скопируйте или создайте какие-нибудь файлы в указанной выше точке монтирования и сделайте длинный список с помощью команды ls:

# cd /mnt/DRDB_PRI/# ls -l 



Вывести список содержимого основного тома Drbd

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

# umount /mnt/DRDB_PRI/# cd# drbdadm secondary test


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

# drbdadm primary test# mkdir -p /mnt/DRDB_SEC/# mount /dev/drbd0 /mnt/DRDB_SEC/# cd /mnt/DRDB_SEC/# ls  -l 



Проверка сетапа DRBD, работающего на вторичном узле.

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

# man drbdadm# man drbdsetup# man drbdmeta


Справка: Руководство пользователя DRBD.

Резюме


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



Узнать подробнее о курсе.


Подробнее..

Перевод Распределенное обучение XGBoost и параллельное прогнозирование с Apache Spark

24.06.2020 14:16:49 | Автор: admin
Привет, хабр! Уже в конце июля Otus запускает новый курс Промышленный ML на больших данных. Традиционно, в преддверии старта нового курса, мы подготовили для вас перевод полезного материала.



Общие сведения


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



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

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

Чтобы обойти это ограничение Тяньцзи Ченом и Карлосом Гестрином было предложено улучшение алгоритма градиентного бустинга, которое называется XGBoost, что расшифровывается как Extreme Gradient Boosting или экстремальный градиентный бустинг. Это своего рода градиентный бустинг на стероидах, который используется в основном для классификации, но также порой для регрессии и ранжирования.

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

В последнее время XGBoost обрел большую популярность и выиграл множество соревнований по машинному обучению в Kaggle. Считается, что он обладает большой вычислительной мощностью и точностью.



XGBoost и Apache Spark


Во время стандартного workflow в ML используются такие системы как Spark для создания пайплайна машинного обучения, где вы предварительно обрабатываете и чистите данные, а затем результат передается на этап машинного обучения, зачастую с помощью Spark MLlib, если вы уже используете Spark.

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

Встречайте XGBoost4J-Spark проект, который объединяет XGBoost и Apache Spark, добавляя XGBoost к фреймворку Apache Spark MLlib.

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



Чтобы начать писать приложение с машинным обучением на XGBoost4J-Spark, вам нужно сначала добавить соответствующую зависимость:

<dependency>    <groupId>ml.dmlc</groupId>    <artifactId>xgboost4j-spark</artifactId>    <version>0.90</version></dependency>


Подготовка данных (пример с ирисами)


Как говорилось ранее, XGBoost4J-Spark позволяет подогнать данные под интерфейс XGBoost.

Как только мы считаем датасет Цветы Ириса в DataFrame, нам нужно будет:

  • Преобразовать столбцы из String к Double;
  • Объединить столбцы признаков в вектора, чтобы данные соответствовали интерфейсу фреймворка машинного обучения Spark.


import org.apache.spark.ml.feature.StringIndexerimport org.apache.spark.ml.feature.VectorAssemblerval stringIndexer = new StringIndexer().  setInputCol("class").  setOutputCol("classIndex").  fit(irisDF)val labelTransformed = stringIndexer.transform(irisDF).drop("class")val vectorAssembler = new VectorAssembler().  setInputCols(Array("sepal length", "sepal width", "petal length", "petal width")).  setOutputCol("features")val xgbInput = vectorAssembler.transform(labelTransformed).select("features", "classIndex")


В DataFrame выше в результате будут два столбца, features: вектор представляющий признаки ириса и classIndex: лейбл типа Double. Такой DataFrame можно спокойно скормить обучающему движку XGBoost4J-Spark.

Распределенное обучение


import ml.dmlc.xgboost4j.scala.spark.XGBoostClassifierval xgbClassifier = new XGBoostClassifier().      setFeaturesCol("features").      setLabelCol("classIndex").      setObjective("multi:softmax")      setMaxDepth(2).      setNumClass(3).      setNumRound(100).      setNumWorkers(10).


Полный список параметров XGBoost вы можете найти здесь. Обратите внимание, что в XGBoost4J-Spark вы также можете использовать camelСase, как в примере выше.

Заметки:


  1. multi:softmax означает, что мы делаем многоклассовую классификацию с помощью функции softmax. Для этого нужно задать количество классов с помощью параметра num_class.
  2. max_depth это максимальная глубина дерева, созданного на каждой итерации бустинга. Увеличение этого значения сделает модель сложной и склонной к переобучению. При обучении глубоких деревьев XGBoost потребляет много памяти.
  3. num_rounds количество раундов бустинга.
  4. Параметр num_workers определяет сколько параллельных воркеров нам нужно при обучении XGBoostClassificationModel. Позже этот параметр станет отложенными тасками в Spark, которые в перспективе будут обрабатываться менеджером кластера (в большинстве случаев YARN).

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

val xgbClassificationModel = xgbClassifier.fit(xgbInput)


Параллельное прогнозирование


XGBoost4j-Spark поддерживает пакетное прогнозирование и точечное прогнозирование.

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

val predictionsDf = xgbClassificationModel.transform(inputDF)predictionsDf.show()+----------------+----------+-------------+-------------+----------+|       features |classIndex|rawPrediction| probability |prediction|+----------------+----------+-------------+-------------+----------+|[5.1,3.5,1.2,.. |       0.0|[3.4556984...|[0.9957963...|       0.0||[4.7,3.2,1.3,.. |       0.0|[3.4556984...|[0.9961891...|       0.0||[5.7,4.4,1.5,.. |       0.0|[3.4556984...|[0.9964334...|       0.0|+----------------+----------+-------------+-------------+----------+


Для точечного прогнозирования модель принимает один вектор.

val features = xgbInput.head().getAs[Vector]("features")val result = xgbClassificationModel.predict(features)


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

На данный момент последняя версия (0.9) XGBoost4J-Spark требует Spark 2.4.x., в основном потому, что теперь в нем используются средства org.apache.spark.ml.param.shared, которые доступны не полностью в более ранних версиях Spark.

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

Узнать больше вы можете в документации XGBoost.

Источники:


XGBoost с CUDA
XGBoost в Spark c GPU и RAPIDS XGboost4J-Spark



Узнать о курсе подробнее.


Подробнее..

Перевод Создаем Gatling скрипты с помощью VS Code

06.07.2020 20:09:26 | Автор: admin

Перевод статьи подготовлен в преддверии старта курса Нагрузочное тестирование.





Предисловие


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


В этом посте мы рассмотрим, как настроить вашу среду разработки Gatling скриптов в VS Code. Мы рассмотрим инструменты сборки Maven и SBT.


Установка Metals


Первое, что нужно сделать, планируете ли вы работать с Maven или SBT, это установить плагин Scala Metals внутри VS Code. Этот плагин позволит языковому серверу Scala работать в VS Code и предоставит типичные функции, которые вы ожидаете от современного IDE.



Установите плагин из VS Code самым стандартным способом, перейдя на вкладку Extensions и выполнив поиск Scala (Metals):



Имея установленный Metals, давайте сначала посмотрим, как запустить Gatling в VS Code с помощью Maven.


Gatling VScode с Maven


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


Затем установите плагин Maven for Java внутри VS Code:



По-прежнему внутри VS Code, откройте Command Pallette (View > Command Pallette) и выберите Maven: Update Maven Archetype Catalog:



Как и следовало ожидать, это обновит каталог доступных архетипов Maven.


Теперь мы хотим создать новый проект Gatling из архетипа Gatling Maven. Для этого сначала откройте Command Pallette и выберите Maven: Create Maven Project. При выборе архетипа, нажмите more. Введите Gatling, после чего должен появиться архетип Gatling. Дальше смотрите видео ниже:



Сохраните проект в подходящем месте на вашем компьютере. Затем откройте проект как обычно в VS Code. Возможно, на этом этапе вам придется импортировать сборку. Для этого перейдите на вкладку Metals в VS Code и нажмите Import Build:



Это заставит Maven собрать ваш проект.


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


package computerdatabaseimport io.gatling.core.Predef._import io.gatling.http.Predef._import scala.concurrent.duration._class BasicSimulation extends Simulation {  val httpProtocol = http    .baseUrl("http://computer-database.gatling.io") // Здесь находится корень для всех относительных URL    .acceptHeader(      "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"// Вот общие заголовки    .acceptEncodingHeader("gzip, deflate")    .acceptLanguageHeader("en-US,en;q=0.5")    .userAgentHeader(      "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0"    )  val scn =    scenario("Scenario Name") // A scenario is a chain of requests and pauses      .exec(        http("request_1")          .get("/")      )      .pause(7) // Note that Gatling has recorder real time pauses  setUp(scn.inject(atOnceUsers(1)).protocols(httpProtocol))}

Чтобы запустить скрипт, откройте терминал в VS Code, и введите mvn gatling:test. Если вы хотите запустить определенный тестовый сценарий, вы можете вместо этого выполнить


mvn gatling:test -Dgatling.simulationClass=computerdatabase.BasicSimulation

Советую вам узнать больше о плагине Gatling Maven.


Gatling VScode с SBT


Если вы предпочитаете запускать и создавать свои Gatling проекты с помощью Scala Build Tool (SBT), я считаю, что проще всего сначала клонировать проект Gatling SBT Plugin Demo.


Как только вы клонировали проект, откройте его как обычно в VS Code. Перейдите на вкладку Metals в VS Code и нажмите Import Build:



VS Code теперь должен собрать ваш проект Gatling с помощью SBT.


Чтобы запустить все тесты в вашем проекте, откройте терминал и введите sbt gatling:test. Или же чтобы запустить конкретный тестовый скрипт, вы можете выполнить команду sbt gatling:testOnly computerdatabase.BasicSimulation.


Вы можете узнать больше о плагине Gatling SBT в его документации.


Резюме


В этой статье мы узнали, как использовать Visual Studio Code для создания наших Gatling скриптов. Мы рассмотрели, как создать и запустить Gatling проект с инструментами сборки Maven и SBT.


Несмотря на то, что IntelliJ IDEA остается моей предпочтительной средой разработки для разработки кода Scala и Gatling, здорово иметь возможность использовать и более популярный VS Code!




Узнать подробнее о курсе Нагрузочное тестирование



Подробнее..

Программист 1С. Где взять ПО для обучения?

29.06.2020 18:10:05 | Автор: admin
Всем привет. В июле OTUS запускает курс Программист 1С, в рамках которого можно будет прокачаться до уровня ведущего 1С-программиста, а также подготовиться к сертификации 1С: специалист. Специально к началу занятий преподаватель курса Дмитрий Котлов подготовил полезную заметку о том, где взять ПО для обучения.





Введение


Коллеги, в этой статье я расскажу какой комплекс программных продуктов нужен для изучения программирования в среде разработке 1С: Предприятие, а также администрирования баз данных в том числе на базе MS SQL и изучения наиболее популярных конфигурации, таких как УТ, БП и ЗУП. Какие есть варианты чтобы сэкономить деньги на его приобретении и использовании.

Рассмотрим этот вопрос подробнее.

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


Платформа: Клиентская платформа 1С предприятие, мобильная платформа 1С предприятие, серверная версия платформы 1С предприятие.

Конфигурации: УТ (Управление торговлей), ЗУП (Зарплата и управление персоналом), БП (бухгалтерия предприятия).

Другое ПО: MS SQL, Android Studio(для разработки мобильных приложений), Apache для Windows(для разработки мобильных приложений)

Где можно взять ПО.


ПО для обучения можно:

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


Рассмотрим вышеописанные варианты подробнее

Где и какое ПО можно скачать бесплатно:


  • Клиентская платформа 1С Предприятие: необходимо зайти по ссылке online.1c.ru/catalog/free/18610119, у данной конфигурации есть ряд ограничений, они подробно описаны по ссылке. Среди интересующих нас: в комплект поставки входит только УНФ и БП, нет ЗУП и УТ(их придётся приобретать), не поддерживается работа в варианте клиент-сервер.
  • Мобильная платформа 1С Предприятие: online.1c.ru/catalog/programs/program/18610155
  • Серверная версия платформы 1С предприятие нет возможности скачать бесплатно
  • Конфигурация БП есть в бесплатной поставке: online.1c.ru/catalog/free/18610119
  • MS SQL: www.microsoft.com/ru-ru/sql-server/sql-server-downloads тут можете выбрать вариант Developer.
  • Android Studio: developer.android.com/studio
  • Apache для Windows: httpd.apache.org/download.cgi тут можно найти различные необходимые версии



Приобретение ПО:


Бесплатно нельзяприобрести:

  1. Версию платформы 1С предприятия поддерживающую вариант работы клиент-сервер
  2. Серверная версия платформы 1С
  3. Конфигурации: УТ (управление торговлей) и ЗУП (Зарплата и управление персоналом)


Приобрести данные продукты вы можете у компании партнёров 1С, на сайте 1С есть прайс: 1c.ru/rus/partners/pricelst.jsp, та цена по которой партнёры продают ПО находится в графе Рекомендованная цена.

1. Версия платформы 1С предприятия поддерживающую вариант работы клиент-сервер


Для изучение клиент-серверного режима работы, включая администрирование таких баз потребуется версия платформы без ограничения на клиент-серверный режим, например, подойдёт:

1С: Предприятие 8. Комплект разработчика. Электронная поставка. На момент написания данной статьи стоимость такого комплекта всего 630 руб. и в него входит конфигурация УТ (управление торговлей)

2. Серверная версия платформы 1С


Версия платформы 1С поддерживающая клиент-сервер (ключ для сервера):

1С: Предприятие 8. Сервер МИНИ на 5 подключений. Антикризисная электронная поставка для разработчиков это наиболее оптимальный вариант по стоимости.

3. Конфигурации


Если вы скачали бесплатную версию 1С и приобрели комплект для разработчика, то остаётся только приобрести ЗУП (1С: Зарплата и Управление Персоналом 8) версий для обучения по данному продукту нет и его стоимость на момент составления статьи составляет: 22600

Аренда ПО:


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

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

  1. Scloud (тариф оптимальный) scloud.ru/tariffs_arenda_1c
  2. Лайв.Cloud bit-live.ru/arenda-1c
  3. Рарус (аренда 1С тариф стандрат) rarus.ru/arenda-1c-oblako/prices




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

Подробнее..

Категории

Последние комментарии

© 2006-2020, personeltest.ru