LINUX.ORG.RU

Быстрое перемещение из stdin в std::string

 , ,


0

1

Есть библиотека snappy, которая сжимает/распаковывает стринги C++. Требуется обработать входной поток этой библиотекой и послать в выходной. Чем быстрее, тем лучше. Размер заранее неизвестен.

На странице http://mattmahoney.net/dc/text.html#5277 нашёл следующие программы:

#define NDEBUG 1  // turn off debugging checks 
#include <snappy.h> 
#include <stdio.h> 
int main() { 
  std::string input, output; 
  int c; 
  while ((c=getchar())!=EOF) input+=char(c);  // read from stdin 
  snappy::Compress(input.c_str(), input.size(), &output);  // MODE = Compress or Uncompress 
  fwrite(output.c_str(), 1, output.size(), stdout);  // write to stdout 
  return 0; 
} 

/*--------------------------------------------------------------*/
 
#define NDEBUG 1  // turn off debugging checks 
#include <snappy.h> 
#include <stdio.h> 
int main() { 
  std::string input, output; 
  int c; 
  while ((c=getchar())!=EOF) input+=char(c);  // read from stdin 
  snappy::Uncompress(input.c_str(), input.size(), &output);  // MODE = Compress or Uncompress 
  fwrite(output.c_str(), 1, output.size(), stdout);  // write to stdout 
  return 0; 
} 

Вопрос: не слишком ли медленно получается читать поток по 1 символу? Нельзя ли это сделать как-то быстрее?

★★★★★

Последнее исправление: question4 (всего исправлений: 1)
Ответ на: комментарий от DELIRIUM

std::istream_iterator

Сразу же наткнулся на информацию, что они как-то обрабатывают пробелы. А что нужно брать, чтобы ничего в потоке не меняло? istreambuf_iterator?

question4 ★★★★★
() автор топика
Ответ на: комментарий от DELIRIUM

Заменить строку с while на

std::string input = (istreambuf_iterator<char>(istream), (istreambuf_iterator<char>()));
?

question4 ★★★★★
() автор топика
Ответ на: комментарий от DELIRIUM

Пробую скомпилировать это:

#include <iostream> 
#include <iterator> 
#include <string> 
int main() { 
  std::string input, output; 
  input = (istreambuf_iterator<char>(istream), (istreambuf_iterator<char>())); 
  return 0; 
} 
Получаю ошибку «нет декларации ‘istreambuf_iterator’ в этой области видимости»

Не хватает какого-то #include ? Что-то надо доустанавливать? Дженту, GCC 4.5.4, dev-libs/STLport не установлен.

question4 ★★★★★
() автор топика
Ответ на: комментарий от fads

std::istreambuf_iterator

Точно. Спасибо.

А что надо ставить вместо «istream» в строке с std::istreambuf_iterator ? Как обозначить входящий поток?

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

#include <iostream> #include <iterator> #include <string> int main() { std::string input = std::string(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>()); return 0; }

anonymous
()
Ответ на: комментарий от anonymous
#include <iostream>.
#include <iterator>.
#include <string>.
int main() {.
  std::string input = std::string(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
  return 0;.
}
anonymous
()
Ответ на: комментарий от anonymous

и совсем правильно:

#include <iostream>
#include <iterator>
#include <string>
int main() {
  std::string input = std::string(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
  return 0;
}

anonymous
()
Ответ на: комментарий от anonymous

Спасибо!

А как организовать вывод? Или лучше оставить fwrite?

И заодно: с какими ключами линковать? -lsnappy для snappy, а достаточно ли -lgccpp для всего остального?

question4 ★★★★★
() автор топика

Не работает с большими файлами. Пишет «Segmentation fault». Есть ли ограничения на размер string?

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

time -v пишет, что максимальная использованная память к моменту падения составляет 268 704 килобайт.

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

Версия из первого поста падает, отъев 16 782 976 К оперативной памяти. С ошибкой «terminate called after throwing an instance of 'std::bad_alloc'».

question4 ★★★★★
() автор топика

не слишком ли медленно получается читать поток по 1 символу?

Померяй. Вообще-то getchar должен быть макросом, который раскрывается в обращение по адресу, а не в чтение.

tailgunner ★★★★★
()

Вопрос: не слишком ли медленно получается читать поток по 1 символу?

Если поток буферизован, то какая разница?

dave ★★★★★
()
Ответ на: комментарий от tailgunner

Померяй.

Как я написал в последних постах, если мерить достаточно долго, программа падает. И скорость перестаёт иметь значение :)

Вообще-то getchar должен быть макросом, который раскрывается в обращение по адресу, а не в чтение.

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

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

Как я написал в последних постах, если мерить достаточно долго, программа падает. И скорость перестаёт иметь значение :)

Ты писал это о программе на Ъ-Си++ - насколько я вижу (по c_str), там нафиг не нужен этот Ъ.

Но я имел в виду, что стринги растут по мере необходимости.

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

А насчет падения - думаю, постоянное переразмещение буфера памяти для строки вызывает преждевременное исчерпание памяти. Если уж ты настаиваешь на использовании string, то преаллоцируй ее и проставь инкремент размера буфера в достаточно большое число (нет, я не знаю, как конкретно это сделать - я давно не пишу на Си++).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Попробуй накапливать и сжимать данные фиксированными порциями.

Придётся.

постоянное переразмещение буфера памяти для строки вызывает преждевременное исчерпание памяти

За счёт фрагментации?

question4 ★★★★★
() автор топика
Ответ на: комментарий от question4

постоянное переразмещение буфера памяти для строки вызывает преждевременное исчерпание памяти

За счёт фрагментации?

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

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.