За последние 24 часа нас посетили 21885 программистов и 1007 роботов. Сейчас ищут 640 программистов ...

Оптимизация substring

Тема в разделе "PHP для новичков", создана пользователем Ippolit2000, 8 дек 2016.

Метки:
  1. Ippolit2000

    Ippolit2000 Новичок

    С нами с:
    8 дек 2016
    Сообщения:
    1
    Симпатии:
    0
    Здравствуйте!
    Входные данные: $str - строка средней длины (не поток, не файл). Все символы однобайтовые.
    Выходные данные: обрезанная строка после N символов.
    Пример: return substr($str, 10000);

    Функция substr в момент выполнения будет "съедать" память пропорционально размеру обрезаемой части строки. Так при отрезания второй половины от строки размером 500KB пиковое потребление памяти будет равно 750KB.

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

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    Нет
    --- Добавлено ---
    Хотите экономить байты - пишите на Си.
     
    denis01 нравится это.
  3. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    Тут важно понять логику:
    1) Отдаем строку, N памяти занято.
    2) Отрезаем половину, создаем новую переменную, старая никуда не делась, N/2 памяти занято.
    3) Это не может произойти ДО того, как будет очищена память из пункта 1. По этому в пике получаем 1.5N памяти.

    Понимаете? Исходная переменная никуда не делась. Плюс создалась вторая, размером с половину первой. Ваше $str ведь как было, так и осталось вне функции. Даже если вы в нее же переприсваиваете новое значение, все равно, на момент исполнения, она существует в скоупе strpos. Можете попробовать передачу по ссылке, но не факт, что поможет.

    Боюсь, что бесполезно, ведь strpos уже написан на Си... И, вероятно, оптимизирован настолько, насколько можно. PHP 7+ не двояко намекает, что не дураками это все делается. PHP - это ж, исторически, скриптовый текстовый редактор. Все, что связано с обработкой текста, тут работает на отлично. Лучшей поддержки работы с текстом, пожалуй, я не видел нигде.
     
  4. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    Я только не понял при чем здесь strpos :)
    Пхп весь на Си написан. Это к теме не имеет отношения.
    Память под новую строку выделяется, поэтому "пиковый расход памяти" такой. На сях он бы просто символ \0 загнал в нужную позицию и считал бы строку обрезанной.
    --- Добавлено ---
    Разница между высокоуровневыми и низкоуровневыми языками в том, что в высокоуровневых вы не паритесь за потраченные байты и потерянные указатели. За удобство приходится платить эффективностью. В большинстве реальных задач это оправдано. Поэтому в телефонах джава и в вебе пхп.
     
  5. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.155
    Симпатии:
    1.769
    Адрес:
    :сердА
    тьфуты...substr, еств. Но ты понял, в общем:)

    Не, так не пойдет. У него в итоге расход памяти не изменится. Автор хотел бы 500 до 250 обрезать. А так, у него 500 обрежется визуально, а по факту не изменится.

    На Си нет строк, автор. Есть char. И есть массивы. Массив char это строка. Память аллоцируется строго статически. То есть. Для строки в 10 символов мы:
    1) Выделяем память.
    2) Опционально чистим ее от мусора.
    3) Заполняем данными.

    Независимо от того, забили мы или нет данными наш массив, размер его будет тот, который мы определили в пункте 1, сказав ОСи, что нам нужно массив под 10 char-ов запилить.

    После этого массив неизменен и статичен. Ты можешь читать из него, можешь писать в него. Можешь его дропнуть. Хочешь получить подстроку? Окей:
    1) Вычисляешь расстояние между началом и концом подстроки.
    2) Аллоцируешь новый фрагмент памяти под пачку char-ов, длиной из пункта 1.
    3) Пишешь туда посимвольно данные из исходного массива.
    4) Дропаешь исходный, если надо.

    Итого, между пунктами 3 и 4 у тебя в пике расход памяти достигнет суммарного значения размеров старого и нового массивов.

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

    А как же работают динамические охрененные супер-массивы в PHP, Сурикат? А точно так же, только от вас это скрыто на низком уровне. Когда ты объявляешь массив хотя бы с 1 элементов, PHP отгрызает оперативки на 2 элемента. С запасом. Когда ты дошел до 2 элементов, PHP создает новую структуру данных, на сей раз на 4 элемента, копирует в нее предыдущие данные, после чего дропает их. Дошел до 4 элементов? PHP создаст структуру на 8. И так далее, постоянно удваивая. Под капотом старая добрая статика. И это не проблема PHP, просто иначе никак.

    Да, автор, PHP-массив размером в 129 элементов будет весить в два раза больше, чем массив в 128 элементов.

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