Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2014.08.03;
Скачать: [xml.tar.bz2];

Вниз

Сохранение StringList большого объема в файл   Найти похожие ветки 

 
_guest_   (2013-09-16 16:33) [0]

Есть StringList с объемом текста в полгига. При попытке сохранить в файл или поток (что в общем то одно и то же) получаю "аут оф мемори", так как SaveTo... пытается сохранить его одним куском. А уже обращение к StringList.Text вызывает эту ошибку.  Построчно в текстовый файл - пожалуйста, только времени не один час. Помогите, пожалуйста, буферизировать сохранение в поток. Для меня проблемой является уже даже получить размер результирующей строки. Рассмотрю любые альтернативные варианты. StringList формируется из кусков в количестве от десятков до сотен тысяч размером около 5 килобайт. Можно бы их сразу по получении сливать на диск, но мне перед этим надо их обработать все вместе, а обработка следующих кусков зависит от результатов обработки предыдущих.


 
DVM ©   (2013-09-16 16:56) [1]

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

http://pastebin.com/70wj5mTS


 
_guest_   (2013-09-16 17:22) [2]

Спасибо, попробую, хотя сомнения и одолевают - больше 14 млн. строк ...


 
brother ©   (2013-09-16 17:41) [3]

я даже боюсь предположить что там...


 
DVM ©   (2013-09-16 17:45) [4]


> _guest_   (16.09.13 17:22) [2]

Это логи что ли какие? А зачем все в память то грузить было? Просто дело в том, что сейчас оно у тебя влезло, а завтра не влезет и без сохранения даже ты получишь Out Of Memory на 32 бит системе. На 64 не получишь, но будет все тормозить сильно.


 
_guest_   (2013-09-16 17:54) [5]


> brother ©   (16.09.13 17:41) [3]

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

> DVM ©   (16.09.13 16:56) [1]

К сожалению процесс не слишком ускорился: обработалось чуть больше
1.5 млн. строк за 10 минут. Еще умножаем на 10, плюс за этим само сохранение из потока в файл..., в общем пока ищу дальше. А кстати, какого типа поток надо давать на вход  TStreamProxy? Может я чего впопыхах не понял у меня memoty.


 
_guest_   (2013-09-16 17:58) [6]


> DVM ©   (16.09.13 17:45) [4]

Печально, сейчас 64 бита, но куда поставят прогу, я не знаю. Буду думать.


 
DVM ©   (2013-09-16 18:02) [7]


> _guest_   (16.09.13 17:54) [5]


> А кстати, какого типа поток надо давать на вход  TStreamProxy?
>  Может я чего впопыхах не понял у меня memoty.

Неееее.  TStreamProxy это лишь обертка. Понятно почему у тебя нет ускорения.

Использовать надо так:
BuffStream := TBufferedStream.Create(TFileStream.Create(...), true);

Далее пишешь в BuffStream


 
Юрий Зотов ©   (2013-09-16 19:16) [8]

> _guest_   (16.09.13 17:54) [5]
>  у меня memoty.

То есть, и стринглист в памяти, и поток тоже в памяти. То есть, мы копируем здоровенную инфу из одного места памяти в другое место той же памяти. И удивляемся, что получили "аут оф мемори".


 
Sha ©   (2013-09-16 23:42) [9]

> Просто со списком работать немного удобнее

а что именно надо сделать с данными?


 
_guest_   (2013-09-17 09:17) [10]


> DVM ©   (16.09.13 18:02) [7]

Да-да. Я в первую очередь FileStream и попробовал, но прироста скорости практически не получил. Очевидно, это обусловлено тем, что строк много, но они короткие типа "имя":"значение". Поэтому при построчной перезаписи преимуществ буферизации почти и нет.

> Юрий Зотов ©   (16.09.13 19:16) [8]
То есть, и стринглист в памяти, и поток тоже в памяти. То есть, мы копируем здоровенную инфу из одного места памяти в другое место той же памяти. И удивляемся, что получили "аут оф мемори".

Нет. В результате этого действия ошибка не возникает, поэтому и не удивляюсь. И, между нами, даже если я пару-тройку раз растиражирую поток такого объема она не возникает, тормозится при свопинге - это да. Ошибки нет при работе со списком такого объема, она  возникает при обращении к StringList.Text см.[1]. И то, что он нормально обрабатывается меня и подвело. Идея, что называется в лоб, была простой: получить строку, выдергивать из нее куски, а уж куда их писать в поток файловый или нет, непосредственно в файл ли - это не принципиально. Куски были бы заметно больше, чем одна строка и сохранение не заняло бы настолько много времени, ведь перезапись файла такого объема никого не шокирует. Я уткнулся в то, что не смог получить доступ к этой строке.

