Ada_Ru форум

Обсуждение языка Ада

Скорость чтения из stdin.

Оставить новое сообщение

Сообщения

Alexey Veselovsky
Скорость чтения из stdin.
2008-05-19 00:00:18

Читаем из stdin построково:

 

======== Ada =========

 

with Ada.Text_IO; use Ada.Text_IO;

 

procedure StdIn_Reader is

 

Seq : String(1 .. 60);

J : Natural;

begin

while not End_Of_File loop

Get_Line (Seq, J);

end loop;

end StdIn_Reader;

 

=====================

 

======== C++ =========

#include <iostream>

 

using namespace std;

 

int main()

{

cin.sync_with_stdio(false);

char line[61];

 

while (!cin.eof())

{

cin.getline(line,61);

}

 

return 0;

}

====================

 

На stdin подаем через перенаправление ввода (т.е. из файла,

называющимся в данном конкретном случае, stdin (я его так обозвал)). В файл размером примерно 250 Мб, длина каждой строки примерно 60

символов:

 

$ time ./ada < stdin

 

real 0m31.856s

user 0m10.457s

sys 0m0.684s

 

$ time ./cpp < stdin

 

real 0m5.911s

user 0m1.308s

sys 0m0.568s

 

Грубо говоря, получаем что ада читает этот файл за 10 секунд, а С++ за 1,5 секунды. Разница примерно в 7 раз. Почему? Как исправить?

 

PS. компиляция производилась с опциями по умолчанию. Т.е.:

gnat make StdIn_Reader.adb

 

и

 

g++ stdin_reader.cpp

On Mon, 19 May 2008 04:00:18 +0400, you wrote:

 

Грубо говоря, получаем что ада читает этот файл за 10 секунд, а С++ за 1,5 секунды. Разница примерно в 7 раз. Почему? Как исправить?

 

1. Text_IO предназначен для форматного ввода-вывода и имеет богатые, но увы, мало кому нужные возможности, которые, однако не допускают эффективной реализации. Для чтения потоков используйте Ada.Streams.

 

(Кстати, и конец строки, Text_IO во многих случаях может определять не так, как Вам было бы нужно.)

 

2. Если уж Text_IO, то не надо использовать End_OF_File, он работает (в ОС типа Windows и Unix, не имеющих файлов записей) через просмотр вперед, и практически в любой ситуации вреден. Конец файла должен ловится по исключению End_Error. Это и программно чище, и быстрее.

 

--

Regards,

Dmitry A. Kazakov

http://www.dmitry-kazakov.de

Это уже новая тема. Как помнится, в GNAT S'Read для String (и массивов вообще) не оптимизирован, он вызывает Read на каждый отдельный Character.

 

Вы абсолютно правы. Если мне не изменяет память, мы это починили пару месяцев назад, так что надеюсь GPL 2008 будет пошустрее на этом

примере.

 

ВФ

1. Text_IO предназначен для форматного ввода-вывода и имеет богатые, но увы, мало кому нужные возможности, которые, однако не допускают эффективной реализации. Для чтения потоков используйте Ada.Streams.

 

(Кстати, и конец строки, Text_IO во многих случаях может определять не так, как Вам было бы нужно.)

 

2. Если уж Text_IO, то не надо использовать End_OF_File, он работает (в ОС типа Windows и Unix, не имеющих файлов записей) через просмотр вперед, и практически в любой ситуации вреден. Конец файла должен ловится по исключению End_Error. Это и программно чище, и быстрее.

 

Переписал:

 

==========================

with Ada.Text_IO; use Ada.Text_IO;

with Ada.Streams; use Ada.Streams;

with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;

with Ada.Text_IO.Text_Streams; use Ada.Text_IO.Text_Streams;

 

procedure StdIn_Reader is

subtype MyStr is String(1 .. 60);

Seq : MyStr;

S : access Root_Stream_Type;

begin

S := Stream(Standard_Input);

loop

MyStr'Read(S,Seq);

end loop;

end StdIn_Reader;

==========================

 

Запустил:

$ time ./ada < stdin

 

raised ADA.IO_EXCEPTIONS.END_ERROR : s-stratt.adb:184

 

real 1m53.850s

user 0m58.176s

sys 0m1.104s

 

По моему, быстрее не стало ;-)

On Mon, 19 May 2008 22:52:54 +0400, you wrote:

 

Переписал:

 

==========================

with Ada.Text_IO; use Ada.Text_IO;

with Ada.Streams; use Ada.Streams;

with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;

with Ada.Text_IO.Text_Streams; use Ada.Text_IO.Text_Streams;

 

procedure StdIn_Reader is

subtype MyStr is String(1 .. 60);

Seq : MyStr;

S : access Root_Stream_Type;

begin

S := Stream(Standard_Input);

loop

MyStr'Read(S,Seq);

 

Это уже новая тема. Как помнится, в GNAT S'Read для String (и массивов вообще) не оптимизирован, он вызывает Read на каждый отдельный Character. Попробуйте читать Stream_Element_Array непосредственно из потока. Или переопределите MyStr'Read, чтобы он читал весь блок за один раз.

 

--

Regards,

Dmitry A. Kazakov

http://www.dmitry-kazakov.de

Новое сообщение:
Страницы: 1

Чтобы оставить новое сообщение необходимо Зарегистрироваться и Войти