Основан 26 Июля 2013 года
freehacks.ru fhacks.me fhacks.pw fhacksnplmzxaaoo.onion
HashFlare

Страница 1 из 2 12 ПоследняяПоследняя
Показано с 1 по 10 из 11
  1. #1
    TopicStarter
    Аватар для pilot114

    Статус
    Offline
    Регистрация
    11.10.2013
    Сообщений
    19
    Репутация
    15 + / -
    Script Kiddie

    работа с памятью в php

    Вопрос знатокам - как посмотреть, что происходит с памятью во время работы php-скрипта?

    Например этот пример дает результат '192':

    [PHP]$a = memory_get_usage();
    $b = 'HelloWorld';
    echo memory_get_usage() - $a;[/PHP]

    С какого хрена 10 символов занимают 192 байта? Я конечно понимаю, там типа обертки какие-то (zval), но ведь и строки в php
    не многобайтные, т.е. тотже 'HelloWorld' сам по себе всего 10 байт занимает.

  2. Пользователь сказал cпасибо:
    admin
  3. #2
    Аватар для Mints97

    Статус
    Offline
    Регистрация
    31.12.2013
    Сообщений
    19
    Репутация
    7 + / -
    Другое
    Чувак, memory_get_usage() вроде же возвращает память, аллоцированную под весь пых, не только под твой скрипт. Так что этот метод может тебе дать только очень приближенное значение используемой памяти, ведь в пыхе еще и на фоне идет работа с памятью. Более точного способа узнать зажранную переменной память в пыхе вроде нет.

  4. #3
    Аватар для Mints97

    Статус
    Offline
    Регистрация
    31.12.2013
    Сообщений
    19
    Репутация
    7 + / -
    Другое
    Да и еще, кстати, пых и под сами переменные память зажирает. В общем, так ты ничего не добъешься. А зачем тебе вообще это понадобилось?

  5. #4
    Trust
    Аватар для ul1k317

    Статус
    Offline
    Регистрация
    26.08.2013
    Сообщений
    823
    Репутация
    395 + / -
    Web-программист
    А что мануал отменили? [Только зарегистрированные могут видеть это. ] читать внимательно, конспектировать, на следующем уроке проверю.
    php, mysql, mssql, js, html, css, ajax, administrating, it consulting, etc.

  6. #5
    TopicStarter
    Аватар для pilot114

    Статус
    Offline
    Регистрация
    11.10.2013
    Сообщений
    19
    Репутация
    15 + / -
    Script Kiddie
    А что мануал отменили? [Только зарегистрированные могут видеть это. ] читать внимательно, конспектировать, на следующем уроке проверю.
    Документация там ниочем (конкретно по этой функции). Лол, а что, был какой-то урок? =)
    Чувак, memory_get_usage() вроде же возвращает память, аллоцированную под весь пых, не только под твой скрипт. Так что этот метод может тебе дать только очень приближенное значение используемой памяти, ведь в пыхе еще и на фоне идет работа с памятью. Более точного способа узнать зажранную переменной память в пыхе вроде нет.
    Чувак ты прав. Частично. Да, php использует дофига памяти под каждую переменную, но ничего фоново он в память не сует, аллокация напрямую зависит от того, как написан скрипт, сколько в нём переменных и какие они (короч оверхед пропорционален реальным данным). В исходном примере мой косяк, разумеется, и под саму $a память выделялась.

    Провозился целый день, но вродь разобрался. Могу накатать статейку, если интересно.

  7. #6
    Trust
    Аватар для ul1k317

    Статус
    Offline
    Регистрация
    26.08.2013
    Сообщений
    823
    Репутация
    395 + / -
    Web-программист
    Ты правда считаешь что памяти пых должен жрать столько сколько ты написал?
    Серьезно?
    Давай я начну нашу интересную игру, где мы будем перечислять то, на что пых берет память:
    - предопределенные переменные

    ...продолжай
    php, mysql, mssql, js, html, css, ajax, administrating, it consulting, etc.

  8. #7
    Trust
    Аватар для ul1k317

    Статус
    Offline
    Регистрация
    26.08.2013
    Сообщений
    823
    Репутация
    395 + / -
    Web-программист
    Да и кстати наверное это будет исчерпывающим ответом на твой вопрос [Только зарегистрированные могут видеть это. ]
    php, mysql, mssql, js, html, css, ajax, administrating, it consulting, etc.

  9. #8
    Аватар для Mints97

    Статус
    Offline
    Регистрация
    31.12.2013
    Сообщений
    19
    Репутация
    7 + / -
    Другое
    Давай я начну нашу интересную игру, где мы будем перечислять то, на что пых берет память:
    - предопределенные переменные

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

    И да, кстати, ответь-ка мне, я тебе кинул ЛС =)

  10. #9
    Trust
    Аватар для ul1k317

    Статус
    Offline
    Регистрация
    26.08.2013
    Сообщений
    823
    Репутация
    395 + / -
    Web-программист
    Цитата Сообщение от Mints97 Посмотреть сообщение
    Это и в жисть не перечислишь. переменные (названия, значения), константы (названия, значения), массивы (названия, ключи, значения) операторы, функции... плюс к этому предопределенные константы, предопределенные, как ты, дсда, сказал, переменные, предопределенные массивы, предопределенные функции...

    И да, кстати, ответь-ка мне, я тебе кинул ЛС =)
    Ответил давно.
    php, mysql, mssql, js, html, css, ajax, administrating, it consulting, etc.

  11. #10
    TopicStarter
    Аватар для pilot114

    Статус
    Offline
    Регистрация
    11.10.2013
    Сообщений
    19
    Репутация
    15 + / -
    Script Kiddie
    Если кратко - чтобы точно посчитать аллокацию нужно копаться в исходниках php =(

    Итак, есть функции:

    memory_get_peak_usage();
    memory_get_usage();

    Первая показывает пик памяти, занимаемый в течении работы, вторая текущее использование.
    Также им пожно передавать TRUE в качестве параметра, тогда будут выводить реальное значение.
    Реальное - не значит то, что реально что-то содержит, а то что php "застолбил" под свои нужды.
    Застолбляет он динамически, кусками по 256 Кб. Для конкретных цифр нам потребуется именно memory_get_usage(),
    которая правда работает не совсем очевидно, нужно мерить по-хитрому.
    1) Память выделяемая ДО замеров (под упомянутые выше предопределенные переменные, функции и пр. и пр.)
    учитывается в обоих вызовах memory_get_usage() поэтому её просто не учитываем.
    2) В разных версиях php возможно разное потребление. Но принцип расчета должен быть общим.
    Я тестил на Винде, x64, php 5.4.13
    3) помним про то, что все переменные храняться в контейнерах, что обуславливает некий оверхед (про них дальше)
    и память под сами имена переменных также выделяется.

    Для начала тесты:
    [PHP]
    // ТЕСТ#1# Результат: 80 байт. имя + контейнер под цифру = 80 байт.
    $a = memory_get_usage();
    echo memory_get_usage() - $a;

    // ТЕСТ#2# Результат: 0 байт
    // Цифра перезаписала цифру, новой памяти не потребовалось.
    // с NULL, boolean и любыми другими цифрами включая float поведение такое же,
    // значит контейнеры для них такие же.
    $a = 1234;
    $a = memory_get_usage();
    echo memory_get_usage() - $a;

    // ТЕСТ#3# Результат: 80 байт. Однако результат обманчив, см. след.тест
    $b = [1,2,3,4];
    $a = memory_get_usage();
    echo memory_get_usage() - $a;

    // ТЕСТ#4# Результат: 88 байт. Лишние 8 байт появляются для тех же NULL, int, float
    // предположительно, виноват встроенный механизм управления памятью (ZMM, Zend Memory Manger)
    // если скажем, наинициализировать в начале несколько переменных, опять будет 80.
    $b = 1234;
    $a = memory_get_usage();
    echo memory_get_usage() - $a;[/PHP]

    Теперь делаем финт ушами:

    [PHP]// ТЕСТ#5# Результат: -16 байт. Значит, контейнер строки на 16 байт больше, чем контейнер цифры.
    // Для пустого массива отклонение будет 48, для экземпляра class example {} всего 24.
    $a = '';
    $a = memory_get_usage();
    echo memory_get_usage() - $a;[/PHP]

    Также нагенерил тесты для проверки влияния длины строки на контейнер. (вплоть до строк длиной 8000 символов.)
    Результат - каждые 8 символов стабильно дают прирост на 16 байт.

    Отдельно написал тест генерации множества строк (с разными именами, но одинаков. значениями - слово 'test').
    Тут меня ждало разочарование - по непонятным причинам память под строки
    выделяется вразнобой: получились числа, кратные 8, почти все распределенные в диапозоне от 72 до 144. (пик - 96 байт).
    Проанализировав их, я пришел к выводу что ZMM как-то хитро объединяет
    несколько подряд объявленных строк, прежде чем сохранить.

    Ещё серия тестов была проведена для длины имени переменной.
    $x = 666; // занимает 80 байт
    $xx = 666; // внезапно 0
    $xxx = 666; // внезапно 0
    Далее длина 4-11 => 8 байт, 12-19 => 16, 20-27 => 24 и т.д.


    Предварительные выводы (в основном, по тесту #5#) таковы:
    Пустая или до 8 символов строка: 96 байт.
    Цифра, NULL: 80 байт.
    Пустой массив: 128 байт.
    Пустой объект: 104 байта.
    Во всех случаях память под имя входит в это число.

    Исходники.

    Качаем [Только зарегистрированные могут видеть это. ], распаковываем, находим /Zend/zend.h
    Тут есть описание структуры для хранения переменных:

    Код:
    typedef union _zvalue_value {
        long lval;                    /* long value */
        double dval;                /* double value */
        struct {
            char *val;
            int len;
        } str;
        HashTable *ht;                /* hash table value */
        zend_object_value obj;
    } zvalue_value;
    
    struct _zval_struct {
        /* Variable information */
        zvalue_value value;        /* value */
        zend_uint refcount__gc;
        zend_uchar type;    /* active type */
        zend_uchar is_ref__gc;
    };
    В Сях я не очень, но очевидно что _zval_struct - это и есть искомый контейнер.

    refcount__gc (4 байта) - количество ссылок на переменную.
    type (1 байт) - это тип данных. Просто цифра.
    is_ref__gc (1 байт) - это флаг ссылки. Если = 1, переменная является ссылкой.
    value - это значение, которое является объединением zvalue_value, где:

    lval используется, если переменная is NULL, integer, resource или boolean.(4 байта)
    dval для float-ов (8 байт)
    str - строка, сотоит из указателя (4 байта?) и длины (4 байта)
    HashTable - особая стрктура для всех php массивов
    obj - видимо, для объектов.

    Таким образом, я подошел к вопросу с самого верха и с самого низа. Что происходит между ними
    и как те гигантские значения сверху соотносятся с вышеозначенными сишными структурами, я не понял, так как уже лень.
    Конечно, вполне можно эту тему развить дальше, только смысла в этом мало. Если кто таки разберёт код memory manager'a,
    а ещё лучше -найдет мануал по Zend, можно разобраться гораздо серьёзнее. Также любопытно было бы посмотреть, как отличаются результаты на разных машинах, поэтому на всякий случай приложу тесты.
    [Только зарегистрированные могут видеть это. ]
    Последний раз редактировалось admin; 05.02.2014 в 10:24.

Страница 1 из 2 12 ПоследняяПоследняя

Метки этой темы

Ваши права

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