> Sha ©   (16.09.13 23:42) [9]
> а что именно надо сделать с данными?

Небольшой анализ, а потом все вывалить в mid он же csv он же просто текстовый файл со значениями через какой-нибудь разделитель. Потом аналитики его заберут в Excel или Access или еще куда-то, но требуют именно текстовый файл в виде плоской таблицы.

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


 
_guest_   (2013-09-17 09:17) [11]


> DVM ©   (16.09.13 18:02) [7]

Да-да. Я в первую очередь FileStream и попробовал, но прироста скорости практически не получил. Очевидно, это обусловлено тем, что строк много, но они короткие типа "имя":"значение". Поэтому при построчной перезаписи преимуществ буферизации почти и нет.

> Юрий Зотов ©   (16.09.13 19:16) [8]
То есть, и стринглист в памяти, и поток тоже в памяти. То есть, мы копируем здоровенную инфу из одного места памяти в другое место той же памяти. И удивляемся, что получили "аут оф мемори".

Нет. В результате этого действия ошибка не возникает, поэтому и не удивляюсь. И, между нами, даже если я пару-тройку раз растиражирую поток такого объема она не возникает, тормозится при свопинге - это да. Ошибки нет при работе со списком такого объема, она  возникает при обращении к StringList.Text см.[1]. И то, что он нормально обрабатывается меня и подвело. Идея, что называется в лоб, была простой: получить строку, выдергивать из нее куски, а уж куда их писать в поток файловый или нет, непосредственно в файл ли - это не принципиально. Куски были бы заметно больше, чем одна строка и сохранение не заняло бы настолько много времени, ведь перезапись файла такого объема никого не шокирует. Я уткнулся в то, что не смог получить доступ к этой строке.

> Sha ©   (16.09.13 23:42) [9]
> а что именно надо сделать с данными?

Небольшой анализ, а потом все вывалить в mid он же csv он же просто текстовый файл со значениями через какой-нибудь разделитель. Потом аналитики его заберут в Excel или Access или еще куда-то, но требуют именно текстовый файл в виде плоской таблицы.

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


 
_guest_   (2013-09-17 09:19) [12]

Извините, кнопку "Добавить" нажал один раз. Или мышку менять или указательный палец.


 
Sha ©   (2013-09-17 09:48) [13]

> Небольшой анализ, а потом все вывалить в mid он же csv он же просто
> текстовый файл со значениями через какой-нибудь разделитель.

Тогда и свойство Text не нужно, и, вероятно, сам StringList.


 
_guest_   (2013-09-17 09:57) [14]


> Sha ©   (17.09.13 09:48) [13]

А где же держать данные, если они в виде списка строк и приходят?


 
brother ©   (2013-09-17 10:00) [15]

array of string?


 
Sha ©   (2013-09-17 10:05) [16]

> А где же держать данные

до сих пор не ясно, зачем их держать или зачем держать их все


 
_guest_   (2013-09-17 10:06) [17]


> brother ©   (17.09.13 10:00) [15]

Не думал о массиве. А его можно быстро сохранить, т.е. можно ли получить кусок массива как буфер? Если нет, то в чем собственно выигрыш?


 
brother ©   (2013-09-17 10:06) [18]

можно многое, но [16]?


 
Inovet ©   (2013-09-17 10:06) [19]

> [15] brother ©   (17.09.13 10:00)
> array of string?

А в чём принципиальная разница? Я понимаю - в БД какую загрузить и её средствами обрабатывать, может быть.


 
DVM ©   (2013-09-17 10:22) [20]


> _guest_   (17.09.13 09:17) [10]


> Да-да. Я в первую очередь FileStream и попробовал, но прироста
> скорости практически не получил. Очевидно, это обусловлено
> тем, что строк много, но они короткие типа "имя":"значение".
>  Поэтому при построчной перезаписи преимуществ буферизации
> почти и нет.

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


 
_guest_   (2013-09-17 10:23) [21]


> Sha ©   (17.09.13 10:05) [16]
> до сих пор не ясно, зачем их держать или зачем держать их все

Да, в общем то, не за чем. От инертности моего мышления. ТЗ нету, состава приходящих данных нету, в смысле "ты сам посмотри, что там приходит", а оно приходит далеко не однородное. Я уже решил разбивать на кварталы [10]. С другой стороны, не каждый же участок сразу в свой файл писать, их же сотни тысяч - даже на харде так хранить не выгодно.


 
Sha ©   (2013-09-17 10:24) [22]

_guest_   (17.09.13 10:23) [21]

Очевидно, что если надо посчитать сумму большого объема данных,
то нет смысла сначала грузить их стринглист, а потом считать.

