Гру 252011
 

Предопределенные, или «волшебные» константы

PHP предусматривает полезные «волшебные» константы для выборки текущего номера строки (__LINE__), пути файла (__FILE__), пути каталога (__DIR__), имени функции (__FUNCTION__), имени класса (__CLASS__), имени метода (__METHOD__) и пространства имен (__NAMESPACE__).

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

Когда в дело включаются другие скрипты, хорошая идея – использование константы __FILE__ (или __DIR__ в версии PHP 5.3):

1.// этот код зависит от пути загруженного скрипт
2.// и может вызвать проблемы при использовании из других каталогов
3.require_once('config/database.php');
4.
5.// а этот код всегда относителен к пути текущего файла
6.// в независимости откуда он был включен
7.require_once(dirname(__FILE__) . '/config/database.php');

Использование __LINE__ облегчает отладку программы. Можно отследить номера строк:

01.// some code
02.// ...
03.my_debug("some debug message"__LINE__);
04./* prints
05.Line 4: some debug message
06.*/
07.
08.// some more code
09.// ...
10.my_debug("another debug message"__LINE__);
11./* prints
12.Line 11: another debug message
13.*/
14.
15.function my_debug($msg$line) {
16.echo "Line $line: $msg\n";
17.}
Гру 252011
 

Сведения об использовании CPU

Для этого мы будем пользоваться функцией getrusage(). Помните о том, что она недоступна на платформе Windows.

01.print_r(getrusage());
02./* prints
03.Array
04.(
05.[ru_oublock] => 0
06.[ru_inblock] => 0
07.[ru_msgsnd] => 2
08.[ru_msgrcv] => 3
09.[ru_maxrss] => 12692
10.[ru_ixrss] => 764
11.[ru_idrss] => 3864
12.[ru_minflt] => 94
13.[ru_majflt] => 0
14.[ru_nsignals] => 1
15.[ru_nvcsw] => 67
16.[ru_nivcsw] => 4
17.[ru_nswap] => 0
18.[ru_utime.tv_usec] => 0
19.[ru_utime.tv_sec] => 0
20.[ru_stime.tv_usec] => 6269
21.[ru_stime.tv_sec] => 0
22.)
23.
24.*/

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

ru_oublock: количество операций блочной записи

ru_inblock: количество операций блочного чтения

ru_msgsnd: количество отправленных сообщений

ru_msgrcv: количество принятых сообщений

ru_maxrss: максимальный размер невыгружаемого набора

ru_ixrss: общий объем разделяемой памяти

ru_idrss: общий объем неразделяемых данных

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

ru_majflt: количество ошибок отсутствия страниц

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

ru_nvcsw: количество переключений контекста процессом

ru_nivcsw: количество принудительных переключений контекста

ru_nswap: количество обращений к диску при подкачке страниц

ru_utime.tv_usec: время работы в пользовательском режиме (микросекунды)

ru_utime.tv_sec: время работы в пользовательском режиме (секунды)

ru_stime.tv_usec: время работы в привилегированном режиме (микросекунды)

ru_stime.tv_sec: время работы в привилегированном режиме (секунды)

Чтобы узнать, какие ресурсы CPU потребляет скрипт, нам нужно посмотреть на значения ‘user time’ (время работы в пользовательском режиме) и ‘system time’ (время работы в привилегированном режиме). По умолчанию величины секунд и миллисекунд представляются раздельно. Таким образом, вы можете разделить значение микросекунд на 1 миллион и добавить к значению секунд, чтобы вычислить общее количество секунд как десятичное число.

Рассмотрим пример:

01.// sleep for 3 seconds (non-busy)
02.sleep(3);
03.
04.$data getrusage();
05.echo "User time: ".
06.($data['ru_utime.tv_sec'] +
07.$data['ru_utime.tv_usec'] / 1000000);
08.echo "System time: ".
09.($data['ru_stime.tv_sec'] +
10.$data['ru_stime.tv_usec'] / 1000000);
11.
12./* prints
13.User time: 0.011552
14.System time: 0
15.*/

Хотя выполнение скрипта заняло примерно 3 секунды, использование CPU было очень-очень низким. Это происходит потому, что во время ожидания (sleep) скрипт фактически не потребляет ресурсов CPU. Существует множество других задач, которые могут занять реальное время, но при этом не использовать время CPU, например ожидание дисковой операции. Так что, как вы видите, использование CPU и действительная длительность времени исполнения – не всегда одно и то же.

