Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функция между file() и fgets() 
:(
    Опции темы
TSVET
Дата 24.5.2008, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 6.9.2007

Репутация: нет
Всего: нет



Читал книгу "PHP 5 в подлиннике", там о функции file() говорится что не следует загружать ей файлы большого объёма. О функции fgets() говорится что она медлительна с большим объёмом данных. Поэтому я ради интереса решил изобрести велосипед,- написать свою функцию которая будет грузить не весь файл и не по одной строчке, а строк сразу по ~200 приблизительно, обрабатывать эти строки, затем опять грузить ~200 строк, и так пока данные в файле не закончатся. Я выбрал объём загружаемых данных равный одному мегабайту, но думаю, этот объём можно увеличить. 

Взят простейший пример: в файле например 30мегабайт текста, каждая строка это веб-страница. В среднем строка имеет объём 10килобайт. За один запрос к скрипту нам надо выдавать одну страницу, а значит, за один запрос нам нужна всего одна строчка.
Код

<?php
if($_REQUEST['numpg']) {$numpage=$_REQUEST['numpg'];}
else {$numpage=1;}


$f = fopen('myfile.txt','r');
$strcounter=0;
$stop=false;
while (!feof($f)) {
    $st = fread($f,'1024000').str_replace("\n",'',fgets($f));
    // Читаем кусок 1 мегабайт
    // Если последняя строка в куске прочитана не полностью, то дочитываем её
    // Заодно удаляем последний символ конца строки, так как из-за него образуется пустая ячейка в массиве

    $strarr = explode("\n",$st); // Разбиваем полученный кусок на строки

    foreach ($strarr as $str) {
        $strcounter++;
        if($numpage==$strcounter) {$page=$str; $stop=true; break;}
        // нам из файла требуется всего 1 строка, когда строка получена, полностью останавливаем циклы
    }
    if($stop==true) break;
}
if(!$page) $page='<h1>404 not found</h1>';
echo $page; // Браво! Строка получена, выводим её.
?>
</body>
</html>


Вот сам текст, который мы обрабатываем:
Код

<h1>Страница 1</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 2</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 3</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 4</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 5</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 6</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 7</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 8</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 9</h1> текст страницы текст страницы текст страницы текст страницы текст страницы
<h1>Страница 10</h1> текст страницы текст страницы текст страницы текст страницы текст страницы

Но как говорилось выше, он имеет не 10 строк, а несколько десятков мегабайт. 

Как видно, если структура проста, и к файлу нет множества обращений на чтение\запись, то можно обойтись и без MySQL 
Чтоб убедиться, что этот код работает я ставил в циклы счётчик, убирал BREAK из циклов, менял метод убирал fread() и fgets(), и выводил число, которое натикало на счётчике. Функция работает как задумано. Но цель функции - сохранить допустимую нагрузку на сервер, и сохранить приемлемую скорость выполнения
Я БЫ ХОТЕЛ ВАС СПРОСИТЬ: добивается ли эта функция поставленных задач? Стоит ли вобще игра свеч? 


______________________________ 
Также я когда-то пытался написать аналогичную функцию для записи, которая работает так: 
1. Читает блок из обрабатываемого файла 
2. Обрабатывает его построчно 
3. Пишет блок во временный файл(цикл повторяется пока функция не перепишет все данные во временный файл) 
4. Копирует обработанный временный файл на место старого 

Но функция не работала по неизвестной мне причине, то ли временный файл не создавался, то ли в него ничего не писалось, а может он не копировался на место старого... 
P.S.: естественно такая функция не расчитана на множество частых запросов записи, а вот там где их немного(админпанель) вполне сойдёт.
PM MAIL WWW ICQ   Вверх
Feldmarschall
Дата 24.5.2008, 13:54 (ссылка) |    (голосов:6) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок
****


Профиль
Группа: Участник
Сообщений: 2641
Регистрация: 11.12.2007

Репутация: 22
Всего: 32



Хороший пример кривизны.
Можно на наглядном примере изучать, как делать не надо.
Криво тут всё: постановка задачи, сама решаемая задача, применяемые средства.

Для чего мы городим весь этот огород? Чтобы обойтись без базы данных.
Понимаешь, какое дело... Кабы помягче сказать. Вот, допустим, приходишь ты на авто.ру, и говоришь, что придумал устройство, которое позволяет запрягать лошадь в автомобиль любой марки. И при поездках на небольшие расстояния оно вполне позволяет обойтись без бензина. Как ты думаешь, какова будет реакция?
Здесь примерно то же самое.

Дальше переходим к исходным данным.

Цитата(TSVET @  24.5.2008,  13:16 Найти цитируемый пост)
О функции fgets() говорится что она медлительна с большим объёмом данных

Изумительно.
Что такое "медлительна", что такое "большие объемы" - не знает никто. Но при этом данная информация берется за некую отправную точку в изысканиях.
И вера книжкам - просто поразительная. fgets даже не участвует в экспериментах. Медлительна - и баста!

Пример, выбранный для исследования не менее замечательный. 
Несомненно, половина вебсайтов именно так и поступают - записывают 3000 страниц в один файл. Отличная идея, очень перспективная. Несомненно, её надо решать.

Ну, и средства. Экономим производительность. Именно в этих целях мы и тягаем в память строку на два мегабайта, парсим её в массив и ходим по нему в цикле ради одной-единственной строчки. Браво. Эталон оптимальности.
PM   Вверх
TSVET
Дата 24.5.2008, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 6.9.2007

Репутация: нет
Всего: нет



Цитата

Что такое "медлительна"

Если брать эту функцию в цикле, и ходить по всему файлу, хотя в моём коде тоже аж два цикла, так что ожидать прироста производительности моего кода не приходится.

Я ведь не со зла написал этот код, я думал так будет лучше)))))