Похожим образом можно поступить и для поквартальных сумм.

Довольно редко попадаются так зависимые данные,
чтобы была абсолютно необходима их полная загрузка в память.


 
_guest_   (2013-09-17 10:37) [23]


> Sha ©   (17.09.13 10:24) [22]

Да я согласен, конечно. Только мне не посчитать, а упорядочить эти данные надо, а они, как я уже говорил, неоднородные. Где-то есть такое значение, где-то нет, но есть другое, которого нет еще где-либо - нет жестко заданной структуры. Что при преобразовании в общую таблицу доставляет определенные неудобства. Собственно, я уже придумал как это сделать, работаю над реализацией.
Ветку можно закрывать, направление работы понятно. Получил даже больше, чем хотел :) общение с умными людьми не проходит бесследно. Всем большое спасибо.


 
DVM ©   (2013-09-17 10:40) [24]


> _guest_   (17.09.13 10:23) [21]

Если ты говоришь, что это JSON, и он грузится долго, то имеет смысл обрабатывать его на лету по мере загрузки. Для этого нужно будет разработать потоковый JSON парсер по аналогии с SAX парсером для XML. Я бы так и поступил. Получили кусок данных отдали парсеру - он выплюнул нужные нам данные, потом следующий кусок и так далее. Это если по уму делать.


 
_guest_   (2013-09-17 10:54) [25]


> DVM ©   (17.09.13 10:40) [24]

Какой-то json парсер есть прямо в делфи по крайней мере в 2010. И в финале, так и будет, как Вы описали. Со дня на день пересяду с 2007 на xe. Проблема не в этом. Вот прямо сейчас мне без разницы распарсенные у меня данные или нет (уберутся всякие скобочки и вместо двоеточия будет стоять равно), если они разные по составу, а максимально возможного состава я не узнаю, пока не получу их все.


 
DVM ©   (2013-09-17 11:14) [26]


> _guest_   (17.09.13 10:54) [25]


> Какой-то json парсер есть прямо в делфи по крайней мере
> в 2010.

Я не видел JSON парсеров которые бы работали так как я описал. Да и с XML то не густо, писал сам для ограниченного применения такой.


 
_guest_   (2013-09-17 11:25) [27]


> DVM ©   (17.09.13 11:14) [26]

Я не силен в этом, и мне не очень понятно зачем нужен "потоковый" парсер. Если данные приходят кусками, а так оно и есть, то: пришли данные, распарсили их обычным, не потоковым парсером, полученные данные сохранили. Я не знаю что такое SAX, правда. Могу быстренько глянуть в инете для уменьшения своей безграмотности, но для xml куча обычных парсеров. Очевидно, я не уловил того, что Вы хотели донести в [24], каких то особенностей работы. Или имеется ввиду обработка в другом потоке для уменьшения времени работы? Если можно, то чуть подробнее.


 
DVM ©   (2013-09-17 11:44) [28]


> _guest_   (17.09.13 11:25) [27]


> Я не силен в этом, и мне не очень понятно зачем нужен "потоковый"
> парсер. Если данные приходят кусками, а так оно и есть,
> то: пришли данные, распарсили их обычным, не потоковым парсером,
>  полученные данные сохранили.

Потоковый парсер или SAX парсит данные по мере поступления,  в отличие от DOM парсера который строит некоторую структуру (дерево) в памяти из элементов. Первый не потребляет памяти вообще и работает быстро, т.к. просто из потока данных вычленяет элементы и отдает их в событиях. Что делать с найденными элементами решать тому кто парсер использует, либо отбрасывать, либо сохранять где то.  Преимущество такого парсера - он может обработать сравнительно быстро любой объем данных при незначительном потреблении памяти.

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


 
DVM ©   (2013-09-17 11:49) [29]


> _guest_   (17.09.13 11:25) [27]

Вот пример из википедии:


{
  "firstName": "Иван",
  "lastName": "Иванов",
  "address": {
      "streetAddress": "Московское ш., 101, кв.101",
      "city": "Ленинград",
      "postalCode": 101101
  },
  "phoneNumbers": [
      "812 123-1234",
      "916 123-4567"
  ]
}

<person>
 <firstName>Иван</firstName>
 <lastName>Иванов</lastName>
 <address>
   <streetAddress>Московское ш., 101, кв.101</streetAddress>
   <city>Ленинград</city>
   <postalCode>101101</postalCode>
 </address>
 <phoneNumbers>
   <phoneNumber>812 123-1234</phoneNumber>
   <phoneNumber>916 123-4567</phoneNumber>
 </phoneNumbers>
</person>


DOM парсеры не распарсят нам данные файлы, пока в первом случае мы не получим последнюю скобочку }, а во втором тег < /person>


 
_guest_   (2013-09-17 11:59) [30]


> DVM ©   (17.09.13 11:44) [28]

Данные приходят небольшими законченными кусками. Их можно считать элементами какого-то общего документа, а можно и не считать. Если по аналогии с xml, то меня вполне устроит модель dom, т.к. приходит не какой-то большой документ, а очень много маленьких и данные из них нужны абсолютно все. Я потому и не заострял на этом моменте внимания, что сама структура данных простая: имя-значение, и если я выкину все скобки а двоеточие заменю на знак равенства, то получу список типа name=value, вот и весь парсинг. Логически что там приходит, мне все равно, раскидал по столбцам и сохранил.


 
DVM ©   (2013-09-17 12:02) [31]


> _guest_   (17.09.13 11:59) [30]


> т.к. приходит не какой-то большой документ, а очень много
> маленьких

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


 
_guest_   (2013-09-17 12:05) [32]


> DVM ©   (17.09.13 12:02) [31]

Нет никаких границ и потока, данные приходят в виде StringList"ов.


 
_guest_   (2013-09-17 12:08) [33]

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


 
DVM ©   (2013-09-17 12:13) [34]


> Нет никаких границ и потока, данные приходят в виде StringList"ов.

Откуда они приходят в таком виде?


 
_guest_   (2013-09-17 12:14) [35]


> DVM ©   (17.09.13 12:13) [34]

С сайта


 
DVM ©   (2013-09-17 12:16) [36]


> _guest_   (17.09.13 12:14) [35]

Че то я не понимаю, как с сайта может прийти дельфийский объект TStringList?
Приходит именно поток данных TStream или буфер (массив данных) из которого потом кто-то перекладывает данные за каким то лешим в TStringList, хотя парсить можно прям оригинальный буфер без лишних телодвижений.


 
stas ©   (2013-09-17 12:17) [37]

_guest_   (17.09.13 12:08) [33]
С такими объемами Вам придется освоить СУБД.


 
_guest_   (2013-09-17 12:30) [38]


> DVM ©   (17.09.13 12:16) [36]

Потому что я использую делфийский компонент, любой на выбор: IdHTTP (indy), IEHTTP, HTTPSend (synapse). Похоже я сейчас узнаю что-то новое для себя. В общем то я с ними вожусь всего 3-й день, но по-моему каждый из них возвращает список строк в том или ином виде.

> stas ©   (17.09.13 12:17) [37]

Зачем? Чтобы текст в одном виде сохранить как текст в другом. Вся обработка исключительно строчная, ничего не надо искать, ничего выбирать или вычислять. Из-за объемов? Так пока что результирующие файлы блокнотом++ спокойно открывались, ну вот до последнего раза. Так мне смотреть на него и не надо.


 
_guest_   (2013-09-17 12:36) [39]

> DVM ©   (17.09.13 12:16) [36]
так чтобы из меня не тянуть клещами: с сайта идет не файл, а сама страничка. Так что если я чего недопонимаю, то Вы меня поправьте.


 
DVM ©   (2013-09-17 12:42) [40]


> _guest_   (17.09.13 12:30) [38]


> Потому что я использую делфийский компонент, любой на выбор:
>  IdHTTP (indy), IEHTTP, HTTPSend (synapse). Похоже я сейчас
> узнаю что-то новое для себя. В общем то я с ними вожусь
> всего 3-й день, но по-моему каждый из них возвращает список
> строк в том или ином виде.

Ну понятно. А приходят эти данные порциями ровно по одному JSON документу или одним большим куском из нескольких склеенных?

Кстати, имей в виду, что не факт что твои JSON данные всегда будут поделены на строки. Т.е полагаться на это не стоит. Там вообще может не быть ни одного перевода строки (в JSON или XML) или где то его забудут сделать. Плюс делается явно лишняя работа по перекладыванию данных из одного места в другое. Не спортивно это на больших объемах.
Принимай данные в какой нить наследник TStream, парси его, потом в него принимай очередную порцию и опять парси и т.д.



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2014.08.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.003 c
3-1299221012
Junior
2011-03-04 09:43
2014.08.03
Поиск текста в строках SQL сервера


2-1379178090
Вова
2013-09-14 21:01
2014.08.03
Оптимизация кода 2. и еще не могу найти ошибку )


2-1379334790
_guest_
2013-09-16 16:33
2014.08.03
Сохранение StringList большого объема в файл


3-1300095610
Бинар
2011-03-14 12:40
2014.08.03
Прерывание запроса


15-1389417411
Viktor Makarov
2014-01-11 09:16
2014.08.03
Помогите пожалуйста написать код для этой задачи)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский