Elite mercenary
С нами с 26.04.09
Сообщения: 10376
Рейтинг: 1650
|
Добавлено: 31/08/10 в 22:01 |
Доброго времени суток.
Братцы, подскажите, мож стыкался кто - ни с того, ни с сего, с неизвестного перепугу начали ОЧЕНЬ сильно тупить ссылки прописанные через mod_rewrite. Открываются секунд по 30-40 %)
У меня на сайте картинки выдаются кодом:
Код: [развернуть] | header("Content-type: image/jpg");
$done = file_get_contents($image['targetImagePath']);
echo $done; |
Так сама страничка ещё загрузиться через 30-40 секунд, а эта конструкция совсем работать перестала.
Я утром на счётчик поглядел - обомлел, теряю посетителей только так
И ведь не происходило ничего такого, что могло бы повлиять, разве что всплеск активности был очень заметный за последние дни, но это я над траффиком поработал.
|
|
|
|
С нами с 31.05.10
Сообщения: 1991
Рейтинг: 487
|
Добавлено: 31/08/10 в 22:20 |
отдавать таким образом картинки это какбе нехорошо и чревато при большом трафе загрузкой проца, сжиранием памяти -> тормозами. похоже что у тебя как раз такой случай. посмотри загрузку процессора, памяти.
и скорее всего стоят голые апач+пхп. а твоя фраза "разве что всплеск активности был очень заметный за последние дни" подтверждает догадку
выход - отдавать графику все-таки нормально, без пхп. если без этого скрипта нельзя, то нужно смотреть в сторону nginx
|
|
|
|
Чингачгук, вождь красноглазых
С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824
|
Добавлено: 31/08/10 в 22:26 |
Ты бы вывод top привел, что ли. free/vmstat как бонус
Вообще жестоко ты так - вывод статики через PHP. Сейчас окажется, что там в своп головой сервер бьется и за все оставшиеся ресурсы бьются несколько копий какой-то задачи из crontab
LeadFarmer писал: | если без этого скрипта нельзя, то нужно смотреть в сторону nginx |
ну да, всем же известно, что с nginx PHP приобретает магические свойства и память перестает жрать
|
|
|
|
Elite mercenary
С нами с 26.04.09
Сообщения: 10376
Рейтинг: 1650
|
Добавлено: 31/08/10 в 22:45 |
>что там в своп головой сервер бьется
да нет там нихрена такого, я то первым делом проверил
Вот щас всё что можно стопнул, рестартанул весь сервак для гарантии, ничего не поменялось.
Показатели из вебмина:
Real memory 1011.48 MB total, 159.59 MB used
Virtual memory 3.81 GB total, 0 bytes used
vmstat до кучи:
Код: [развернуть] | > vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 0 168140 83668 592912 0 0 82 34 145 213 2 0 97 1 |
всё на всех сайтах грузится нормально, но как только кликаешь на ссылке прописанной через mod_rewrite - провисание секунд на 40, потом страничка таки загрузится,подтянутся фиды, а вот картинка выдаваемая чере вышеприведённую конструкцию так и не загружается.
>Вообще жестоко ты так - вывод статики через PHP
за то никакого хотлинка.
>и скорее всего стоят голые апач+пхп. а твоя фраза "разве что всплеск активности был очень заметный за последние дни" подтверждает догадку
на данный момент никакого всплеска уже нет, траффик упал если не до плинтуса, то ниже пояса точно.
так что дело не в перезагрузке сервака, тут что то другое, только вот ума не приложу что
|
|
|
|
Чингачгук, вождь красноглазых
С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824
|
Добавлено: 31/08/10 в 22:58 |
cyberdream3 писал: |
>Вообще жестоко ты так - вывод статики через PHP
за то никакого хотлинка.
|
Ты сам себе не хуже иного хотлинка сделал - у тебя всегда имидж выдается в броузер, который даже кэшем пользоваться не может, поскольку у него нету информации о modified (ты ж ее в хедер не выдаешь), да и фичи HTTP 1.1, которые трафик и ресурсы экономят, тоже работать не будут. И, исходя из картины болезни, я бы не был так уверен, что хотлинка "никакого".
Тут уже трудно говорить теоретически - выкладывай тогда рулезы rewrite, код выше этих строк, и т.п.
|
|
|
|
www.phpdevs.com
С нами с 24.10.02
Сообщения: 16633
Рейтинг: 16105
|
Добавлено: 31/08/10 в 23:01 |
ну mod_rewrite ты так и не показал, может там у тебя циклы. А потом попробуй вместо
Код: [развернуть] |
$done = file_get_contents($image['targetImagePath']);
echo $done;
|
использовать Код: [развернуть] | readfile($image['targetImagePath']); |
|
|
Пишу на php/mysql/django за вменяемые деньги.
Обращаться в личку.
|
3
|
|
|
Elite mercenary
С нами с 26.04.09
Сообщения: 10376
Рейтинг: 1650
|
Добавлено: 01/09/10 в 01:39 |
Пилять мороженная, это nameserver слёг
Прописал в /etc/resolv.conf гугловский nameserver 8.8.8.8 - всё поднялось
Всё равно всем спасибо за попытки помочь, держите рейт.
|
|
|
|
С нами с 01.03.07
Сообщения: 304
Рейтинг: 223
|
Добавлено: 01/09/10 в 10:48 |
ты бы все равно картинки лучше бы через Nginx выдавал. При большом трафике это помогает
|
|
|
|
Чингачгук, вождь красноглазых
С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824
|
Добавлено: 01/09/10 в 14:59 |
leroy_17 прав, ну или хотя бы так делай: я как-то выдавал пикчи прямо из базы (надо было) и, чтобы снизить нагрузку, внутри php сделал полное соответствие http 1.1
Вот так проверяется, что тебе вообще надо что-то выдавать
Код: [развернуть] |
$ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
if ($ifModifiedSince && strtotime($ifModifiedSince) >= $timestamp ) {
header('HTTP/1.0 304 Not Modified');
return;
}
|
$timestamp - время модификации, откуда его брать, сам разберешься.
А вот это надо вписать в выдачу имиджа самого.
Код: [развернуть] |
if (is_numeric($timestamp)) {
header('Last-Modified: '.gmdate('D, d M Y H:i:s',$timestamp) . ' GMT');
}
header('Content-Type: image/jpeg');
|
Все это очень хорошо тебе расход трафика снизит, поскольку броузеры этими фичами пользуются, и часто.
|
|
|
|
С нами с 11.06.03
Сообщения: 1266
Рейтинг: 950
|
Добавлено: 02/09/10 в 01:07 |
Умник на умнике. Всё правильно ТС делал.
Нагрузку на проц file_get_contents практически не создаёт. Если PHP работает как модуль внутри апача, то вообще мизер. Даже при большом трафике.
И счётчики стартера тому подтверждение.
вот если бы стартер пикчи GD формировал на лету другое дело.
|
|
|
|
Чингачгук, вождь красноглазых
С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824
|
Добавлено: 02/09/10 в 01:28 |
А потом компании меня зовут разгребать код за такими вот "писателями" - "это мизер", "копейки", "железо ныне дешевое", написали как курица лапой, и глядишь - и ломается все под нагрузкой.
Чего, как ты думаешь, у него bind упал? Наверное, не от переизбытка памяти в дни высокой нагрузки. Каковую память ты как-то забыл включить в свои рассуждения, и в которую загоняется результат file_get_contents.
|
|
|
|
С нами с 11.06.03
Сообщения: 1266
Рейтинг: 950
|
Добавлено: 02/09/10 в 19:48 |
Цитата: | file_get_contents() is the preferred way to read the contents of a file into a string. It will use memory mapping techniques if supported by your OS to enhance performance.
|
Все уважающие себя системы поддерживают мемори-маппинг. А это значит что оперативная память будет выделяться только по фолтам, когда процесс будет обращаться к соответвующему смещению переменной (файла).
Стартер видимо дёргает картинки с других хостов. Вы ему предложите для экономии памяти курл использовать так, чтобы выдирать кусок картинки, отдавать клиенту, потому ещё кусок, и т.д. если сервер с которого он дергает докачку поддерживает.
|
|
|
|
Чингачгук, вождь красноглазых
С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824
|
Добавлено: 02/09/10 в 20:35 |
Sha писал: | Все уважающие себя системы поддерживают мемори-маппинг. А это значит что оперативная память будет выделяться только по фолтам, когда процесс будет обращаться к соответвующему смещению переменной (файла). |
Ты просто под strace как-нибудь запусти простой скрипт и посмотри, что php вызывает и как - все файловые функции, seek, read и т.д. На file_get_contents(). Хорошо, что на мануал хватило, но то, что он где-то mmap() _использует_, не значит, что он память не жрет вообще. Смысл mmap в том, что он избавляет от копирования лишнего. А так эта строка точно так же в RAM находится после того, как ты ее получил и выдал клиенту в броузер. Или ты думаешь, если ты потом на нее preg_* напустишь - она снова с диска будет читаться?
Ну и как я сказал - bind просто так не падает.
Цитата: | Стартер видимо дёргает картинки с других хостов. Вы ему предложите для экономии памяти курл использовать так, чтобы выдирать кусок картинки, отдавать клиенту, потому ещё кусок, и т.д. если сервер с которого он дергает докачку поддерживает. |
Вот взял бы и сам посоветовал, если надо, к людям-то чего приставать?
|
|
|
|
Elite mercenary
С нами с 26.04.09
Сообщения: 10376
Рейтинг: 1650
|
Добавлено: 03/09/10 в 10:40 |
Братцы, я вижу вы уже свой холивар завели, без меня
Я встревать не буду, но определённую ясность внесу - nameserver юзался предоставленный хостером, и издох явно не от моей нагрузки.
Может щас его уже и подняли, незнаю, я гугловский оставил, работает норм.
На серваке никогда небыло проблем с нехваткой ресурсов из за использования конструкции file_get_contents.
Ось стоит - Debian Linux 5.0, Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny3 with Suhosin-Patch Server
Даже при всплесках актиности и заметном росте траффика я лично не заметил чтоб проц стал пц напрягаться, или сильно возросло потребление памяти.
Возможно, при более большом траффике что то и проявиться, но на данном этапе и проц, и память - полёт нормальный, траффик растёт, но я не вижу особого пожирания ресурсов проца или памяти.
Говорю то, что вижу, и из этого делаю выводы.
Ещё раз всем спасибо за обсуждение, и за предоставленные конструкции кода, сохраню на всякий пожарный, может нужно будет. Но покамест на полочку, ибо нету на серваке перенапрягов.
|
|
|
|
С нами с 11.06.03
Сообщения: 1266
Рейтинг: 950
|
Добавлено: 03/09/10 в 11:28 |
Dr.Syshalt писал: | Смысл mmap в том, что он избавляет от копирования лишнего. А так эта строка точно так же в RAM находится после того, как ты ее получил и выдал клиенту в броузер. Или ты думаешь, если ты потом на нее preg_* напустишь - она снова с диска будет читаться?
|
http://en.wikipedia.org/wiki/Mmap
http://en.wikipedia.org/wiki/Memory-mapped_file
Так вот отдача файла методом стартера через file_get_contents вообще не приведёт к выделению памяти в областях задачи. Из файлового буфера будет отдаваться сразу в буфер сокета.
Так же из этих статей можно понять где и когда строка находится если на неё напустить preg_*.
Цитата: |
Ну и как я сказал - bind просто так не падает.
|
Все уже согласились что Бинд сложно упал. Только не во всём что упало виноват file_get_contents.
|
|
|
|
Чингачгук, вождь красноглазых
С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824
|
Добавлено: 03/09/10 в 17:26 |
В википедию он меня тыкает по таким вопросам... Еще школьный учебник по информатике проверь
Ты сделай file_get_contents на большой файл, а потом проверь, что тебе покажет memory_get_usage.
Еще смешнее будет, когда тебе file_get_contents свалится по php-шному ограничению памяти на аллокацию.
Юморист. Из какого, блин, буфера?
Цитата: | Так же из этих статей можно понять где и когда строка находится если на неё напустить preg_*. |
Ты не статьи читай, а с кодом повозись. Жетательно таки с сишным, чтобы понять, как OS память выделяет. Файловый буфер.. курам на смех. А он где размещается - такой, чтобы строковая функция могла всю строку обработать? В параллельной вселенной?
Сервера нормальные, когда хотят из файла прямо в сокет выдать, пользуются sendfile(). Все - и апач, и nginx, и proftpd - используют этот кернельный вызов для статики, он может и просто по DMA передать данные от дискового контроллера в сокет. А вовсе не mmap, который, один хуй, все в результате в RAM загрузит. Все очень просто - если ты делаешь mmap(), пробегаешься по всему файлу пойнтером - он у тебя весь сидит в памяти. Все. И смысл этого в сравнении с pread() был только тот, что ты промежуточного буфера не использовал. И можешь после этого хоть обтыкаться ссылками куда то, в чем ты ничего не понял.
Цитата: | It naturally implements demand paging, because initially file contents are not entirely read from disk and do not use physical RAM at all. The actual reads from disk are performed in "lazy" manner, after a specific location is accessed. |
Вот и все. И никаких паралелльных вселенных под файловые буферы, все просто.
|
|
|
|
С нами с 11.06.03
Сообщения: 1266
Рейтинг: 950
|
Добавлено: 03/09/10 в 21:35 |
Цитата: |
А он где размещается - такой, чтобы строковая функция могла всю строку обработать? В параллельной вселенной?
|
Это, батенька, не из параллельной вселенной, а из средневековья. Ещё скажите, что вся переменная целиком должна находиться в RAM, а подкачка - фантастика. ММАП - та же подкачка, только RAM - в файловый кэш, но в своп как другие страницы юзерспейса откачиваются только при определённых обстоятельствах, которые к случаю стартера отношения не имеют. В файловый же кеш они попадают по мере востребованности, а не как вы думаете (сначало всё в кеш, а потом качать-не-перекачать). Даже если вы сканируете переменную, то чтение файла проводится по мере необходимости и одни страницы файлового кэша вытесняются другими. Но эти страницы - ядерные и RAM больше чем них отведено вы никак не съедите.
Цитата: |
in most operating systems the memory region mapped actually is the kernel's page cache (file cache), meaning that no copies need to be created in user space.
...
Memory-mapping may not only bypass the page file completely, but the system only needs to load the smaller page-sized sections as data is being edited, similarly to demand paging scheme used for programs.
|
Не уж то врут?
Что же касается "file_get_contents свалится по php-шному ограничению памяти на аллокацию". Я НЕ утверждал, что mmap НЕ мапирует файл на вирт пространство. Конечно может быть получен отказ на расширение вирт. пространства. Но до использования RAM не дойдёт. Здесь проверяются счётчики используемого вирт.пространства. Одна переменная.
И эта проверка проводится ещё до каких-либо отображений (фактических аллокаций), а не посередине.
|
|
|
|
Чингачгук, вождь красноглазых
С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824
|
Добавлено: 04/09/10 в 20:27 |
Sha писал: | В файловый же кеш они попадают по мере востребованности, а не как вы думаете (сначало всё в кеш, а потом качать-не-перекачать). Даже если вы сканируете переменную, то чтение файла проводится по мере необходимости и одни страницы файлового кэша вытесняются другими. |
То есть мы проходим пойтнером N сегментов, которые размещают в себе строку размером 10MB: один, второй, третий раз... и каждый раз OS выбирает эти 10MB с диска в мааааленький какой-то буфер - только нужный на данную секунду сегмент? А остальные релизит тут же - чтобы, если мы двинем пойнтер в сегмент N-1, снова его подкачать с диска? Каждый раз диск дергает типа.
А ГОЛОВУ ВКЛЮЧИТЬ?
OS, представь себе, будет держать в памяти всю строку, пока у нее есть такая возможность - точно так же, как в случае любого другого использования виртуальной памяти. mmap() ничем таким не уникален и не волшебная функция, которая позволяет "не использовать RAM", как ты, почему-то, решил.
Цитата: | Здесь проверяются счётчики используемого вирт.пространства. Одна переменная.
И эта проверка проводится ещё до каких-либо отображений (фактических аллокаций), а не посередине. |
Блин, просто глянь сорсы get_file_contents(), вместо того, чтобы теоретизировать тут и ссылки на вики давать. Как оно читает там. Тупо в память читает, и все. strace подтверждает поведение (в курсе такой штуки-то?).
1.php:
Код: | <?php
$cont = file_get_contents("apache_error.old");
?>
|
$ strace php 1.php (фрагмент - где оно как раз file_get_contents выполняет)
Код: [развернуть] | lstat("/home", {st_mode=S_IFDIR|0755, st_size=29, ...}) = 0
lstat("/home/oleg", {st_mode=S_IFDIR|0755, st_size=8192, ...}) = 0
lstat("/home/oleg/apache_error.old", {st_mode=S_IFREG|0644, st_size=14769208, ...}) = 0
open("/home/oleg/apache_error.old", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=14769208, ...}) = 0
lseek(3, 0, SEEK_CUR) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=14769208, ...}) = 0
mmap(NULL, 14946304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f07aeaab000
read(3, "[Mon Oct 19 04:15:36 2009] [warn"..., 8192) = 8192
read(3, "g.com/content/html/favicon.ico\n["..., 8192) = 8192
read(3, "[Mon Oct 19 04:19:05 2009] [warn"..., 8192) = 8192
read(3, "otice: Undefined variable: html"..., 8192) = 8192
read(3, "g.com/content/html/ads/mature/sh"..., 8192) = 8192
read(3, "html/ads/mature/show.php on line"..., 8192) = 8192
read(3, "t not found or unable to stat: /"..., 8192) = 8192
read(3, " stderr: PHP Notice: Undefined "..., 8192) = 8192
read(3, "ntent/html/ads/mature/show.php o"..., 8192) = 8192
|
О чем тут вообще говорить?
Достало уже с высосанными из пальца теориями спорить там, где все просто и понятно.
|
|
|
|
С нами с 05.02.08
Сообщения: 5
|
Добавлено: 04/09/10 в 20:45 |
ТС, тебя спасет джедайская связка:
nginx (для раздачи статики) + php скрипт который будет проверять кому отдавать картинки, а кому нет + X-Accel-Redirect.
как-то примерно так,
да пробудет с вами Сила!
|
|
|
|
Elite mercenary
С нами с 26.04.09
Сообщения: 10376
Рейтинг: 1650
|
Добавлено: 04/09/10 в 22:37 |
2HulioCarlos
Я, наверное, в прошлом сообщении как то то ли невнятно выразился, то ли мелковатым шрифтом написал
тогда повторюсь уже выделенным:
Возможно, при более большом траффике что то и проявиться, но на данном этапе и проц, и память - полёт нормальный, траффик растёт, но я не вижу особого пожирания ресурсов проца или памяти. Предоставленные в данном топике конструкции кода, сохраню на всякий пожарный, может нужно будет, НО ПОКА НИЧЕГО МЕНЯТЬ НЕ БУДУ, ибо всё работает нормально.
X-Accel-Redirect мне советует уже где то 5й человек, но я пока не вижу в нём надобности.
2all
Я в холиваре не участвую, тем более доводы уже перешли в область, которая выше моих познаний, но хочу уточнить:
Тут постоянно пугают друг друга громадными файлами которые доведут таки сервак до ручки. Но в моём случае ничего громадного не обрабатывается, с помощью file_get_contents дёргаются картинки, а это максимум 3 мегабата (установлено ограничение), а основном картинки 60-200кб.
|
|
|
|
С нами с 11.06.03
Сообщения: 1266
Рейтинг: 950
|
Добавлено: 05/09/10 в 14:02 |
Dr.Syshalt писал: |
mmap(NULL, 14946304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f07aeaab000 |
Ошибочка, брат. У тя версия ПХП багнутая.
Вот мой код
Код: [развернуть] |
<?php
$b = file_get_contents('mbox');
echo $b;
?>
|
И в терминах сисколов
Код: [развернуть] |
--- file_get_contents
lstat("/root",0xbfbfc7c0) = 0 (0x0)
lstat("/root/mbox",0xbfbfc7c0) = 0 (0x0)
open("/root/mbox",0x0,0666) = 4 (0x4)
fstat(4,0xbfbfd060) = 0 (0x0)
lseek(4,0x0,SEEK_CUR) = 0 (0x0)
lseek(4,0x0,SEEK_SET) = 0 (0x0)
fstat(4,0xbfbfd100) = 0 (0x0)
mmap(0x0,275883,(0x1)PROT_READ,(0x1)MAP_SHARED,4,0x0) = 677089280 (0x285b9000)
break(0x829b000) = 0 (0x0)
munmap(0x285b9000,0x435ab) = 0 (0x0)
close(4) = 0 (0x0)
fstat(1,0xbfbfcfd0) = 0 (0x0)
ioctl(1,TIOCGETA,0xbfbfd010) = 0 (0x0)
------ echo
write(1,0x8248000,56) = 56 (0x38)
write(1,0x8248000,41) = 41 (0x29)
|
ЗЫ хотя наверное соглашусь, что в пространство задачи копирование происходит всё-таки. Ибо слишком рано анмап вызывается.
Dr.Syshalt писал: | А ГОЛОВУ ВКЛЮЧИТЬ?
OS, представь себе, будет держать в памяти всю строку, пока у нее есть такая возможность - точно так же, как в случае любого другого использования виртуальной памяти. mmap() ничем таким не уникален и не волшебная функция, которая позволяет "не использовать RAM", как ты, почему-то, решил.
|
Вот тут, Вы, батенька в корне неправы. Про строку я таки согласен. И я не утверждал, что рам не используется.
Но не путайте реализацию функции ммап и использование этой функции в ПХП.
Копирование в юзерспейс происходит не потому, что ммап такой "неуникальный" и жить без юзерспейса не может (иначе в нём вообще смысла нет), а потому что в программе на ПХП используется оператор присваивания, а память для переменной $a выделена (или будет выделена) только в юзерспейсе. Протрассируйте readfile (только на нормальном PHP) и будет видно наверное.
Последний раз редактировалось: Sha (05/09/10 в 15:36), всего редактировалось 4 раз(а)
|
|
|
|
С нами с 11.06.03
Сообщения: 1266
Рейтинг: 950
|
Добавлено: 05/09/10 в 14:48 |
Стартер используй в своём случае @readfile. В этом случае в пространстве задачи большая область не выделяется. И всё работает как я писал.
|
|
|
|
Чингачгук, вождь красноглазых
С нами с 14.05.04
Сообщения: 4744
Рейтинг: 1824
|
Добавлено: 05/09/10 в 18:41 |
Sha писал: | Ошибочка, брат. У тя версия ПХП багнутая. |
Скорее, дело в том, что у меня 5.2 - ты наверняка на 5.3 экспериментируешь. Но не суть, в принципе, смысл там все равно остается.
Цитата: |
ЗЫ хотя наверное соглашусь, что в пространство задачи копирование происходит всё-таки. Ибо слишком рано анмап вызывается.
|
Зачем гадать? Даже в 5.3 file_get_contents() вызывает функцию с красноречивым именем _php_stream_copy_to_mem()
Мог бы просто проверить доступные исходники, а не ссылки на вики кидать - как я тебе 3 дня назад уже говорил.
Цитата: | Копирование в юзерспейс происходит не потому, что ммап такой "неуникальный" и жить без юзерспейса не может (иначе в нём вообще смысла нет) |
У тебя точно какие-то странные представления о работе mmap(). В нем смысл тот, что в работе с MMF как раз не используется никаких буферов - ты напрямую получаешь ссылки на страницы от менеджера виртуальной памяти. *read же сначала читает содежимое в тот самый буфер, который ты пытаешься mmap() приписать - а вот потом уже копирует его содержимое в буфер, адрес которого ты ему передаешь. То есть получаем лишнее копирование. Именно поэтому mmap() так быстро читает целиком небольшие файлы. И именно поэтому он используется в file_get_contents() - потому что там и надо читать как правило небольшие файлы, и сразу. Ну и много где он еще полезен - в случае, когда у тебя много потоков или даже процессов к одним участкам файла имеют доступ на R/O, например. А вот когда тебе надо кусок вычитать из большого - там все уже совсем не так однозначно ;) Порой mmap куда медленнее, чем традиционный POSIX I/O. Это так, к сведению. Память mmap прекрасно использует - просто если ты отмапишь файл в N гигов, то по мере нехватки памяти OS будет релизить страницы отмапленного файла - если ты, не дай бог, его не менял. А то ж еще и на диск скидывать начнет, а там запись вообще дорогая получится.
Вот тебе, кстати, чтение для досуга.
Если ты хочешь быстро, не расходуя памяти, послать файл в сокет - еще раз, mmap не вариант. Для этого во всех современных OS есть асинхронный I/O. Тот же кернельный вызов sendfile. Вот именно благодаря ему nginx и умудряется слать статику сотням одновременных соединений, при этом расходуя несколько мегабайт RAM на все. А если ты берешь php, да еще и, как говорил, в виде модуля (то есть используешь префоркнутый апач) - то там попадалово на память будет по несколько MB на одно соединение. Ну и чисто вопрос количества соединений - когда эта посудина начнет черпать воду бортом )
Насчет readfile - вижу проблему уже в том, что он вызывает _php_stream_passthru(), который читает файл по кускам в буфер размером 8192 байт и выкидывает его клиенту через PHPWRITE() в цикле - можешь уверять меня сколько угодно в волшебный свойствах readfile после этого, но ему все равно до нормального сервера статики как до луны пешком. Это в 5.3, кстати, так.
Резюмирую: все эти "трюки" с php хороши до тех пор, пока у тебя клиентов как кот наплакал. Ну несколько десятков одновременно. Когда у тебя сотни соединений - то вся эта конструкция начнет разваливаться на куски - там, где по-нормальному сделанное (то есть вообще без вывода статики через php) оно еще долго бы жило счастливой жизнью.
|
|
|
|
С нами с 01.03.07
Сообщения: 304
Рейтинг: 223
|
Добавлено: 05/09/10 в 18:46 |
Короче заканчивайте флудить , для тех кто не верит что file_get_contents может убить сервак могут эксперементировать дальше. Для тех кто это уже понял будет больше работы ;)
|
|
|
|
С нами с 11.06.03
Сообщения: 1266
Рейтинг: 950
|
Добавлено: 06/09/10 в 13:16 |
С file_get_contents разобрались уже. Его прожорливость следствие того что возвращается не ссылка, а значение.
Dr.Syshalt писал: |
У тебя точно какие-то странные представления о работе mmap().
В нем смысл тот, что в работе с MMF как раз не используется никаких буферов - ты напрямую получаешь ссылки на страницы от менеджера виртуальной памяти....
|
Ссылки на какие страницы? Правильно, на страницы которые будут располагаться в буфере ввода-вывода ядра который в простонародии называется файловый кэш. Ядро обменивается с блочными устройствами ввода-вывода через буфера.
Но фактический ввод-вывод будет производиться не во время вызова ммап, а по мере обращения к адресам врирт. памяти из программы.
Цитата: | *read же сначала читает содежимое в тот самый буфер, который ты пытаешься mmap() приписать - а вот потом уже копирует его содержимое в буфер, адрес которого ты ему передаешь.
|
read использует ядерные буфера для чтения расположенные в том же пуле что и страницы на которые отображаются вирт.адреса посредством ммап.
Цитата: |
То есть получаем лишнее копирование. Именно поэтому mmap() так быстро читает целиком небольшие файлы.
|
Копирование в юзерспейс и есть суть вызова read. Было бы странно если бы он это лишнее копирование не делал бы.
ммап не читае быстрее. ммап вообще ничего не читает. Производится только ассоциация области юзерспейса на отрезок файла. Чтение отложено до момента фактического обращения к адресам этой области.
И в момент необходимости происходит та же самая передача из файла (если ещё не в кеше) что и при вызове read. Далее вместо опирования на эти страницы буфера создаётся ссылка из юзерспейса.
Если же Вы думаете что система всё это проворачивает во время вызова ммап, то ошибаетесь.
Цитата: | И именно поэтому он используется в file_get_contents() - потому что там и надо читать как правило небольшие файлы, и сразу. Ну и много где он еще полезен - в случае, когда у тебя много потоков или даже процессов к одним участкам файла имеют доступ на R/O, например. А вот когда тебе надо кусок вычитать из большого - там все уже совсем не так однозначно ;) Порой mmap куда медленнее, чем традиционный POSIX I/O. Это так, к сведению. Память mmap прекрасно использует - просто если ты отмапишь файл в N гигов, то по мере нехватки памяти OS будет релизить страницы отмапленного файла - если ты, не дай бог, его не менял. А то ж еще и на диск скидывать начнет, а там запись вообще дорогая получится.
|
Эта запись ничуть не дороже той которая будет при вытеснении страниц юзерспейса в свoп. Если есть пример когда обращение к странице отображённой ммап медленнее посикс-чтения, велкам.
Цитата: |
Вот тебе, кстати, чтение для досуга.
Если ты хочешь быстро, не расходуя памяти, послать файл в сокет - еще раз, mmap не вариант.
Для этого во всех современных OS есть асинхронный I/O.
|
Какая связь асинхронности со скоростью передачи данных? Диски быстрее крутятся или сетевые адаптеры несущую частоту повышают?
А буферы ядром используются те же самые. Асинхронность может помочь в многопотоковости и многозадачности. Но никак не осуществить этот ввод-вывод.
Цитата: |
Тот же кернельный вызов sendfile. Вот именно благодаря ему nginx и умудряется слать статику сотням одновременных соединений, при этом расходуя несколько мегабайт RAM на все. А если ты берешь php, да еще и, как говорил, в виде модуля (то есть используешь префоркнутый апач) - то там попадалово на память будет по несколько MB на одно соединение. Ну и чисто вопрос количества соединений - когда эта посудина начнет черпать воду бортом )
|
Если сравнивать сендфайл и связку ммап + send то производительность конечно немного увеличится благодаря экономии системных вызово и благодаря чуть большей синхронизации чтения из файла и записи в сокет.
Экономии памяти вообще не будет если в сенд отдавать в качестве указателя на буфер передачи адрес из региона отражённого ммап.
В этом случае система будет так же всё делать сама. Читать из файла (если страница неактуальна) и (кстати сразу) отсылать в сокет. От ядерного sendfile отличается только тем что иногда будет вызвращать результат отличный от заданной длины апередачи. И программе придётся перезапускать send.
Цитата: |
Насчет readfile - вижу проблему уже в том, что он вызывает _php_stream_passthru(), который читает файл по кускам в буфер размером 8192 байт и выкидывает его клиенту через PHPWRITE() в цикле - можешь уверять меня сколько угодно в волшебный свойствах readfile после этого, но ему все равно до нормального сервера статики как до луны пешком. Это в 5.3, кстати, так.
Резюмирую: все эти "трюки" с php хороши до тех пор, пока у тебя клиентов как кот наплакал. Ну несколько десятков одновременно. Когда у тебя сотни соединений - то вся эта конструкция начнет разваливаться на куски - там, где по-нормальному сделанное (то есть вообще без вывода статики через php) оно еще долго бы жило счастливой жизнью.
|
Я делал трассировку ПХП-шного readfile. Так вот используется ммап. И анмап не производится до последнего write. Ниодного вызова read естественно нет.
Файл читается по мере обращения к сответствующим смещениям.
Чтение с диска производится, естественно, ибо никто не может отдать содержимое файла не прочитав его?
Единственная существенная разница между ядерным sendfile и mmap+send в том, что вообще не используется вирт.пространство задачи. Т.е. по идее sendfile просто не может превысить лимиты процесса.
|
|
|
|
Текстовая реклама в форме ответа Заголовок и до четырех строчек текста Длина текста до 350 символов Купить рекламу в этом месте! |
|
Спонсор раздела
|