Просмотр больших логов на сервере

head filename.log - просмотр начала файла (10 строк по умолчанию).

tail -15 filename.log - просмотр конца файла, 15 строк.

tail -f filename.log - просмотр 10 строк с конца файла + отслеживать добавление новых строк.

Как браузер рисует страницу

  1. Загружает HTML и строит DOM.
  2. Загружает CSS и строит CSS Object Model (CSSOM).
  3. На основе DOM и CSSOM строит дерево рендеринга. Дерево похоже на DOM но там нет невидимых элементов (<head>, display:none), это дерево описывает визуальное представление DOM.
  4. Для каждого элемента дерева расчитывается его положение на странице(flow), layouting.
  5. Происходит отрисовка всего этого в браузере.

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

Repaint

В случае изменения стилей элемента не влияющих на его размеры и положение (border-color, background-color) - браузер повторяет реднеринг элемента с новыми стилями.

Reflow

Если изменения затрагивают структуру документа происходит пересчет положения элементов (reflow/relayout).
Изменения которые могут привести к reflow:

  • манипуляция с DOM деревом
  • изменение содержимого, в т.ч. в полях форм
  • расчет/изменение свойств CSS
  • добавление/удаление таблиц стилей
  • изменение размеров окна браузера/прокрутка

Какие свойства CSS заставляет браузер выполнять перекомпозицию (outline box model)

Свойства: display, position, margin, padding, z-index, left/right/top/bottom, [min-/max-]height/width

Подробнее

Doctrine lazy, extra_lazy, eager

При загрузке сущности, если у нее есть связанная сущность/сущности то при:
fetch="eager" - связанная сущность/сущности тоже будет загружена из БД.
fetch="lazy" - будет создан прокси-объект, данные будут загружены только после обращения.
fetch="extra_lazy" - усиление ленивой загрузки. C этим режимом загрузки будут доступы методы count, contains, get, slice

Подробнее

Deep copy / Shallow copy

Shallow copy - копирует самый возможный минимум.
Если поле - примитив, будет скопировано значение, если поле адрес - будет скопирован адрес. Это дешевле и быстрее, но при редактировании значения по адресу в копии - значение будет изменено и у оригинального объекта:

$arr = array(1,2);
$arr1 = &$arr;
$arr1[0]++
echo $arr[0]; // 2
echo $arr1[0]; // 2

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

$arr = array(1,2);
$arr1 = $arr;
$arr1[0]++
echo $arr[0]; // 1
echo $arr1[0]; // 2

Стандарты написания PHP кода

PHP Standards Recommendations (PSR)

1 - базовый стандарт оформления
3 - интерфейс протоколирования (Logger Interface)
4 - стандарт автозагрузки
6 - интерфейс кэширования

и их много

Типизация в PHP

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

Статическая типизация - когда тип переменной точно известен во время компиляции.
Например, в Clang int a = 1; и при выполнении тип переменной a может быть только int.
С динамической типизацией попроще - тип переменной определяется во время выполнения.
Например, в PHP $a = 1; и при выполнении переменная $a может быть числом 1 или даже строкой(если туда записать строку).

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

Типизация, в свою очередь, делится на сильную (strong) и слабую (weak).
Когда мы выполняем какую-либо операцию при сильной типизации, то два операнда должны иметь один и тот же тип.
Например, в Python 1 + 'string' (пример слабый конечно, ведь умножение строки на число в питоне допустимо) вызовет ошибку, потому что 1 - число, а «string» - строка.
А вот в языках со слабой типизацией ошибки не будет.
Например, в PHP 1 + "string" вернёт цифру 1.
И причиной всему является приведение типов.

serialize и unserialize в PHP

Функция serialize генерирует пригодное для хранение представление переменной. Используется для передачи значений между скриптами без потери структуры и типов данных. На выходе возвращает строчку.
При сериализации объектов php пытается вызывать магические методы __serialize и __sleep перед сериализацией, чтобы позволить объекту произвести очистку некоторых ресурсов перед тем как выполнять сериализацию.

Функция unserialize выполняет обратную операцию и декодирует строку в объекты, так же проверяя и вызывая магические методы __unserialize и __wakeup, чтобы объект мог настроить необходимые для работы ресурсы, например соединение с БД.

Потоки в JS в браузере

В каждом окне выполняется только один главный поток, который занимается выполнением JavaScript, отрисовкой и работой с DOM.
Он выполняет команды последовательно, может делать только одно дело одновременно и блокируется при выводе модальных окон, таких как alert.
Есть и другие, служебные потоки, например, для сетевых коммуникаций.