Жила-была одна ЦМС написанная на файлах без мускуля, только она грузила файлы целиком... А в каментах ведь срут, файлы раздуваются(я б никогда не стал хранить форум или каменты в файлах)
Работала причём эта цмс, но потом их закрыли за большую нагрузку на сервер, а вот еслибы они через fgets() делали, или как я то их не закрыли бы...


Цитата

Пример, выбранный для исследования не менее замечательный. 
Несомненно, половина вебсайтов именно так и поступают - записывают 3000 страниц в один файл. Отличная идея, очень перспективная. Несомненно, её надо решать.

Я не говорю, что сайты будут хранить столько страниц в одном файле, но предусмотреть это нам никто не мешает. Притом работать это будет не нагружая сервер, а то что в файле будет столько страниц то врядли...

А ведь мускуль тоже перебирает всё, только он на Си писан и там всё быстрее... и продуманно более умнО и разносторонне...

А вообще бувает, придумаешь как кажется что нибудь "гиниальное", а на деле полный бред выходит...


Меня интересует, как вы относитесь к txtSQL? Тот же мускуль, только на ПХП. Что мешает реализовать мускуль на ПХП? ПХП слабый язык? txtSQL живёт, значит что-то здравое в этом ведь есть?..
PM MAIL WWW ICQ   Вверх
Feldmarschall
Дата 24.5.2008, 21:37 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок
****


Профиль
Группа: Участник
Сообщений: 2641
Регистрация: 11.12.2007

Репутация: 22
Всего: 32



Так и я не со зла её раскритиковал.
Я рад, что ты нормально это воспринял. 
Просто на твоем примере хорошо видно, что обдумывать надо все этапы своей работы - от предпосылок до реализации.

Цитата(TSVET @  24.5.2008,  20:58 Найти цитируемый пост)
а вот еслибы они через fgets() делали, или как я то их не закрыли бы...

на самом деле, вариантов масса. сколько бы ни было каментов - их число всегда достаточно разумное(если только их защищать и чистить от спама - если не защищать, то тут любая база быстро подохнет) и работа с ними всегда будет нормальной, если грамотно структурировать. К примеру, каменты под статьёй - для каждй статьи свой файл.

Цитата(TSVET @  24.5.2008,  20:58 Найти цитируемый пост)
предусмотреть это нам никто не мешает

