2015-03-10 3 views
7

Я запускаю Windows   7 - 64-разрядный, с последней версией XAMPP, которая имеет 32-битную версию PHP.PHP тихо оптимизирует последовательные fseek-команды в одну команду fseek?

На тестировании http://php.net/manual/en/function.fseek.php#112647 для очень большого файла (больше, чем PHP_MAX_INT 2147483647) Теперь я вполне уверен, что последовательно следующие fseeks суммируются перед казнью на filepointer.

У меня есть два вопроса:

  1. Могу ли я разбить это суммируя с разумными средствами (или только с обходным, указанной в приведенной выше ссылке)?

  2. Является ли это агрегацией в PHP (как я предполагаю, хотя я не знаю, где на PHP) или в Windows   7?

Ответ себя: Попытка двух обходных путей с несколькими изыскивает не работает на моей системе. Вместо этого они помещают filepointer в разные позиции под PHP_MAX_INT. (32-разрядная версия PHP может только стремиться к PHP_MAX_INT + 192. Чтение оттуда по-прежнему возможно, но я не знаю, как далеко.)

Поэтому вопрос устарел для моего конкретного случая, а 32 -битный PHP может искать только PHP_MAX_INT + 8192, что бы вы ни делали. I оставьте вопрос, потому что два человека проголосовали за него, и может быть заинтересован в общем ответе.

Я подал отчет об ошибке здесь:
https://bugs.php.net/bug.php?id=69213
Результат: С 64-битной PHP сборки он может работать, но я не пробовал.

+0

Примечание. Я не пытался использовать SplFileObject, как было предложено кем-то еще, поскольку я доверяю php-manual, что SplFileObject должен быть просто слоем над обычными командами seek и etc. И я уже перешел на perl для этой конкретной задачи. (Который даже парень на стороне ошибки php понял.) Я не буду разворачивать 64-битную сборку php, если она не является основной. И я не полностью переношусь на perl, просто просматривая и пишу пару очень больших файлов. (И мне очень сложно увидеть какое-либо концептуальное преимущество в SplFileObject. Хотя сопровождающие говорят об этом «с энтузиазмом».) – John

ответ

1

Это не так. Это на самом деле что-то делает даже тупой. Вот фрагмент из исходного кода PHP:

 switch(whence) { 
      case SEEK_CUR: 
       offset = stream->position + offset; 
       whence = SEEK_SET; 
       break; 
     } 

Это в кишках реализации для РНР fseek. Что здесь происходит: если вы скажете PHP искать текущую позицию, это переводит это в «эквивалентный» поиск с начала файла. Это работает только тогда, когда вычисление смещений не переполняется; если это так, то offset - это целое число со знаком, так что это неопределенное поведение.

И, ладно, это потому, что PHP буферизует потоки внутри, поэтому им нужно сделать . Но это не обязательно должно быть так.

Возможно, вам лучше всего попытаться выполнить свою работу на языке, который фактически выполняет то, что вы ему рассказываете.

+0

Это не должно быть проблемой, поскольку изменения в точке чтения и записи сокращаются до смещений от их текущие позиции и дисковая система не будут выполнять ненужные запросы; он будет искать голову там, где ему нужно читать и писать. В этом смысле поиск без чтения или записи - это просто изменение целых чисел. –

+1

Снимите очки с цветным ядром. Эти семантики означают, что никакая PHP-программа не может искать намного больше, чем байты ZEND_LONG_MAX' в файл, даже если файловая система и операционная система способны на это. Поскольку реализация PHP 'SEEK_CUR' содержит неопределенное поведение в формальном, C-стандартном смысле. PHP не будет делать то, что программист сказал ему сделать в этом случае, и это должно быть * неприемлемым *. – Alex

+0

@Alex: Это соответствует тому, что я узнал, попробовав разные целевые значения. (См. Последнюю запись в сообщении php-bug, с которым я связан.) Поэтому я принимаю этот ответ. Поскольку там присутствует ошибка (или старый код), в конечном итоге это не влияет на конечных пользователей, если есть другие оптимизации или ошибки на других уровнях, поскольку эти другие уровни никогда не получат принятые значения. Я предполагаю. Я не в этом. Как написано, я использую perl для одной большой задачи файла. :) Возможно, вы могли бы написать отчет об ошибке с кодами, которые вы нашли, и, возможно, это будет улучшено. :) – John

0

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

Я могу ответить на низком уровне. fseek() в php реализуется с использованием php-потоков. Он объявлен в файле ext/standard/file.h и определен в .c. Его реализация вызывает php_stream_seek(), который вызывает в _php_stream_seek() в streams.c.Выполнение этого низкого уровня осуществляется через оболочку простых потоков, и в этом случае вы можете обратиться к zend_seek или zend_fseek, которые, в свою очередь, просто сопоставляются с 32 или 64-битными seek _ seeki64 c вызовами.

Итак ... если произойдет какое-либо агрегирование, это, похоже, должно быть в оптимизации кода операции или даже ниже в операционной системе или аппаратном обеспечении. Жесткие диски реализуют внекорпоративную выборку для уменьшения расстояний для поиска головы, а системы буферизации файловой системы могут уменьшить количество искажений, которые не имеют побочных эффектов. Если вас беспокоит время чтения диска, первое автоматически обрабатывает это. Если вы заинтересованы в том, чтобы, возможно, перебирая память (требуя больших расстояний без необходимости в буфере), вы могли бы рассмотреть другой подход. Смотрите: http://www.cs.iit.edu/~cs561/cs450/disksched/disksched.html для получения дополнительной информации о том, как диски избегают тратить время поиска.

Надеюсь, это поможет.

Смежные вопросы