Существует спецификация Web Workers, которая позволяет запускать дополнительные JavaScript-процессы(workers).
Они могут обмениваться сообщениями с главным процессом, но у них свои переменные, и работают они также сами по себе.
Такие дополнительные процессы не имеют доступа к DOM, поэтому они полезны, преимущественно, при вычислениях, чтобы загрузить несколько ядер/процессоров одновременно.

Event loop

Параллелизм/Многопоточность в JavaScript работает за счёт цикла событий (event loop), который отвечает за выполнение кода, сбора и обработки событий и выполнения под-задач из очереди (queued sub-tasks).
Вызов любой функции создает контекст выполнения (Execution Context). При вызове вложенной функции создается новый контекст, а старый сохраняется в специальной структуре данных - стеке вызовов (Call Stack).
Объекты размещаются в куче. Куча - это просто имя для обозначения большой неструктурированной области памяти.
Среда выполнения JavaScript содержит очередь задач. Эта очередь - список задач, подлежащих обработке. Каждая задача ассоциируется с некоторой функцией, которая будет вызвана, чтобы обработать эту задачу.
Когда стек полностью освобождается, самая первая задача извлекается из очереди и обрабатывается. Обработка задачи состоит в вызове связанной с ней функции с параметрами. Вызов функции создаёт новый контекст выполнения и заносится в стек вызовов.
Обработка задачи заканчивается, когда стек снова становится пустым. Следующая задача извлекается из очереди и начинается её обработка.
Каждая задача выполняется полностью, прежде чем начнет обрабатываться следующая. Благодаря этому мы точно знаем: когда выполняется текущая функция - она не может быть приостановлена и будет целиком завершена до начала выполнения другого кода (который может изменить данные, с которыми работает текущая функция).

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

Особенностью цикла событий в JavaScript является то, что поток выполнения никогда не блокируется. Обработка I/O обычно осуществляется с помощью событий и функций обратного вызова, поэтому даже когда приложение ожидает запрос от IndexedDB или ответ от XHR, оно может обрабатывать другие процессы, например пользовательский ввод.

Однобайтовые и Многобайтовые кодировки

Прародителем всех современных кодировок можно считать ASCII (American Standard Code for Information Interchange /американская стандартная кодировочная таблица для печатных символов и некоторых специальных кодов).
Это однобайтовая кодировка, в которую изначально заложено всего 128 символов.
Позже она была расширена до 256 символов, чтобы использовать в кодировании байт целиком.
Это позволило добавлять символы национальных языков, помимо существующей латиницы(например KOI8-R/Windows-1251).

В 1991 году Консорциум Юникода предложил UTF-32 - многобайтовую кодировку, в которой каждый символ кодировался 32 битами(4 байта).
Проблема кодировки в том, что для кодирования того же количества информации стало требоваться в 4 раза больше памяти!
На смену ей пришла UTF-16 (16 бит / 2 байта). Символов меньше, но все еще в 2 раза больше памяти, в сравнении с однобайтовыми кодировками.

Подумали и придумали UTF-8 - многобайтовая кодировка с переменной длиной символа. Из названия можно подумать, что тут используется 8 бит для кодирования.
Нет.
Все латинские символы кодируются 1 байтом, иначе говоря базовая часть ASCII перешла в UTF-8. А все остальные символы кодируются двумя байтами. Таким образом для хранения файлов, которым было достаточно ASCII, не требуется больше памяти, и при этом мы можем использовать расширенный набор символов.

Работа с UTF-8 в PHP

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

echo substr("hi mémé", 0, 5); // will print hi m�
echo mb_substr("hi mémé", 0, 5); // will print hi mé

До PHP7.2 можно было использовать механизм перегрузки функций - задать настройке mbstring.func_overload в php.ini положительное значение, которое представляет собой комбинацию битовых масок, определяющих категории функций, которые нужно перегружать.
Значения:
1 для перегрузки функции mail()
2 для строковых функций
4 для функций регулярных выражений
7 для всего что выше вместе

Отличие POST от GET

GET/POST/PUT/DELETE - HTTP методы которые представляют операцию которую необходимо провести с ресурсом.

В GET данные формы передаются как часть URL, в POST в теле запроса.
Общепринято использовать POST для создания ресурсов, GET для получения, PUT/PATCH - для обновления, DELETE - для удаления.
Но никто не запрещает делать все GET или DELETE запросами.