Нет, мешает.
Вообще, попытки что-то предусматривать без достаточного опыта, обычно приводят к обратному результату. Сколько компьютерщиков тратили бешеные бабки, покупая последнюю модель материки или видюхи, "под апгрейд". И как жестоко накалывались, когда ко времени апгрейда проц уже имел другой сокет, а видюха - стандарт. И так во всем. Брать надо на сейчас. В будущем у тебя изменятся требования, задачи, и продходы к их решению. Ты потратишь время на универсальное решение, которое тебе не понадобится.

В программировании ещё хуже. 
Сейчас ты не понимаешь разницу между решаемыми задачами. Они тебе кажутся одинаковыми. Но это не так. Для страниц умнее - держать их в отдельном файле. Для других задач - другие решения. Не надо искать универсальное. Если у тебя есть проблема - зайди на форум и задай конкретный вопрос. Тебе дадут конкретное удобное решение.

Цитата(TSVET @  24.5.2008,  20:58 Найти цитируемый пост)
А ведь мускуль тоже перебирает всё

А вот и не угадал!
Мускуль, вообще-то, тоже не что-то застывшее и однообразное. Одних движков хранилищ в нем десяток. Но если обращаться к хрестоматийной БД, то там все гораздо проще и быстрее.
Во-первых, открой для себя волшебную функцию fseek(). Которая ,при умелом использовании, ускорит твой код в разы.
Во-вторых, если выравнивать строки по длине, то поиск нужной будет занимать и вовсе ничтожное время.
В-третьих, если нам понадобится искать данные по ключевым словам, то мы сделаем индексный файл, который будет в сотни раз меньше файла с данными, который мы будем целиком читать в память, находить в нем номер строки с нужным ключевым словом и выбирать эту строку с помощью fseek, и ворочать таким образом громадными базами. Поздравляю! Ты изобрел БД! Теперь осталось её отладить и обкатать на паре стоен проектов и она готова... Вот только зачем ,если это уже сделали до тебя?

Цитата(TSVET @  24.5.2008,  20:58 Найти цитируемый пост)
txtSQL живёт, значит что-то здравое в этом ведь есть?.. 

извини, но логики в этом заявлении нет никакой. бомжи как-то живут? кому-то нравится быть бродягой - значит, что-то здравое в этом есть? Возможно. давай, подавайся в бомжи. если следовать твоей логике. 
если что-то где-то живет - это СОВСЕМ не повод напяливать это на себя. 
PM   Вверх
Kaiden
Дата 24.5.2008, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 26.11.2007

Репутация: нет
Всего: нет



Просто небольшое замечание по коду.
У команды break есть опциональный параметр, который указывает, из скольких вложенных циклов нужно выйти. Т.е. вместо некрасивого использования булевой переменной stop, можно было просто написать break 2.

Что касается самой функции... На мой взгляд, она могла бы быть полезна при решении какой-то очень узкой задачи - когда, допустим, из файла в два миллиона строк надо выбрать одну строку, т.е .как в примере выше. Но при текущей реализации такая функция скорее всего проиграет в скорости построчному чтению файла через gets(). Да и задача такая не должна возникать. 
PM MAIL   Вверх
TSVET
Дата 25.5.2008, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 6.9.2007

Репутация: нет
Всего: нет



Скорее такая задача поставлена от нечего делать. И задача эта такова: сделать что-то абсурдное(обойтись без мускуля), но чтоб это было вполне рабочим. А потом когда это реализовано, торжественно ударить в бубен и крикнуть: БРАВО! Я изобрёл велосипед!  smile
Задача не столько практическая, сколько познавательная. Я думаю, что пойму как работает простейшая БД.

А вообще, спасибо за здравую критику, и разъяснение про fseek(), я тоже вначале думал про индексный файл и про fseek(), но потом почему-то забыл...

А вообще fseek() это и есть ответ на мой вопрос, это правда убило весь смысл моего кода.
Можно поступить так: по-прежнему структура - каждая строчка это страница.
Храним в индексном файле положение каждой строчки в байтах.
Подъезжаем к строке fseek'ом, вытягиваем её fgets'ом.

Храним ID страниц + положения файлового указателя соответствующих строк, и Title страницы.
Пример индексного файла:
Код

1:0:Главная
2:8563:Рыболовные снасти
3:15672:Магазин


И на последок: Если мы меняем положение страницы, то оперируем только с ID'шниками в индексном файле.
Если мы удаляем то читаем по одному мегабайту fread'ом, перекидываем во временный файл. Если расстояние от позиции с которой читаем до позиции удаляемой строки меньше одного мегабайта, то указываем fread'у прочитать с текущей позиции до позиции удаляемой строки. Перекидываем во временный файл. Пропускаем вхолостую fgets'ом удаляемую строку, не перекидываем её во временный файл. Продолжаем читать fread'ом по мегабайту с позиции конца удаляемой строки, перекидываем во временный, так повторяем цикл до конца файла. Копируем временный файл на место старого.

УРА! Я мозгоё... мозголом! smile
Всё это я делаю ради того, чтоб мозги не засохли. Так что не следует воспринимать это вштыки!

Ну и на последок, ради пущего мозголомства я думаю за хорошие деньги нанять программиста, который реализует простую ЦМС на этом принципе. Если меня конечно не пошлют куда по-дальше...
Я РАСЧИТЫВАЮ ПОЛУЧИТЬ ГРАНТ ЗА САМЫЙ АБСУРДНЫЙ ПРОЕКТ. smile 
PM MAIL WWW ICQ   Вверх
Feldmarschall
Дата 25.5.2008, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок
****


Профиль
Группа: Участник
Сообщений: 2641
Регистрация: 11.12.2007

Репутация: 22
Всего: 32



Цитата(TSVET @  25.5.2008,  23:05 Найти цитируемый пост)
Если мы меняем положение страницы, то оперируем только с ID'шниками в индексном файле.

только если ID'шник не служит идентификатором страницы. 
PM   Вверх
TSVET
Дата 26.5.2008, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 6.9.2007

Репутация: нет
Всего: нет



Точнее меняем местами строки в индексном файле.

Наверное если попытаться придумать мускуль, то мозг расплавится. Не стоит так рисковать мозгами smile 
PM MAIL WWW ICQ   Вверх
Feldmarschall
Дата 26.5.2008, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок
****


Профиль
Группа: Участник
Сообщений: 2641
Регистрация: 11.12.2007

Репутация: 22
Всего: 32



TSVET, ты запутаешься.
В принципе, мысль верная: индекс - это и есть файл, заранее отсортированный по ключевому полю.
Но из этого следует, что менять порядок ID - нельзя. Если нужна сортировка, то надо для неё заводить другое поле.
PM   Вверх
TSVET
Дата 26.5.2008, 15:26 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 6.9.2007

Репутация: нет
Всего: нет



О, уже количество полей увеличивается. Как же их все обрабатывать-то.
Если количество полей продолжит расти, то на индексный файл придётся создавать еще один индексный файл)))))... шучу.

Сномневаюсь... даже если дать такое техническое задание даже очень хорошему программисту, то думаю даже он сломает голову... или всё это выльется в круглую сумму. хм.

Открытие: всё это может и будет работоспособным. Только вот от мускуля будет отличаться вот чем: если мы захотим расширить функционал, добавить новую фичу то тут врядли что-то выйдет. Это не мускуль. Здесь нет аналогов мускульных запросов. Всё хорошо до тех пор, пока структура хранимых данных проста, и особых требований к запросам нет. Хотя даже с простыми данными не вполне ясно как реализовать нормальный поиск.

Поскольку это всё страницы в ЦМС, то надо выводить еще и меню, а так как в задуме оно трёхуровневое древовидное, то в индекс добавляется еще одно поле, в котором цифры 1, 2 или 3 указывающие на уровень пункта в меню. Ужос.


Как-то я сбоку посмотрел на свои рассуждения, представил себя идиотом smile 
Файло-фетишизм...
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1155 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.