Вот другой пример:

01.// loop 10 million times (busy)
02.for($i=0;$i<10000000;$i++) {
03.
04.}
05.
06.$data getrusage();
07.echo "User time: ".
08.($data['ru_utime.tv_sec'] +
09.$data['ru_utime.tv_usec'] / 1000000);
10.echo "System time: ".
11.($data['ru_stime.tv_sec'] +
12.$data['ru_stime.tv_usec'] / 1000000);
13.
14./* prints
15.User time: 1.424592
16.System time: 0.004204
17.*/

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

Время работы в привилегированном режиме (System Time) – это количество времени, которое CPU тратит на выполнение системных запросов к ядру от имени программы. Вот пример этого:

01.$start = microtime(true);
02.// keep calling microtime for about 3 seconds
03.while(microtime(true) - $start < 3) {
04.
05.}
06.
07.$data getrusage();
08.echo "User time: ".
09.($data['ru_utime.tv_sec'] +
10.$data['ru_utime.tv_usec'] / 1000000);
11.echo "System time: ".
12.($data['ru_stime.tv_sec'] +
13.$data['ru_stime.tv_usec'] / 1000000);
14.
15./* prints
16.User time: 1.088171
17.System time: 1.675315
18.*/

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

Еще вы можете заметить, что цифры соответствуют 3 секундам неточно. Это потому что на сервере также, возможно, выполнялись и другие процессы, так что скрипт не использовал 100% CPU в течение всех 3 секунд.

 Posted by at 07:12
Гру 252011
 

Сведения об использовании памяти

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

PHP есть «сборщик мусора» (программа очистки памяти) и довольно сложный диспетчер памяти. Количество памяти, используемой вашим скриптом, может увеличиваться и уменьшаться в процессе его выполнения. Получить сведения о текущем использовании памяти можно, используя функцию memory_get_usage(), а чтобы узнать о наибольшем объеме памяти в любой точке, можно воспользоваться функцией memory_get_peak_usage().

01.echo "Initial: ".memory_get_usage()." bytes \n";
02./* prints
03.Initial: 361400 bytes
04.*/
05.
06.// let's use up some memory
07.for ($i = 0; $i < 100000; $i++) {
08.$array []= md5($i);
09.}
10.
11.// let's remove half of the array
12.for ($i = 0; $i < 100000; $i++) {
13.unset($array[$i]);
14.}
15.
16.echo "Final: ".memory_get_usage()." bytes \n";
17./* prints
18.Final: 885912 bytes
19.*/
20.
21.echo "Peak: ".memory_get_peak_usage()." bytes \n";
22./* prints
23.Peak: 13687072 bytes
24.*/
 Posted by at 07:07  Tagged with:
Гру 232011
 

Двоичные данные (Boolean)

Это простейший тип. Он выражает истинность значения – это может быть либо TRUE, либо FALSE. Булев тип был введен в PHP4.

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

<?php
$x = True; // присвоить $x значение TRUE
?>

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

<?php
// == это оператор, который проверяет
// эквивалентность и возвращает булево значение
if ($action == "показать_версию") {
echo "Версия 1.23";
}

// это не обязательно…
if ($show_separators == TRUE) {
echo “<hr>\n”;
}

// …потому что вы можете просто написать
if ($show_separators) {
echo “<hr>\n”;
}
?>

Преобразование в тип Boolean

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

При преобразовании в логический тип, следующие значения рассматриваются как FALSE:

Все остальные значения рассматриваются как TRUE (включая любой ресурс).

Внимание! -1 считается TRUE, как и любое ненулевое (отрицательное или положительное) число!

<?php
var_dump((bool) "");        // bool(false)
var_dump((bool) 1);         // bool(true)
var_dump((bool) -2);        // bool(true)
var_dump((bool) "foo");     // bool(true)
var_dump((bool) 2.3e5);     // bool(true)
var_dump((bool) array(12)); // bool(true)
var_dump((bool) array());   // bool(false)
var_dump((bool) "false");   // bool(true)
?>

Работа с бинарными данными (тип boolean)

Cтроки могут содержать любые, в том числе и бинарные данные. Для работы с такими строками иногда
удобно использовать функции pack() и unpack().

pack(string $format [,mixed $args, …])

