![]() |
1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!
![]() ![]() |
![]() |
TarasBer |
![]()
Сообщение
#1
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
Мне очень не нравится скорость побайтового чтения - 3МБ файл читается больше секунды, когда дельфовый аналог на BlockRead считывает его моментально.
Всё, что приходит в голову - открыть файл для типа byte, узнать размер, потом открыть файл для массива данного размера и считать за раз.
Но это выдаёт raised STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW (даже после того, как я вместо заведения массива на стеке завёл указатель) Да и мало ли размер файла изменится между первым и вторым открытиями. И вообще много дёргать винт это плохо. Последний вариант - через ВинАПИ, но мне неохота туда лезть. ПС Настраиваемые пакеты во внутреннем блоке - это сильно. Реально круто, я про язык. Сообщение отредактировано: TarasBer - 31.05.2011 12:16 -------------------- |
IUnknown |
![]()
Сообщение
#2
|
![]() a.k.a. volvo877 ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: ![]() ![]() ![]() |
Цитата Но это выдаёт Не подтверждается... В пустом проекте читает трехмегабайтный файл легко...raised STORAGE_ERROR : EXCEPTION_STACK_OVERFLOW Цитата Всё, что приходит в голову - открыть файл для типа byte, узнать размер, потом открыть файл для массива данного размера и считать за раз. Чтобы узнать размер файла, совсем не обязательно его открывать. Есть пакет Directories, который предоставляет тебе информацию:procedure File_Read isшестимегабайтный файл прочитало меньше, чем за 0.1 секунды. Сообщение отредактировано: IUnknown - 31.05.2011 14:20 |
TarasBer |
![]()
Сообщение
#3
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
Так, я понял. При инициализации шаблона там, в модуле файлов, на стеке создаётся массив соответствующего размера.
> Не подтверждается... В пустом проекте читает трехмегабайтный файл легко... А где в настройках компилятора размер стека правится? Впрочем, это не решение. А если я захочу в кучу прочитать полугиговый файл за раз? Ну допустим, что это неправильно: я могу с той же скоростью читать порциями по 4096 байт, но это же привязывание к размеру кластера (т.е. к особенностям машины). Жаль, что стандартный файловый тип не умеет буферизовать (как я понял). > Чтобы узнать размер файла, совсем не обязательно его открывать. Есть пакет Directories, который предоставляет тебе информацию: Спасибо. Всё-таки, каков оптимальный размер для считывания за раз? Может, есть стандартная функция, которая это говорит, по аналогии с функцией, говорящей оптимальный размер блока для выделения памяти в куче? -------------------- |
IUnknown |
![]()
Сообщение
#4
|
![]() a.k.a. volvo877 ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: ![]() ![]() ![]() |
Цитата Жаль, что стандартный файловый тип не умеет буферизовать Работай с потоками, они умеют. Если правильно организовать ввод из файла, как из потока (правильно - это чтоб не было лишних копирований буфера с места на место, чтоб читать прямо туда, где физически буфер расположен в памяти), то работать будет очень быстро. Года полтора назад на comp.lang.ada некто Gautier (есть такой программист, широко известный в узких кругах) показывал разницу в скорости обработки потока: читал и перезаписывал содержимое одного файла в другой. Первый раз - обычными 'Read/'Write, второй раз - правильно работая с буфером. Так вот второй способ отработал чуть-ли не в 50 раз быстрее (подробностей не помню, но если надо - могу поискать ту ветку).Цитата Может, есть стандартная функция, которая это говорит, по аналогии с функцией, говорящей оптимальный размер блока для выделения памяти в куче? Не встречал никогда. |
TarasBer |
![]()
Сообщение
#5
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
>Работай с потоками, они умеют.
Да только я не умею... Из описания в книге я так и не понял, как должен выглядеть полный пример использования потока. Я не понял, как и что необходимо закрывать. Ну завёл я F: File_Type, ну открыл файл, ну написал S := Stream(F); В конце что делать с этими S и F? Если бы я работал только с F, то я бы просто написал Close, а тут что надо? С этим S надо что-то делать? И ещё. Я не люблю вручную писать закрытие файла по исключению, и просто писать закрытие в конце тоже не люблю, я вообще считаю, что все подобные вещи должны быть завёрнуты в контролируемый объект (и тут простой РАИИ позволяет делать то, где навороченные, но недетерминированные ГЦ не помогут никак), вплоть до жёсткого контроля на уровне запрета компилятора. Так вот, нету ли стандартного контролируемого потока? -------------------- |
IUnknown |
![]()
Сообщение
#6
|
![]() a.k.a. volvo877 ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: ![]() ![]() ![]() |
Цитата Так вот, нету ли стандартного контролируемого потока? Нет. Ни файлов, ни потоков контролируемых нет и не будет. Придется писать закрытие в конце работы с потоком. А работать с ним очень просто:with Interfaces; Не дожидаясь вопроса, сразу объясню, что такое Is_Workaround_Possible. У компиляторов GNAT и ObjectAda есть некоторые проблемы со скоростью выполнения Read и Write в потоках. Так вот, если Stream_Element это и есть байт, и оба тестовых массива одинаково упакованы и одинаково выровнены - то можно значительно ускорить операции чтения/записи, работая напрямую с массивом Stream_Element-ов, наложенным на буфер (строка for SE_Buffer'Address use Buffer'Address этим занимается). Если же нет возможности работать с таким массивом - что ж поделаешь - приходится читать медленно в буфер, это действительно медленно: автор замерял, говорит о 50-кратном замедлении в среднем. Если надо, кстати, есть и BlockWrite для стримов... |
TarasBer |
![]()
Сообщение
#7
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
А почему именно от 1 до 19? Специально, чтобы не делилось на 4?
Дальше, умеет ли компилятор определять значение Is_Workaround_Possible, убрав одну из ветвей if Is_Workaround_Possible then ... else ... end if; > Ни файлов, ни потоков контролируемых нет и не будет. То есть в стандартной библиотеке не будет? Себе я сделал так:
Использование:
Добавлено через 10 мин. Ещё такой момент. Я применил это для своего вектора. Всё зашибись, но возник облом на файле 3МБ (какое-то исключение raised ADA.IO_EXCEPTIONS.DEVICE_ERROR : Invalid argument), причём именно в случае Is_Workaround_Possible. Я принудительно выставил Is_Workaround_Possible в false. И всё нормально прочиталось, при этом программа отработала за 0.21 секунд (я так понял, тут уже не время считывания, а время запуска, инициализаций итд). -------------------- |
IUnknown |
![]()
Сообщение
#8
|
![]() a.k.a. volvo877 ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: ![]() ![]() ![]() |
Цитата возник облом на файле 3МБ (какое-то исключение raised ADA.IO_EXCEPTIONS.DEVICE_ERROR : Invalid argument), причём именно в случае Is_Workaround_Possible. Я принудительно выставил Is_Workaround_Possible в false. И всё нормально прочиталось Очень странно. Воообще-то такое поведение должно было иметь место в обратном случае: если Is_Workaround_Possible равно False, а ты насильно перекинул в True, и из-за несоответствия размеров и(ли) выравнивания процедура Read не смогла прочесть информацию в SE_Buffer. В таком случае Read бросает IO_Exceptions.Device_Error... Получается, что Is_Workaround_Possible вернула True, но буферные переменные не соответствуют друг другу? Попробуй действовать наверняка: прямо внутри BlockRead опиши подтипы: subtype mysz_Test_A is Byte_Buffer(1 .. Buffer'Length);, и проверяй размер/выравнивание этих подтипов. У меня при подключении твоего пакета без сбоя прочитались 3-х, 6-ти и 9-ти Мб файлы. И не только прочитались, а и скопировались в другой стрим (ну да, я добавил еще создание файла в твой код). Хотя, если тебя скорость устраивает... Может, в 2010 уже починили эту багу просто? в GNAT-2009 с этим невозможно было мириться. |
TarasBer |
![]()
Сообщение
#9
|
![]() Злостный любитель ![]() ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: ![]() ![]() ![]() |
Код такой:
Вылетает. Если же Is_Workaround_Possible сделать в лоб false, то всё нормально. ________________________________ Правка: Всё, я заменил Element'Size на Element'Size/8 и всё заработало не только на мелких файлах. Ну и формулу integer(Size(File.F)) * 8 / Element'Size; поменял на integer(Size(File.F)) / (Element'Size / 8); (чтобы на больших файлах не было лишнего переполнения) Всё-таки иногда забываю, что размер возвращается в битах, а не байтах. Сообщение отредактировано: TarasBer - 2.06.2011 16:18 -------------------- |
![]() ![]() |
![]() |
Текстовая версия | 22.06.2025 1:28 |