Comments 30
Ну, многие вопросы могли бы и там в комментариях спросить. Но можно и здесь.
Что знаю, расскажу по-порядку.
1. Да, я знаю, что имена с точки не показываются в Покете. Была мысль сделать то же самое, но не хотелось экспериментировать с возможными вылезающими багами. Ну и, в конце концов, настройка на то и настройка, что каждый может поменять, как ему удобнее. В любом случае спасибо. Если вы подтверждаете, что это не приносит проблем, то с точки начинать имя хранилища наверное самое оно.
2. Именно поэтому я в статье и упомянул о том, что скрипт делался под винду. В моем случае предполагается, что файлы пишутся на флешку или промежуточную директорию на винте именно из-под винды, на устройстве в результате русские имена файлов/каталогов преобразуются в юникод. Так же в скрипте внутри есть рекодинг с помощью iconv(), можно поубирать либо добавить где надо автоматическое преобразование. Но есть такой момент — все приводится внутри к 1251.
3. В моей статье я указал про параметры вызова get_splitten_dirs() в основном скрипте. Именно ними можно регулировать создание доп.уровней типа «три первых буквы» и таким образом рулить глубиной вложенности. Т.к. выложенный скрипт работает без промежуточной БД, затруднительно определить заранее количество книг в том или ином разделе, и соответственно автоматом рассчитать требуемую глубину вложенности каталогов. Тут уж извините )
4. Вы можете мне в личку скинуть примеры таких файлов? Последние правки парсера были связаны с добавлением обработки html-комментариев, и полного тестирования механизма после этих правок не было. Возможно глюки связаны именно с этим. Если сбросите, я их погоняю, поправлю парсер. Еще в основном скрипте «process.php» можете попробовать заменить вызов xmlp_data2struct_old() на xmlp_data2struct(). Это два варианта парсинга. Отличаются механизмом работы с регулярками.
Кстати, в настройках массив 'tags_processing' рулит генерацией регулярок для парсера, возможно есть смысл сменить настройку 'pattern_type' на XMLP_TPS_SAFE. В таком случае будет принудительно ограничена жадность(greedy) регулярки и соседними параметрами будет четко ограничена длина имени тега и аттрибутов. то есть вместо конструкций вида [^\s\<\>]*? будут работать конструкции вида [^\s\<\>]{0,1024}, и таким образом будет работать что-то типа защиты от переполнения буффера. В вебе, кстати, лучше всегда так писать регулярки.
5. Да, флешка монтируется на /mnt/ext2, а внутренняя память на /mnt/ext1. Могли и там в комментах спросить, я бы ответил ) Я просто посчитал, что если в той статье слишком развернуто описывать работу Покета, включая описание подобных мелочей, статья будет километровая, многие не осилят. Она и так длинновата получилась )
6. Зиповка файлов предназначена именно для выкачки например всей флибусты. Текущая флибуста уже на две флешки по 32Гб минимум влезет, и это в зипах, да и то не факт, так что зипование важнее времени открытия. Но чесгря я не замечаю особой задержки между открытием fb2 файла и открытием его же в зипе. Чтение зипов обычно не особо ресурсоемкая процедура, по крайней мере по сравнению с упаковкой. В любом случае, настройка для того и вынесена — кто как хочет, так и делает )
Кстати, если проверите работу с образом диска, может в этот пост добавите потом мануал? Это очень полезно будет по моему мнению.
P.S. У вас последние мои исходники? Там в статье было пара обновлений, в конце статьи читайте разделы UPD и UPD2.
Что знаю, расскажу по-порядку.
1. Да, я знаю, что имена с точки не показываются в Покете. Была мысль сделать то же самое, но не хотелось экспериментировать с возможными вылезающими багами. Ну и, в конце концов, настройка на то и настройка, что каждый может поменять, как ему удобнее. В любом случае спасибо. Если вы подтверждаете, что это не приносит проблем, то с точки начинать имя хранилища наверное самое оно.
2. Именно поэтому я в статье и упомянул о том, что скрипт делался под винду. В моем случае предполагается, что файлы пишутся на флешку или промежуточную директорию на винте именно из-под винды, на устройстве в результате русские имена файлов/каталогов преобразуются в юникод. Так же в скрипте внутри есть рекодинг с помощью iconv(), можно поубирать либо добавить где надо автоматическое преобразование. Но есть такой момент — все приводится внутри к 1251.
3. В моей статье я указал про параметры вызова get_splitten_dirs() в основном скрипте. Именно ними можно регулировать создание доп.уровней типа «три первых буквы» и таким образом рулить глубиной вложенности. Т.к. выложенный скрипт работает без промежуточной БД, затруднительно определить заранее количество книг в том или ином разделе, и соответственно автоматом рассчитать требуемую глубину вложенности каталогов. Тут уж извините )
4. Вы можете мне в личку скинуть примеры таких файлов? Последние правки парсера были связаны с добавлением обработки html-комментариев, и полного тестирования механизма после этих правок не было. Возможно глюки связаны именно с этим. Если сбросите, я их погоняю, поправлю парсер. Еще в основном скрипте «process.php» можете попробовать заменить вызов xmlp_data2struct_old() на xmlp_data2struct(). Это два варианта парсинга. Отличаются механизмом работы с регулярками.
Кстати, в настройках массив 'tags_processing' рулит генерацией регулярок для парсера, возможно есть смысл сменить настройку 'pattern_type' на XMLP_TPS_SAFE. В таком случае будет принудительно ограничена жадность(greedy) регулярки и соседними параметрами будет четко ограничена длина имени тега и аттрибутов. то есть вместо конструкций вида [^\s\<\>]*? будут работать конструкции вида [^\s\<\>]{0,1024}, и таким образом будет работать что-то типа защиты от переполнения буффера. В вебе, кстати, лучше всегда так писать регулярки.
5. Да, флешка монтируется на /mnt/ext2, а внутренняя память на /mnt/ext1. Могли и там в комментах спросить, я бы ответил ) Я просто посчитал, что если в той статье слишком развернуто описывать работу Покета, включая описание подобных мелочей, статья будет километровая, многие не осилят. Она и так длинновата получилась )
6. Зиповка файлов предназначена именно для выкачки например всей флибусты. Текущая флибуста уже на две флешки по 32Гб минимум влезет, и это в зипах, да и то не факт, так что зипование важнее времени открытия. Но чесгря я не замечаю особой задержки между открытием fb2 файла и открытием его же в зипе. Чтение зипов обычно не особо ресурсоемкая процедура, по крайней мере по сравнению с упаковкой. В любом случае, настройка для того и вынесена — кто как хочет, так и делает )
Кстати, если проверите работу с образом диска, может в этот пост добавите потом мануал? Это очень полезно будет по моему мнению.
P.S. У вас последние мои исходники? Там в статье было пара обновлений, в конце статьи читайте разделы UPD и UPD2.
P.P.S. А, сорри, не внимательно прочитал о бесплотности духа. Действительно вы же не могли там в камментах спросить ничего )) Извините.
Еще в догонку.
Я пожалуй в ближайшие пару дней допилю скрипт, учитывая ваши замечания.
По крайней мере частично.
1. переведу все комментарии в коде на англицкий, чтобы не нужно было перекодировать.
2. допилю процедуру get_splitten_dirs(), добавлю в нее гибкую генерацию регионов типа «Аве-Арц» и выведу все ее настройки в начало скрипта.
3. добавлю опцию на предмет «выливать в UTF-8» для генерации конечных путей под линуксом.
Не уверен, что буду переводить «genres.inc» и всю внутреннюю работу сразу на UTF-8. Тут я универсального решения для работы с кодом не вижу пока. Если подскажете, буду рад. Хотя, справедливости ради, это мои личные заморочки — я привык к своему редактору для исходников, а он не поддерживает UTF-8. Наверное пора задуматься о смене редактора )))
Я пожалуй в ближайшие пару дней допилю скрипт, учитывая ваши замечания.
По крайней мере частично.
1. переведу все комментарии в коде на англицкий, чтобы не нужно было перекодировать.
2. допилю процедуру get_splitten_dirs(), добавлю в нее гибкую генерацию регионов типа «Аве-Арц» и выведу все ее настройки в начало скрипта.
3. добавлю опцию на предмет «выливать в UTF-8» для генерации конечных путей под линуксом.
Не уверен, что буду переводить «genres.inc» и всю внутреннюю работу сразу на UTF-8. Тут я универсального решения для работы с кодом не вижу пока. Если подскажете, буду рад. Хотя, справедливости ради, это мои личные заморочки — я привык к своему редактору для исходников, а он не поддерживает UTF-8. Наверное пора задуматься о смене редактора )))
2. Да, было бы круто. Только хорошо бы сразу сделать генерацию многоуровневого дерева, тогда вроде бы нужен единственный параметр — максимальное количество детей у каждой вершины. Должно быть равно количеству строк на экране; хотя я уже засомневался — может удобней лишний раз нажать PgDn, чем иметь лишний уровень?
Кстати, как насчет того, чтобы выложить, например, в гитхаб?
Кстати, как насчет того, чтобы выложить, например, в гитхаб?
2. Не очень понял вторую часть абзаца. Если вы о интерфейсе покета, то перейти на следующую страницу списка не проблема, проблема в том, чтобы файлов/поддиректорий в одной директории было условно не более сотни. Тогда и книжка тупить не будет долго, считывая содержимое папки, и навигация по небольшому количеству страниц списка будет приемлемой.
С гитхабом даже не думал, если чесно. Я не вижу такой выскокой «стоимости» данного скрипта, чтобы превращать его в какой-то развивающийся проект. Скорее как описание и пример реализации идеи для тех ребят, которые пишут десктопные программы-каталогизаторы, либо как доп.помощник для людей, имеющих покетбуки или совместимые с «брожением по файловой системе» аппараты.
С гитхабом даже не думал, если чесно. Я не вижу такой выскокой «стоимости» данного скрипта, чтобы превращать его в какой-то развивающийся проект. Скорее как описание и пример реализации идеи для тех ребят, которые пишут десктопные программы-каталогизаторы, либо как доп.помощник для людей, имеющих покетбуки или совместимые с «брожением по файловой системе» аппараты.
Да, я об интерфейсе самого устройства: если содержимое директории будет занимать несколько страниц, то нужно будет нажимать несколько раз кнопку PgDn, чтобы найти нужное, а он каждый раз перерисовывает экран и тормозит. А вот бродить вверх-вниз на одной странице — гораздо более быстрая операция. Глобальный вопрос в том, чтобы минимизировать полное время поиска нужного файла. Вроде бы очевидно, что для этого нужно иметь на каждом уровне примерно одинаковое число веток, и вопрос лишь в том, сколько именно: если больше, то надо листать страницы, если меньше — будет глубже дерево. Причем глубина растет логарифмически, поэтому, возможно, выгоднее сделать столько веток, чтобы умещалось на одной странице.
Про гитхаб: операция помещения туда почти ничего не стоит (если, разумеется, человек вообще владеет git'ом). А польза от «как описание и пример реализации идеи» уже стоит того.
Про гитхаб: операция помещения туда почти ничего не стоит (если, разумеется, человек вообще владеет git'ом). А польза от «как описание и пример реализации идеи» уже стоит того.
>> Глобальный вопрос в том, чтобы минимизировать полное время поиска нужного файла.
Не думаю, что это является «бутылочным горлышком». Иными словами, минимизировать конечно это хорошо, но не до фанатизма.
Я не знаю, где у вас на устройстве кнопка PgDn, у меня просто вправо-влево джойстиком гуляние по страницам. И не факт, что переместиться куда нужно можно по одной странице быстрее, чем по, скажем, трем. Можно жмакать кнопку вверх, чтобы перейти сразу вниз страницы и двигаться по списку вверх, это да, но иногда например всего одно нажатие вправо переместит вас на следующую страницу и возможно в ее начале сразу будет требуемый вам пункт.
В общем, так или иначе, если страниц приемлемое количество(3-5-7), то доп.навигация по ним не является такой уж проблемой.
Просто не забывайте, что предназначение читалки в первую очередь в чтении, а уже во вторую — в навигации. Оптимизация не всегда должна быть реализована по максимуму, скорее в копромиссах с функциональностью и универсальностью.
Про гитхаб еще подумаю.
Не думаю, что это является «бутылочным горлышком». Иными словами, минимизировать конечно это хорошо, но не до фанатизма.
Я не знаю, где у вас на устройстве кнопка PgDn, у меня просто вправо-влево джойстиком гуляние по страницам. И не факт, что переместиться куда нужно можно по одной странице быстрее, чем по, скажем, трем. Можно жмакать кнопку вверх, чтобы перейти сразу вниз страницы и двигаться по списку вверх, это да, но иногда например всего одно нажатие вправо переместит вас на следующую страницу и возможно в ее начале сразу будет требуемый вам пункт.
В общем, так или иначе, если страниц приемлемое количество(3-5-7), то доп.навигация по ним не является такой уж проблемой.
Просто не забывайте, что предназначение читалки в первую очередь в чтении, а уже во вторую — в навигации. Оптимизация не всегда должна быть реализована по максимуму, скорее в копромиссах с функциональностью и универсальностью.
Про гитхаб еще подумаю.
Все-таки лучше выложите. Ей там самое место.
Эмм… А вы не могли бы прояснить некоторые моменты?
Я не знаком с гитхабом, только приблизительно понимаю, что это. Не работаю я просто в комманде над некими шаровыми исходниками. Когда-то немного работал с какой-то древней системой контроля версий, на том мои познания и заканчиваются. В моей основной деятельности это просто не нужно.
И так, вопросы:
Какой смысл туда выкладывать этот проект? В целом? Ну в смысле… Не знаю как сказать… Для чего я это делаю и на что мне ориентироваться?
Я вот зарегистрировался, вылил вроде проект в репозиторий. Сгенерил RSA ключ с паролем, как подсказывал гайд на гитхабе. Надо было пароль? Или лучше перегенерить ключи без него?
Как я понял, гитхаб нужен для двух вещей:
1. чтобы пользователи данного скрипта могли неким унифицированным методом всегда получить свежайшие исходники, так же как получают их с других проектов на том же гитхабе.
2. давать нужным проверенным/заинтересованным людям права тоже что-то там править и дописывать.
Верно?
Тогда как лучше отконфигурить репозиторий?
Какие важные моменты нужно мне учесть, типа необходимости генерации этих SSH-паролей?
Спасибо.
Я не знаком с гитхабом, только приблизительно понимаю, что это. Не работаю я просто в комманде над некими шаровыми исходниками. Когда-то немного работал с какой-то древней системой контроля версий, на том мои познания и заканчиваются. В моей основной деятельности это просто не нужно.
И так, вопросы:
Какой смысл туда выкладывать этот проект? В целом? Ну в смысле… Не знаю как сказать… Для чего я это делаю и на что мне ориентироваться?
Я вот зарегистрировался, вылил вроде проект в репозиторий. Сгенерил RSA ключ с паролем, как подсказывал гайд на гитхабе. Надо было пароль? Или лучше перегенерить ключи без него?
Как я понял, гитхаб нужен для двух вещей:
1. чтобы пользователи данного скрипта могли неким унифицированным методом всегда получить свежайшие исходники, так же как получают их с других проектов на том же гитхабе.
2. давать нужным проверенным/заинтересованным людям права тоже что-то там править и дописывать.
Верно?
Тогда как лучше отконфигурить репозиторий?
Какие важные моменты нужно мне учесть, типа необходимости генерации этих SSH-паролей?
Спасибо.
Я, по правде сказать, самим гитхабом и не пользовался (как участник какого-либо проекта). Пользуюсь своим сервером с зоопарком репозиториев. ;)
На самом деле, когда я предлагал «выложить на гитхаб», имел в виду просто поместить в какой-либо публичный репозиторий, даже не обязательно git (хотя сам уже давно не пользуюсь ни subversion, ни, тем более, CVS — только git'ом).
> Как я понял, гитхаб нужен для двух вещей:…
К вышеуказанным пунктам можно добавить хранение истории комитов, а также возможность заинтересованным (но непроверенным) людям удобно делать свои ветки и форки. Да, слово «гитхаб» здесь можно заменить на более общее «любой публичный репозиторий». Если у вас есть предпочтение (или умение) использовать не гит, а, например, mercury или subversion, то лучше пользоваться ими; только придется найти соответствующий сервер или завести свой.
> Тогда как лучше отконфигурить репозиторий?
Это можно по ходу менять по мере надобности, сейчас вроде можно оставить всё по умолчанию.
Насчет ssh-ключей. Протокол ssh — один из общих методов доступа к git-серверу. Сам по себе ssh-протокол универсален (запуск программ (прежде всего shell) на удаленной машине) и имеет два основных способа доступа к серверу: пароль и ключ (обычно RSA). Насколько я понял, конкретно в github доступ по паролю отключен (это просто настройка сервера), но есть логин/пароль для доступа на веб-сервер, которые совершенно ортогональны. Что касается ssh-ключа, то его как раз лучше делать БЕЗ passphrase (почему-то принято говорить, что у ключа не password, а passphrase): одна из функций ключа (помимо большей криптозащиты) — снятие необходимости каждый раз набирать пароль при доступе с доверенного компа. Passphrase нужна лишь на случай взлома вашего компа и кражи с него секретной части ключа. В данном случае это не очень осмысленно, поскольку снявши голову (домашний комп) по волосам (логин на гитхабе) не плачут.
Да, я только что зарегистрировался на гитхабе с логином janatem. Чтоб было.
На самом деле, когда я предлагал «выложить на гитхаб», имел в виду просто поместить в какой-либо публичный репозиторий, даже не обязательно git (хотя сам уже давно не пользуюсь ни subversion, ни, тем более, CVS — только git'ом).
> Как я понял, гитхаб нужен для двух вещей:…
К вышеуказанным пунктам можно добавить хранение истории комитов, а также возможность заинтересованным (но непроверенным) людям удобно делать свои ветки и форки. Да, слово «гитхаб» здесь можно заменить на более общее «любой публичный репозиторий». Если у вас есть предпочтение (или умение) использовать не гит, а, например, mercury или subversion, то лучше пользоваться ими; только придется найти соответствующий сервер или завести свой.
> Тогда как лучше отконфигурить репозиторий?
Это можно по ходу менять по мере надобности, сейчас вроде можно оставить всё по умолчанию.
Насчет ssh-ключей. Протокол ssh — один из общих методов доступа к git-серверу. Сам по себе ssh-протокол универсален (запуск программ (прежде всего shell) на удаленной машине) и имеет два основных способа доступа к серверу: пароль и ключ (обычно RSA). Насколько я понял, конкретно в github доступ по паролю отключен (это просто настройка сервера), но есть логин/пароль для доступа на веб-сервер, которые совершенно ортогональны. Что касается ssh-ключа, то его как раз лучше делать БЕЗ passphrase (почему-то принято говорить, что у ключа не password, а passphrase): одна из функций ключа (помимо большей криптозащиты) — снятие необходимости каждый раз набирать пароль при доступе с доверенного компа. Passphrase нужна лишь на случай взлома вашего компа и кражи с него секретной части ключа. В данном случае это не очень осмысленно, поскольку снявши голову (домашний комп) по волосам (логин на гитхабе) не плачут.
Да, я только что зарегистрировался на гитхабе с логином janatem. Чтоб было.
Добавил. Ключ перегенерил без пассфразы.
github.com/dsdcorp/fb2p
Позже обновлю свой пост и добавлю туда ссылку на Гит.
github.com/dsdcorp/fb2p
Позже обновлю свой пост и добавлю туда ссылку на Гит.
1. По правде сказать, я и помыслить себе не могу, чтобы возник баг из-за имени директории. С другой стороны я уже сталкивался с чем-то таким: закомитил в репозиторий файл aux.tcl, а потом коллеги не могли его выкачать из-за того, что в винде имя файла aux соответствует устройству.
2. С использованием cp1251 во внутренней кухне я вижу только одну проблему: некоторые алфавиты (арабский, иврит, может быть даже украинский) в нее не умещаются, поэтому либо сломается внутренний вызов конвертера, либо на выходе будут неадекватные символы.
3. Я примерно так и сделал — поковырялся в get_splitten_dirs(), чтобы убрать трехбукрвенные директории. Естественно, построение префиксного дерева требует более серьезного рефакторинга.
4. Попозже (в нерабочее время) я повторю процедуру, чтобы найти конкретно проблемные файлы (а то я их уже потер). Сейчас могу сказать, что проблемы возникли с той библиотекой, что была на устройстве (или на прилагаемом диске) при покупке. Возможно, я что-то переносил, но скорее всего изначально были директории library/{Зарубежная Классика, Русская Классика}, и в обеих были плохие файлы.
Объяснение, что это из-за регвыров — вполне логичное.
Про образ раздела сделаю.
Исходники были не последние, а, скорее всего, первые.
2. С использованием cp1251 во внутренней кухне я вижу только одну проблему: некоторые алфавиты (арабский, иврит, может быть даже украинский) в нее не умещаются, поэтому либо сломается внутренний вызов конвертера, либо на выходе будут неадекватные символы.
3. Я примерно так и сделал — поковырялся в get_splitten_dirs(), чтобы убрать трехбукрвенные директории. Естественно, построение префиксного дерева требует более серьезного рефакторинга.
4. Попозже (в нерабочее время) я повторю процедуру, чтобы найти конкретно проблемные файлы (а то я их уже потер). Сейчас могу сказать, что проблемы возникли с той библиотекой, что была на устройстве (или на прилагаемом диске) при покупке. Возможно, я что-то переносил, но скорее всего изначально были директории library/{Зарубежная Классика, Русская Классика}, и в обеих были плохие файлы.
Объяснение, что это из-за регвыров — вполне логичное.
Про образ раздела сделаю.
Исходники были не последние, а, скорее всего, первые.
2. Ага, могло быть такое с совсем «не нашими» языками. Я расчитывал только под англицкий и русский, потому не делал поддержки остальных. Впрочем, всякие французско-немецкие с умляутами тоже по идее должны нормально мапиться в 1251 кодировку. И украинские тоже должны нормально обрабатываться.
3. у get_splitten_dirs() в текущей реализации есть два параметра: $lcnt и $both_fld. Это второй и четвертый параметры по счету соответственно.
если установить $lcnt(количество букв) в 0, и $both_fld(оба уровня) в false(или не передавать), то в директориях типа 'Буквы А-Я/' будет сразу список авторов-жанров-серий, без промежуточных одно- и многобуквенных поддиректорий.
если $lcnt=1 и $both_fld=false, то только однобуквенный уровень.
если $lcnt>1 и $both_fld=false, то один уровень с количеством букв $lcnt.
если $lcnt>1 и $both_fld=true, то уровень с первой буквой плюс уровень с количеством букв $lcnt.
4. Будет время, погоняю на стандартной поставке, посмотрю что там к чему.
Еще может отличаться работа с регулярками под виндой и линуксом. Раньше я встречал разницу в обработке тех же точкозаменителей .*?, при чем не особо зависимо от параметров самой регулярки. Хотя во-первых давно должны были привести в порядок эти различия, во-вторых не помню, вроде это только в древнем перле под разные системы были такие различия, да и то, по сравнению обычного перла с ActivePerl под винду, и в-третьих у себя я не использовал эти спорные штуки(точку).
3. у get_splitten_dirs() в текущей реализации есть два параметра: $lcnt и $both_fld. Это второй и четвертый параметры по счету соответственно.
если установить $lcnt(количество букв) в 0, и $both_fld(оба уровня) в false(или не передавать), то в директориях типа 'Буквы А-Я/' будет сразу список авторов-жанров-серий, без промежуточных одно- и многобуквенных поддиректорий.
если $lcnt=1 и $both_fld=false, то только однобуквенный уровень.
если $lcnt>1 и $both_fld=false, то один уровень с количеством букв $lcnt.
если $lcnt>1 и $both_fld=true, то уровень с первой буквой плюс уровень с количеством букв $lcnt.
4. Будет время, погоняю на стандартной поставке, посмотрю что там к чему.
Еще может отличаться работа с регулярками под виндой и линуксом. Раньше я встречал разницу в обработке тех же точкозаменителей .*?, при чем не особо зависимо от параметров самой регулярки. Хотя во-первых давно должны были привести в порядок эти различия, во-вторых не помню, вроде это только в древнем перле под разные системы были такие различия, да и то, по сравнению обычного перла с ActivePerl под винду, и в-третьих у себя я не использовал эти спорные штуки(точку).
>> Объяснение, что это из-за регвыров — вполне логичное.
Да не очень оно и логичное. У меня регвыражения используются, чтобы отделить теги от текста между ними. То есть не так, как все обычно пытаются регвыражениями вообще все распарсить сходу. Дальше обработка в цикле последовательным перемещением по тегам, сколько текста между ними — вообще не важно.
Однако в последних версиях PHP, как я слышал, сделан большой упор в сторону передачи параметров ссылками(references), вот это может вполне сказаться на жадности к памяти. Есть атомарные функции типа strlen или substr, которые при передаче в них PHP-шного референса пытаются автоматически превратить его в независимую переменную(понятия не имею зачем), для чего им приходится создавать копию этой переменной в памяти. Из-за этого эти функции тупят и нажирают стек, особенно в больших циклах.
Вы можете самостоятельно в этом убедиться, попытавшись замерить производительность двух, на первый взгляд идентичных, циклов:
Второй цикл идентичен первому, но получает на вход референс, из-за этого работает на порядки дольше.
Хотя, опять же, я свежайший PHP нигде не ставил, возможно у него как раз с этим все в порядке, но на производительность могут влиять как раз некоторые мои трюки, разработанные именно для более старых версий PHP.
В общем, так или иначе, с референсами в PHP нужно быть очень аккуратным, ибо это совсем не одно и то же, что pointers в Си.
P.S. и так же все-таки попробуйте мой совет выше сменить главную функцию парсинга с xmlp_data2struct_old() на xmlp_data2struct(). Эта функция хоть и работает чуть дольше xmlp_data2struct_old(), но не использует strlen или substr внутри себя.
А так же можно попробовать отрубить в настройках параметр 'include_comments'. В таком случае xmlp_data2struct() будет работать даже быстрее, чем xmlp_data2struct_old(), хоть и html-комментарии превратит в html-коды.
Да не очень оно и логичное. У меня регвыражения используются, чтобы отделить теги от текста между ними. То есть не так, как все обычно пытаются регвыражениями вообще все распарсить сходу. Дальше обработка в цикле последовательным перемещением по тегам, сколько текста между ними — вообще не важно.
Однако в последних версиях PHP, как я слышал, сделан большой упор в сторону передачи параметров ссылками(references), вот это может вполне сказаться на жадности к памяти. Есть атомарные функции типа strlen или substr, которые при передаче в них PHP-шного референса пытаются автоматически превратить его в независимую переменную(понятия не имею зачем), для чего им приходится создавать копию этой переменной в памяти. Из-за этого эти функции тупят и нажирают стек, особенно в больших циклах.
Вы можете самостоятельно в этом убедиться, попытавшись замерить производительность двух, на первый взгляд идентичных, циклов:
$ind=200;
$cnt=10;
$max=1000;
$test_str=str_repeat(' ', 10000000);
$a1=array();
for ($i=0;$i<$max;$i++) {
$a1[]=substr($test_str, $ind, $cnt);
}
$test_str1=&$test_str;
$a2=array();
for ($i=0;$i<$max;$i++) {
$a2[]=substr($test_str1, $ind, $cnt);
}
Второй цикл идентичен первому, но получает на вход референс, из-за этого работает на порядки дольше.
Хотя, опять же, я свежайший PHP нигде не ставил, возможно у него как раз с этим все в порядке, но на производительность могут влиять как раз некоторые мои трюки, разработанные именно для более старых версий PHP.
В общем, так или иначе, с референсами в PHP нужно быть очень аккуратным, ибо это совсем не одно и то же, что pointers в Си.
P.S. и так же все-таки попробуйте мой совет выше сменить главную функцию парсинга с xmlp_data2struct_old() на xmlp_data2struct(). Эта функция хоть и работает чуть дольше xmlp_data2struct_old(), но не использует strlen или substr внутри себя.
А так же можно попробовать отрубить в настройках параметр 'include_comments'. В таком случае xmlp_data2struct() будет работать даже быстрее, чем xmlp_data2struct_old(), хоть и html-комментарии превратит в html-коды.
4. Прогнал стандартную поставку Покета 912. Отработало на виртуалке за время меньше минуты обоими способами: xmlp_data2struct_old() и xmlp_data2struct(). В первом случае в пике памяти кушал чуть более 70Мб, обычно около 50-55, во втором случае максимум около 45Мб, обычно 38-40.
Не лег в результирующие директории только «Евгений Онегин» Пушкина, да и то, только потому, что автор не был прописан в метатегах книги — только в начале самого текста поэмы(или романа в стихах, если правильнее).
Вот кстати еще одна пометка, что стоит добавить в настройки и алгоритм — что делать с файлами с кривыми метатегами, не подходящими под условия каталогизатора.
А так еще в некоторые файлы добавилось в результате несколько байт — видимо мелкие огрехи поисправляло, типа что-то(может быть даже что-то не обязательное) в HTML-коды перевело.
В общем, ошибок в лог не написало никаких, поэтому делаем вывод, что левых тегов и косяков XML-структуры не встречалось.
Может скинете мне свой набор тестовой поставки?
Там вообще только FB2 или есть epub например?
Не лег в результирующие директории только «Евгений Онегин» Пушкина, да и то, только потому, что автор не был прописан в метатегах книги — только в начале самого текста поэмы(или романа в стихах, если правильнее).
Вот кстати еще одна пометка, что стоит добавить в настройки и алгоритм — что делать с файлами с кривыми метатегами, не подходящими под условия каталогизатора.
А так еще в некоторые файлы добавилось в результате несколько байт — видимо мелкие огрехи поисправляло, типа что-то(может быть даже что-то не обязательное) в HTML-коды перевело.
В общем, ошибок в лог не написало никаких, поэтому делаем вывод, что левых тегов и косяков XML-структуры не встречалось.
Может скинете мне свой набор тестовой поставки?
Там вообще только FB2 или есть epub например?
Так, я нашел один из плохих файлов (хотя он не единственный). Ломаются обе версии xmlp_data2struct_old() и xmlp_data2struct(). На хороших файлах больше 100МБ вроде не отъедалось, а на этом жрется вся память.
Что-то не соображу, как лучше файл передать. (Он был в сборке «Русская классика» с диска, прилагаемого к устройству; его md5sum: 0f3730e48d5db8bd5163c2bb94f21906 Lohvitskaya_Oborotni.55375.fb2 .)
Что-то не соображу, как лучше файл передать. (Он был в сборке «Русская классика» с диска, прилагаемого к устройству; его md5sum: 0f3730e48d5db8bd5163c2bb94f21906 Lohvitskaya_Oborotni.55375.fb2 .)
Кинул файл в личку.
Скачал. У меня отрабатывает этот файл за 10 миллисекунд.
Важных ошибок нет.
Находит и правит только одну текстовую ошибку в этом абзаце(в его конце):
Так что скорее всего проблемы растут из-за кодировок и как следствие, спотыканий парсера.
Попробуйте в файле test.php в его начале указать эту книжку и прогнать именно test.php.
Указывать вот так(найдете в файле эти строки и поймете что куда):
Он сгенерирует 6 файлов вида «out_xxxxxxx.txt»
и один файл «test_errors.txt»
Зазипуйте и мне перешлите так же через личку. Посмотрю что там не так.
Важных ошибок нет.
Находит и правит только одну текстовую ошибку в этом абзаце(в его конце):
<p>Одна из наших дам раздобыла ее адрес и проездом через тот городок, где жила баронесса, разыскала ее местожительство, но дома не застала. Квартирная хозяйка баронессы отозвалась о ней с большим уважением. - Herr Onegin, - сказала она, - ist ein braver mann. <Господин Онегин... - превосходный человек (нем.). > </p>
Так что скорее всего проблемы растут из-за кодировок и как следствие, спотыканий парсера.
Попробуйте в файле test.php в его начале указать эту книжку и прогнать именно test.php.
Указывать вот так(найдете в файле эти строки и поймете что куда):
$in_fname='Lohvitskaya_Oborotni.55375.fb2';
$fdata=@file_get_contents($in_fname);
Он сгенерирует 6 файлов вида «out_xxxxxxx.txt»
и один файл «test_errors.txt»
Зазипуйте и мне перешлите так же через личку. Посмотрю что там не так.
Исправлено. Мой пост обновлен(UPD4) и исходники тоже.
habrahabr.ru/post/143492/
Перекачивать крайне желательно всем заинтересованным:
Была банальная ошибка копипаста, приводившая к бесконечному циклу при кривом указании жанра.
Извините, мой грубый косяк.
habrahabr.ru/post/143492/
Перекачивать крайне желательно всем заинтересованным:
Была банальная ошибка копипаста, приводившая к бесконечному циклу при кривом указании жанра.
Извините, мой грубый косяк.
Добавил про копирование образа.
Предлагаю набросок алгоритма префиксного дерева.
Берем всё множество строк (авторов), сортируем. Пусть их N штук. Далее, берем параметр q — желаемое количество детей у каждой вершины (макс количество элементов в каждой директории), находим такое n, что
Это будет глубина дерева. Впрочем, для алгоритма ее не нужно вычислять, само получится. Собственно, сам алгоритм:
Берем пачку из первых N/q строк — они все будут помещаться в первую директорию (возможно, вложенно). Нужно найти правильное имя этой директории. Делается это так: берем несколько первых букв первого автора и несколько первых букв последнего в пачке (сколько именно — потом станет ясно), слепляем их через тире — имя готово. Далее, создаем директорию с таким именем и заходим в нее (на самом деле, конечно, лучше отделить создание файлов от вычислений); рекурсивно вызываем алгоритм, передав ему первую пачку строк в качестве всего множества.
Затем выполняем то же самое со второй пачкой — строки с номерами от N/q до 2N/q-1. И т.д. до последней пачки.
Теперь о том, сколько первых букв имени выбирать. Главное — чтобы префикс данной длины различался у последней строки данной пачки и первой строки следующей. Можно также дополнительно потребовать, чтобы на всём уровне все такие длины были одинаковыми — так будет красивее.
Берем всё множество строк (авторов), сортируем. Пусть их N штук. Далее, берем параметр q — желаемое количество детей у каждой вершины (макс количество элементов в каждой директории), находим такое n, что
q^(n-1) < N <= q^n
Это будет глубина дерева. Впрочем, для алгоритма ее не нужно вычислять, само получится. Собственно, сам алгоритм:
Берем пачку из первых N/q строк — они все будут помещаться в первую директорию (возможно, вложенно). Нужно найти правильное имя этой директории. Делается это так: берем несколько первых букв первого автора и несколько первых букв последнего в пачке (сколько именно — потом станет ясно), слепляем их через тире — имя готово. Далее, создаем директорию с таким именем и заходим в нее (на самом деле, конечно, лучше отделить создание файлов от вычислений); рекурсивно вызываем алгоритм, передав ему первую пачку строк в качестве всего множества.
Затем выполняем то же самое со второй пачкой — строки с номерами от N/q до 2N/q-1. И т.д. до последней пачки.
Теперь о том, сколько первых букв имени выбирать. Главное — чтобы префикс данной длины различался у последней строки данной пачки и первой строки следующей. Можно также дополнительно потребовать, чтобы на всём уровне все такие длины были одинаковыми — так будет красивее.
>> Берем всё множество строк (авторов), сортируем.
Дык я вам о чем говорю: где ж его взять-то, это множество, при старте скрипта? Он же понятия не имеет каких у нас и сколько авторов!
Была бы БД уже заполненная — тогда без проблем. Или двойной проход скрипта нужен.
А так у меня скрипт раскладывает каждую книжку сходу сразу как распарсил — он не знает, что там в библиотеке есть еще. Даже предудущие обработанные книги не помнит, кроме порядкового номера )))
Дык я вам о чем говорю: где ж его взять-то, это множество, при старте скрипта? Он же понятия не имеет каких у нас и сколько авторов!
Была бы БД уже заполненная — тогда без проблем. Или двойной проход скрипта нужен.
А так у меня скрипт раскладывает каждую книжку сходу сразу как распарсил — он не знает, что там в библиотеке есть еще. Даже предудущие обработанные книги не помнит, кроме порядкового номера )))
Ну даже двойной проход не проблема — машина-то железная. ;) И БД — это громко сказано. Так, ассоциативный массивчик (в языке, насколько я понял, такой тип встроен, так?).
Можно даже внешний вызов сделать, чтоб количество посчитать:
Правда, это вроде не особо помогает, потому что небходимо выковырять имена из файлов.
Можно даже внешний вызов сделать, чтоб количество посчитать:
find . -name '*.fb2'
Правда, это вроде не особо помогает, потому что небходимо выковырять имена из файлов.
Ассоциативные массивы-то встроены, ака хеши в перле.
Меня именно этот момент и смущает. Я ж весь функционал БД из скриптов своих убрал и выпустил для хабра такую standalone лайт-версию, работающую сходу и без всяких тяжелых обвесов.
А тут вы предлагаете… В общем, раскидывание по ренж-директориям оно-то конечно хорошо, но степень полезности меня смущает.
В моем понимании электрокнижка у любого юзера используется преимущественно 99% времени для непосредственно чтения, и хорошо если 1% времени для поиска книг. Это я про работу с локальной библиотекой, исключая мучения во встроенном браузере и игры во всякие шахматы.
Поэтому кмк текущего поиска вполне достаточно, и он довольно несложен. Лишние пару нажатий погоды не составят.
Кроме того, скриптик этот расчитан в перую очередь для огромных объемов книг, а не простеньких коллекций в пару сотен максимум. А там уже двойной проход и создание массива — это и время, и память.
Более интересным был бы алгоритм разброса и поиска по названиям книг. При чем алгоритм, не требующий предварительного получения этого списка.
Еще как вариант для новых покетбуков(новых прошивок) можно во время работы скрипта создавать и заполнять базу данных explorer.db(SQLite3), которую как раз для индексации и поиска использует новая книжная полка в новых прошивках. Соответсвенно в настройках самого устройства обновления индекса запретить.
И еще не забывайте в свой алгоритм такой момент, как анализ, сколько книжек в каком диапазоне будет. Вполне возможно, что будет диапазон ААА-БББ с парой тысяч, а диапазон ЕЕЕ-ННН — вообще пустой.
И как бы так не получилось, что с вашими "(макс количество элементов в каждой директории)" выйдет хвост из нескольких файлов, выплюнутых в соседний почти пустой диапазон, но при этом подходящих по условию к предыдущему диапазону. В общем, там столько нюансов полезет с этими диапазонами…
Поэтому если уж и делать двухпроходность, то двумя этапами: первый проход — укладываем реквизиты книжек в БД, второй проход — формируем библиотеку для устройства. В БД можно накрутить любые сортировки и вычисления.
То есть вернемся к тому, что у меня и было до создания статьи на хабр. А там уж и до своей системы каталогизированного хранения недалеко. А зачем нам еще одна программа типа Calibre или MyHomelib, да еще и без GUI? )))
Меня именно этот момент и смущает. Я ж весь функционал БД из скриптов своих убрал и выпустил для хабра такую standalone лайт-версию, работающую сходу и без всяких тяжелых обвесов.
А тут вы предлагаете… В общем, раскидывание по ренж-директориям оно-то конечно хорошо, но степень полезности меня смущает.
В моем понимании электрокнижка у любого юзера используется преимущественно 99% времени для непосредственно чтения, и хорошо если 1% времени для поиска книг. Это я про работу с локальной библиотекой, исключая мучения во встроенном браузере и игры во всякие шахматы.
Поэтому кмк текущего поиска вполне достаточно, и он довольно несложен. Лишние пару нажатий погоды не составят.
Кроме того, скриптик этот расчитан в перую очередь для огромных объемов книг, а не простеньких коллекций в пару сотен максимум. А там уже двойной проход и создание массива — это и время, и память.
Более интересным был бы алгоритм разброса и поиска по названиям книг. При чем алгоритм, не требующий предварительного получения этого списка.
Еще как вариант для новых покетбуков(новых прошивок) можно во время работы скрипта создавать и заполнять базу данных explorer.db(SQLite3), которую как раз для индексации и поиска использует новая книжная полка в новых прошивках. Соответсвенно в настройках самого устройства обновления индекса запретить.
И еще не забывайте в свой алгоритм такой момент, как анализ, сколько книжек в каком диапазоне будет. Вполне возможно, что будет диапазон ААА-БББ с парой тысяч, а диапазон ЕЕЕ-ННН — вообще пустой.
И как бы так не получилось, что с вашими "(макс количество элементов в каждой директории)" выйдет хвост из нескольких файлов, выплюнутых в соседний почти пустой диапазон, но при этом подходящих по условию к предыдущему диапазону. В общем, там столько нюансов полезет с этими диапазонами…
Поэтому если уж и делать двухпроходность, то двумя этапами: первый проход — укладываем реквизиты книжек в БД, второй проход — формируем библиотеку для устройства. В БД можно накрутить любые сортировки и вычисления.
То есть вернемся к тому, что у меня и было до создания статьи на хабр. А там уж и до своей системы каталогизированного хранения недалеко. А зачем нам еще одна программа типа Calibre или MyHomelib, да еще и без GUI? )))
> будет диапазон ААА-БББ с парой тысяч, а диапазон ЕЕЕ-ННН — вообще пустой.
По построению в каждой пачке будет одинаковое количество элементов. То есть может случиться так, что создадутся ААА-ААВ и ААГ-ЯЯЯ, но в каждой из них будет (примерно) поровну.
Ну ладно, может такая тулза и не очень целесообразна. Просто я пока не изучил этих калибрей прочие программы-каталогизации. Возможно, какая-нибудь из них меня удовлетворит.
А я уже завелся и скачал SDK для покетбука. ;) Правда, всё равно нет возможность достаточно времени этому уделять…
По построению в каждой пачке будет одинаковое количество элементов. То есть может случиться так, что создадутся ААА-ААВ и ААГ-ЯЯЯ, но в каждой из них будет (примерно) поровну.
Ну ладно, может такая тулза и не очень целесообразна. Просто я пока не изучил этих калибрей прочие программы-каталогизации. Возможно, какая-нибудь из них меня удовлетворит.
А я уже завелся и скачал SDK для покетбука. ;) Правда, всё равно нет возможность достаточно времени этому уделять…
С СДК еще надо сначала поковыряться и разобраться с рендером на экран, потом уж логику писать.
А так с ним не сложно, главное начальный объем азов вкурить. Ну и время конечно на это выделить )
А так с ним не сложно, главное начальный объем азов вкурить. Ну и время конечно на это выделить )
Да и какое там SDK — всего лишь (почему-то закрытая) единственная библа inkview. А весь набор инструментов состоит из gcc для arm, который не обязательно брать из ихнего SDK.
Собственно, API этой библы и нужно вкуривать.
Собственно, API этой библы и нужно вкуривать.
Так а кто говорил о чем-то еще? Там же линукс внутри девайса. Там кроме этой либы, своей оболочки из пары программ и портов общеизвестных прог, типа fbreader, ничего особенного и нет.
Вы можете в директории /mnt/ext1/applications (/applications в флеш-памяти девайса) создавать файлы с расширением .app и содержанием типа:
или
и получить на флешке листинг файловой системы или список процессов.
или еще интереснее:
и вытащить все содержимое на флешку.
По идее достаточно и:
Но я не силен в этом, не знаю, как иначе исключить копирование на флешку собственно /mnt/ext1 и /mnt/ext2, кроме как первым способом.
Я таким образом пошел в магазин, взял девайс посмотреть, вставил свою флеху, запустил с нее же скрипт и слил на нее же все что было в девайсе — нужны были файлы от заводской прошивки, которую у себя я уже давно обновил, а она не публикуется для простого отката на своем же девайсе. Пришлось с магазинного экземпляра сливать. Правда оно мне не помогло в итоге, но это не важно ))
Как запускать скрипты не из папки «Приложения»(/applications)если в «Библиотеке» их не показывает, описано в моем посте в первом UPD.
Вы можете в директории /mnt/ext1/applications (/applications в флеш-памяти девайса) создавать файлы с расширением .app и содержанием типа:
#!/bin/sh
ls -laR / >/mnt/ext2/ls.txt
или
#!/bin/sh
ps ax >/mnt/ext2/ps.txt
и получить на флешке листинг файловой системы или список процессов.
или еще интереснее:
#!/bin/sh
cp -R /mnt/ext3/ /mnt/ext2/myroot/mnt/ 2>/mnt/ext2/cp_mnt_ext3.txt
cp -R /mnt/secure/ /mnt/ext2/myroot/mnt/ 2>/mnt/ext2/cp_mnt_secure.txt
cp -R /bin/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_bin.txt
cp -R /ebrmain/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_ebrmain.txt
cp -R /etc/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_etc.txt
cp -R /lib/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_lib.txt
cp -R /lost+found/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_lost_found.txt
cp -R /proc/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_proc.txt
cp -R /sbin/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_sbin.txt
cp -R /sys/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_sys.txt
cp -R /usr/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_usr.txt
cp -R /var/ /mnt/ext2/myroot/ 2>/mnt/ext2/cp_var.txt
и вытащить все содержимое на флешку.
По идее достаточно и:
#!/bin/sh
cp -R / /mnt/ext2/myroot/ 2>/mnt/ext2/cp.txt
Но я не силен в этом, не знаю, как иначе исключить копирование на флешку собственно /mnt/ext1 и /mnt/ext2, кроме как первым способом.
Я таким образом пошел в магазин, взял девайс посмотреть, вставил свою флеху, запустил с нее же скрипт и слил на нее же все что было в девайсе — нужны были файлы от заводской прошивки, которую у себя я уже давно обновил, а она не публикуется для простого отката на своем же девайсе. Пришлось с магазинного экземпляра сливать. Правда оно мне не помогло в итоге, но это не важно ))
Как запускать скрипты не из папки «Приложения»(/applications)если в «Библиотеке» их не показывает, описано в моем посте в первом UPD.
Sign up to leave a comment.
Еще раз об электронной библиотеке для PocketBook