Функция pack() упаковывает заданные аргументы в бинарную строку, которая затем и возвращается. Формат параметров, а также их количество, задается при помощи строки $format, которая представляет собой набор однобуквенных спецификаторов форматирования — наподобие тех, которые указываются в sprintf(), но только без знака %. После каждого спецификатора может стоять число, которое отмечает, сколько информации будет обработано данным спецификатором. А именно, для форматов a, A, h и H число задает, какое количество символов будет помещено в бинарную строку из тех, что находятся в очередном параметре-строке при вызове функции (то есть, определяется размер поля для вывода строки). В случае @ оно определяет абсолютную позицию, в которую будут помещены следующие данные. Для всех остальных спецификаторов следующие за ними числа задают количество аргументов, на которые распространяется действие данного формата. Вместо числа можно указать *, в этом случае подразумевается, что спецификатор действует на все оставшиеся данные. Вот полный список спецификаторов формата:

a — строка, свободные места в поле заполняются символом с кодом 0;
A — строка, свободные места заполняются пробелами;
h — шестнадцатеричная строка, младшие разряды в начале;
H — шестнадцатеричная строка, старшие разряды в начале;
c — знаковый байт (символ);
C — беззнаковый байт;
s — знаковое короткое целое (16 битов, порядок байтов определяется архитекту-
рой процессора);
S — беззнаковое короткое целое;
n — беззнаковое целое (16 битов, старшие разряды в конце);
v — беззнаковое целое (16 битов, младшие разряды в конце);
i — знаковое целое (размер и порядок байтов определяется архитектурой);
I— беззнаковое целое;
l — знаковое длинное целое (32 бита, порядок байтов определяется архитекту-
рой);
L — беззнаковое длинное целое;
N — беззнаковое длинное целое (32 бита, старшие разряды в конце);
V — беззнаковое целое (32 бита, младшие разряды в конце);
— число с плавающей точкой (зависит от архитектуры);
d — число с плавающей точкой двойной точности (зависит от архитектуры);
x — символ с нулевым кодом;
X — возврат назад на 1 байт;
@ — заполнение нулевым кодом до заданной абсолютной позиции.

Немало, не правда ли? Вот пример использования этой функции:

// Целое, целое, все остальное — символы
$bindata = pack("nvc*", 0x1234, 0x5678, 65, 66);

После выполнения приведенного кода в строке $bindata будет содержаться 6 байтов в такой последовательности: 0x12, 0x34, 0x78, 0x56, 0x41, 0x42 (в шестнадцатеричной системе счисления).

unpack(string $format, string $data)

Функция unpack() выполняет действия, обратные pack() — распаковывает строку $data, пользуясь информацией о формате $format. Возвращает она ассоциативный массив, содержащий элементы распакованных данных. Строка$format задается немного в другом формате, чем в функции pack(), а именно, после каждого спецификатора (или после завершающего его числа) должно “впритык” следовать имя ключа в ассоциативном массиве. Разделяются параметры при помощи символа /. Пример:

$array=unpack("c2chars/nint", $bindata);

В результирующий массив будут записаны элементы с ключами: chars1chars2 и int. Как видим, если после спецификатора задано число, то к имени ключа будут добавлены номера 1, 2 и т. д., т. е. в массиве появятся несколько ключей, отличающихся суффиксами.
Когда бывают полезны функции pack() и unpack()? Например, вы считали участок GIF-файла, содержащий его размер в пикселах, и хотите преобразовать бинарную 32-битную ячейку памяти в формат, понятный PHP. Или, наоборот, стремитесь работать с файлами с фиксированным размером записи. В этом случае вам и пригодятся рассматриваемые функции. Вообще говоря, функции pack() и unpack() применяются сравнительно редко. Это связано с тем, что в PHP практически все действия, которые могут потребовать работы с бинарными данными (например, анализ файла с рисунком с целью определения его размера), уже реализованы в виде встроенных функций, например, с GIF-картинкой это GetImageSize().

Гру 232011
 

Типы данных языка PHP

Скалярные типы данных:
» Двоичные данные (boolean)
» Целые числа (Integer)
» Числа с плавающей точкой (Float)
» Строки (String)

Смешанные типы данных:
» Массивы (Array)
» Объекты (Object)

Специальные типы данных:
» Ресурсы (Resource)
» Пустой тип (NULL)

Псевдотипы данных:
» Смешанный (Mixed)
» Числа (Number)
» Обратного вызова (Callback)

Дополнительно:
» Манипуляции с типами данных

 Posted by at 18:39  Tagged with: