Прожорливость памяти ОЗУ MT5, проблемы с чтением/записью больших файлов

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Aleksey Vyazmikin
15934
Aleksey Vyazmikin  

Такой  у меня вопрос, есть файл CSV размером 78 мегабайт, хочу обсчитать его, так как эксель очень сильно тупит из-за размеров, думал воспользоваться MT5.

Сделал скрипт, который пока только считывает данные в массивы для каждой строки (57 массивов на чтение из файла и 57 на запись в новый файл), размер массива равен числу строк в файле CSV. Так вот, скрипт съел 8 гигабайт памяти, в то время как эксель менее чем 1,5 гигабайта, и операцию чтение/запись MT5 выполнял аж целых 9 минут!

Roffild
1319
Roffild  

Хотя бы код на MQL выложили... Построчно нужно считать.

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

Aleksey Vyazmikin
15934
Aleksey Vyazmikin  
Roffild:

Хотя бы код на MQL выложили... Построчно нужно считать.

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

У меня там пока расчетов нет, просто запись в массив столько времени отъедает по непонятным причинам (на самом деле именно чтение из файла съедает время, про память пока не ясно).

Не исключаю, что проблемы с кодом. Я использую класс для чтения, подправленный(вроде как правил) с MT4.

Код основной почти 700 строк - там ничего интересного - объявляем массив, обнуляем массив, меняем размер массива, записываем данные в массив из файла, перезаписываем данные из массива в массив, записываем данные из массива в файл.

Вот класс, за который были уплачены деньги:

//+------------------------------------------------------------------+
//|                                                    CSVReader.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property strict
//+------------------------------------------------------------------+
//| CSVReader                                                        |
//+------------------------------------------------------------------+
class CSVReader
  {
private:
   int               m_flags;
   string            m_filename;
   char              m_delimiter;
   bool              m_data_loaded;
   //---
   string            m_column_names[];
   string            m_cells[];
   //---
   int               m_total_rows;
   int               m_total_columns;
   //---
   bool              AddData(string data_str,bool header);
   bool              CheckIndexes(int row,int column);
   string            ReplaceCommaByDot(string str);
public:
                     CSVReader(string path);
   //---
   void              SetDelimiter(char delimiter);
   void              SetCommon(bool common);
   //---
   bool              Load(int start_line);
   //---
   string            GetStringValue(int row,int column);
   int               GetIntValue(int row,int column);
   double            GetDoubleValue(int row,int column);
   bool              GetBoolValue(int row,int column);
   //---
   int               TotalRows() {return(m_total_rows);}
   int               TotalColumns() {return(m_total_columns);}
//---
   string            FileName() {return(m_filename);}
   //---
   string            ColumnName(int index);
  };
//+------------------------------------------------------------------+
//| CSVReader class constructor                                      |
//+------------------------------------------------------------------+
void CSVReader::CSVReader(string filename)
  {
   m_filename=filename;
   m_flags=FILE_SHARE_READ|FILE_TXT|FILE_ANSI;
   m_delimiter=';';
   m_data_loaded=false;
   ArrayResize(m_column_names,0);
   ArrayResize(m_cells,0);
   m_total_rows=0;
   m_total_columns=0;
  }
//+------------------------------------------------------------------+
//| SetDelimiter                                                     |
//+------------------------------------------------------------------+
void CSVReader::SetDelimiter(char delimiter)
  {
   m_delimiter=delimiter;
  }
//+------------------------------------------------------------------+
//| SetCommon                                                        |
//+------------------------------------------------------------------+
void CSVReader::SetCommon(bool common)
  {
   if(common) m_flags|=FILE_COMMON;
   else m_flags&=~FILE_COMMON;
  }
//+------------------------------------------------------------------+
//| ColumnName                                                       |
//+------------------------------------------------------------------+
string CSVReader::ColumnName(int index)
  {
   if(m_total_columns==0) return("");
   if((index>=0) && (index<m_total_columns)) return(m_column_names[index]);
   return("error");
  }
//+------------------------------------------------------------------+
//| AddData                                                          |
//+------------------------------------------------------------------+
bool CSVReader::AddData(string data_str,bool header)
  {
   string str=data_str;

  int DlinaStroki=StringLen(str);
  int ObrezLeft=StringTrimLeft(str);
  int ObrezRifgr=StringTrimRight(str);
   if(ObrezLeft>0)
   {
   str=StringSubstr( 
        str,              // строка 
        ObrezLeft,        // с какой позиции начать 
        DlinaStroki-ObrezLeft         // длина извлекаемой строки 
   );
   ObrezRifgr=StringTrimRight(str);
   }
   if(ObrezRifgr>0)
   {
   str=StringSubstr( 
        str,              // строка 
        0,        // с какой позиции начать 
        DlinaStroki-ObrezRifgr         // длина извлекаемой строки 
   );
   }
   
   
//   str=StringTrimLeft(str);
//   str=StringTrimRight(str);
//---
   if(StringLen(str)==0) return(false);
   string lines[];
   StringSplit(str,m_delimiter,lines);
//--- check ending with delimiter
   if(StringLen(str)>0)
     {
      string str0=StringSubstr(str,StringLen(str)-1,1);
      //--- ending with delimiter case, decrease lines[]
      if(str0==CharToString(m_delimiter))
        {
         ArrayResize(lines,ArraySize(lines)-1);
        }
     }
//--- parse header
   if(header==true)
     {
      m_total_columns=ArraySize(lines);
      if(m_total_columns==0) return(false);
      ArrayResize(m_column_names,m_total_columns);
      //---
      for(int i=0; i<m_total_columns; i++)
        {
         m_column_names[i]=lines[i];
        }
     }
   else
//--- parse data
     {
      int columns_count=ArraySize(lines);
      //--- add data
      if(columns_count==m_total_columns)
        {
         m_total_rows++;
         ArrayResize(m_cells,m_total_rows*m_total_columns,10000);
         //---
         for(int i=0; i<columns_count; i++)
           {
            int index=m_total_columns*(m_total_rows-1)+i;
            if((index>=0) && (index<ArraySize(m_cells)))
              {
               m_cells[index]=ReplaceCommaByDot(lines[i]);
              }
            else return(false);
           }
        }
     }
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| Load                                                             |
//+------------------------------------------------------------------+
bool CSVReader::Load(int start_line)
  {
   int filehandle=FileOpen(m_filename,FILE_CSV|FILE_READ|FILE_ANSI|FILE_SHARE_READ,'\n');
   if(filehandle==INVALID_HANDLE)
     {
      Alert("Error in open of file ",m_filename,", error",GetLastError());
      return(false);
     }
//---
   int line_index=0;
   while(!FileIsEnding(filehandle))
     {
      string str=FileReadString(filehandle);
      //--- skip 0th row
      if(line_index>=start_line)
         if(str!="")
           {
            if(line_index==1) AddData(str,true);
            else AddData(str,false);
           }
      line_index++;
     }
//---
   FileClose(filehandle);
   return(true);
  }
//+------------------------------------------------------------------+
//| ReplaceCommaByDot                                                |
//+------------------------------------------------------------------+
string CSVReader::ReplaceCommaByDot(string str)
  {
   string str0="";
   for(int i=0; i<StringLen(str); i++)
     {
      ushort chr=StringGetCharacter(str,i);
      if(chr==',') chr='.';
      str0+=CharToString((uchar)chr);
     }
   return(str0);
  }
//+------------------------------------------------------------------+
//| CheckIndexes                                                     |
//+------------------------------------------------------------------+
bool CSVReader::CheckIndexes(int row,int column)
  {
   if((m_total_columns==0) || (m_total_rows==0)) return(false);
   if((row<0) || (row>=m_total_rows)) return(false);
   if((column<0) || (column>=m_total_columns)) return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| GetStringValue                                                   |
//+------------------------------------------------------------------+
string CSVReader::GetStringValue(int row,int column)
  {
   if(CheckIndexes(row,column)==false) return("");
//---
   int index=m_total_columns*row+column;
   if((index>=0) && (index<ArraySize(m_cells))) return(m_cells[index]);
   return("error");
  }
//+------------------------------------------------------------------+
//| GetIntValue                                                      |
//+------------------------------------------------------------------+
int CSVReader::GetIntValue(int row,int column)
  {
   if(CheckIndexes(row,column)==false) return(0);
//---
   int index=m_total_columns*row+column;
   if((index>=0) && (index<ArraySize(m_cells)))
     {
      return((int)StringToInteger(m_cells[index]));
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| GetDoubleValue                                                   |
//+------------------------------------------------------------------+
double CSVReader::GetDoubleValue(int row,int column)
  {
   if(CheckIndexes(row,column)==false) return(0.0);
//---
   int index=m_total_columns*row+column;
   if((index>=0) && (index<ArraySize(m_cells)))
     {
      return(StringToDouble(m_cells[index]));
     }
   return(0.0);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| GetBoolValue                                                   |
//+------------------------------------------------------------------+
bool CSVReader::GetBoolValue(int row,int column)
  {
   if(CheckIndexes(row,column)==false) return(0.0);
//---
   int index=m_total_columns*row+column;
   if((index>=0) && (index<ArraySize(m_cells)))
     {
      if (StringToInteger(m_cells[index])==1) return (true);
      else return (false);
     }
   return(0.0);
  }
//+------------------------------------------------------------------+

Скрипт (запись убрал, так-как проблема именно с чтением) урезанный вариант

#property version   "1.00"
#property indicator_chart_window
#property strict
//---
#property script_show_inputs
#include <CSVReader.mqh>                              //Класс по чтению информации из файла
//#include <CsvWriter_2.mqh>                            //Класс по записи информации в файл

input string  FileLoadSetup="PredFind\\Test\\Pred_Ocenka_Read.csv";
input int Prediktor=1; //Целевая
input double Support=0.01;//Поддержка
input double Relevantnost=70.0;//Достоверность


int arrRead_01[];
int arrRead_02[];
int arrRead_03[];

//--Информационные
string arrRead_DateTime[];

int arrWrite_01[];
int arrWrite_02[];
int arrWrite_03[];

//--Информационные
string arrWrite_DateTime[];

CsvWriter Printer;
int Statistic;

int StrokTotal=0;
int arrSize=0;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {

   CSVReader FileLoads(FileLoadSetup);
   FileLoads.SetDelimiter(';');
   FileLoads.SetCommon(true);
   int StrokaSetup=0;
   if(FileLoads.Load(1))
     {
      StrokTotal=FileLoads.TotalRows();
      arrSize=StrokTotal;
      PrintFormat("File%s loaded. Total rows=%d,Total columns=%d",FileLoads.FileName(),FileLoads.TotalRows(),FileLoads.TotalColumns());


      ArrayFree(arrRead_01);
      ArrayFree(arrRead_02);
      ArrayFree(arrRead_03);
      ArrayFree(arrRead_DateTime);
    
      ArrayFree(arrWrite_01);
      ArrayFree(arrWrite_02);
      ArrayFree(arrWrite_03);
      ArrayFree(arrWrite_DateTime);
      
      
      
      //--Зададим размер массивам
     
      ArrayResize(arrRead_01,arrSize);
      ArrayResize(arrRead_02,arrSize);
      ArrayResize(arrRead_03,arrSize);
      ArrayResize(arrRead_DateTime,arrSize);
 
      ArrayResize(arrWrite_01,arrSize);
      ArrayResize(arrWrite_02,arrSize);
      ArrayResize(arrWrite_03,arrSize);
      ArrayResize(arrWrite_DateTime,arrSize);

      for(int i=1;i<StrokTotal; i++)
        {
         //Print(FileLoads.GetIntValue(i,20));
        }

      for(int i=1;i<StrokTotal; i++)
        {
         arrRead_DateTime[i]=FileLoads.GetStringValue(i,0);        
         arrRead_01[i]=FileLoads.GetIntValue(i,1);
         arrRead_02[i]=FileLoads.GetIntValue(i,2);
         arrRead_03[i]=FileLoads.GetIntValue(i,3);
        }

     }

   for(int i=1;i<arrSize; i++)
     {
         arrWrite_DateTime[i]=arrRead_DateTime[i];
         arrWrite_01[i]=arrRead_01[i];
         arrWrite_02[i]=arrRead_02[i];
         arrWrite_03[i]=arrRead_03[i];
     }

  }
//+------------------------------------------------------------------+
Файлы:
Aleksey Vyazmikin
15934
Aleksey Vyazmikin  

Есть и ещё одна проблема - не могу понять, как писать больше 48 столбцов. Так же использую класс. Может кто поможет поправить класс, с целью расширения числа столбцов для записи?

Вот код, который отсутствует в прошлом посте, для записи в файл.

   string TimeF=TimeToString(TimeLocal(),TIME_DATE|TIME_MINUTES);
   StringSetCharacter(TimeF,13,'_');
   Statistic=Printer.FileCreate(Symbol()+"_"+"Pred_Ocenka_Write","PredFind\\Test",false,false,EvryTick); //Создание файла для записи     
   Printer.Write(
                 "arr_Buy_Sell",
                 "arr_Vektor_Week",
                 "arr_Vektor_Day",
                 "arr_Vektor_Don",
                 "arr_DonProc",
                 "arr_iDelta_H_1_H1",
                 "arr_iDelta_H_1_H3",
                 "arr_iDelta_H_1_H4",
                 "arr_iDelta_H_1_H6",
                 "arr_iDelta_H_1_H12",
                 "arr_iDelta_H_1_D1",
                 "arr_iDelta_H_1_W1",
                 "arr_iDelta_H_1_MN1",
                 "arr_RSI_Open_M1",
                 "arr_RSI_Open_H1",
                 "arr_BB_Center",
                 "arr_BB_Up",
                 "arr_BB_Down",
                 "arr_TimeH",
                 "arr_Den_Nedeli",
                 "arr_iDelta_Max_H1",
                 "arr_iDelta_Min_H1",
                 "arr_iDelta_Max_D1",
                 "arr_iDelta_Min_D1",
                 "arr_Buy Расчетная",
                 "arr_Buy Номер правила",
                 "arr_Buy Поддержка",
                 "arr_Buy Достоверность"
                 );

   for(int i=1;i<arrSize; i++)
     {
      Printer.Write(
                     arrRead_DateTime[i],
                    IntegerToString(arrWrite_01[i]),
                    IntegerToString(arrWrite_02[i]),
                    IntegerToString(arrWrite_03[i]),
                    IntegerToString(arrWrite_04[i]),
                    IntegerToString(arrWrite_05[i]),
                    IntegerToString(arrWrite_06[i]),
                    IntegerToString(arrWrite_07[i]),
                    IntegerToString(arrWrite_08[i]),
                    IntegerToString(arrWrite_09[i]),
                    IntegerToString(arrWrite_10[i]),
                    IntegerToString(arrWrite_11[i]),
                    IntegerToString(arrWrite_12[i]),
                    IntegerToString(arrWrite_13[i]),
                    IntegerToString(arrWrite_14[i]),
                    IntegerToString(arrWrite_15[i]),
                    IntegerToString(arrWrite_16[i]),
                    IntegerToString(arrWrite_17[i]),
                    IntegerToString(arrWrite_18[i]),
                    IntegerToString(arrWrite_19[i]),
                    IntegerToString(arrWrite_20[i]),
                    IntegerToString(arrWrite_21[i]),
                    IntegerToString(arrWrite_22[i]),
                    IntegerToString(arrWrite_23[i]),
                    IntegerToString(arrWrite_24[i]),
                    IntegerToString(arrWrite_25[i]),
                    IntegerToString(arrWrite_26[i]),
                    IntegerToString(arrWrite_27[i]),
                    IntegerToString(arrWrite_28[i]),
                    IntegerToString(arrWrite_29[i]),
                    IntegerToString(arrWrite_30[i]),                                                                                
                    IntegerToString(arrWrite_40[i]),
                    IntegerToString(arrWrite_41[i]),
                    IntegerToString(arrWrite_42[i]),
                    IntegerToString(arrWrite_43[i]),
                    IntegerToString(arrWrite_44[i]),
                    IntegerToString(arrWrite_45[i]),
                    IntegerToString(arrWrite_46[i]),
                    IntegerToString(arrWrite_47[i]),
                    IntegerToString(arrWrite_48[i]),
                    IntegerToString(arrWrite_49[i]),
                    IntegerToString(arrWrite_50[i]),
                    IntegerToString(arrWrite_51[i]),
                    IntegerToString(arrWrite_52[i]),
                    IntegerToString(arrWrite_53[i]),
                    IntegerToString(arrWrite_54[i]),
                    IntegerToString(arrWrite_55[i]),
                    IntegerToString(arrWrite_56[i])
                    );
     }

А вот класс для записи данных в файл так же оплаченный

//+------------------------------------------------------------------+
//|                                                    CsvWriter.mqh |
//|                                                Виктор Крупинский |
//|                                               Krupinskiy@Mail.Ru |
//+------------------------------------------------------------------+
#property copyright "Виктор Крупинский"
#property link      "Krupinskiy@Mail.Ru"
#property version   "2.00"
#property strict

enum periodicity { EvryTick=-1,NewBar=PERIOD_CURRENT,EvryHour=PERIOD_H1,
                     EvryDay=PERIOD_D1,EvryWeek=PERIOD_W1,EvryMonth=PERIOD_MN1 };
class CsvWriter {
private:
   int handle;
   periodicity writeperiod; 
   datetime opentime; 
   bool flag;
   string DotToComma(string value);
public:
   CsvWriter() { flag=false; };
   ~CsvWriter() { if(flag) FileClose(handle); };
   int FileCreate(string fileame,string Dir="",bool Common=false,bool FileNew=true,periodicity period=EvryTick);
   void FileSelectByHandle(int h,periodicity period=EvryTick) { handle=h; SetPeriodicity(period);};
   void SetPeriodicity(periodicity period);   
   int Write(string T1,string T2="",string T3="",string T4="",string T5="",string T6="",string T7="",
            string T8="",string T9="",string T10="",string T11="",string T12="",string T13="",string T14="",
            string T15="",string T16="",string T17="",string T18="",string T19="",string T20="",string T21="",
            string T22="",string T23="",string T24="",string T25="",string T26="",string T27="",string T28="",
            string T29="",string T30="",string T31="",string T32="",string T33="",string T34="",string T35="",
            string T36="",string T37="",string T38="",string T39="",string T40="",string T41="",string T42="",
            string T43="",string T44="",string T45="",string T46="",string T47="",string T48="",string T49="",
            string T50="",string T51="",string T52="",string T53="",string T54="",string T55="",string T56="",
            string T57="",string T58="",string T59="",string T60="",string T61="",string T62="",string T63="") {  
      int ReturnValue=0;   
      if(writeperiod==-1 || opentime!=iTime_Old(_Symbol,writeperiod,0)) {
         if(FileWrite(handle,DotToComma(T1),DotToComma(T2),DotToComma(T3),DotToComma(T4),DotToComma(T5),DotToComma(T6),
                  DotToComma(T7),DotToComma(T8),DotToComma(T9),DotToComma(T10),DotToComma(T11),DotToComma(T12),
                  DotToComma(T13),DotToComma(T14),DotToComma(T15),DotToComma(T16),DotToComma(T17),DotToComma(T18),
                  DotToComma(T19),DotToComma(T20),DotToComma(T21),DotToComma(T22),DotToComma(T23),DotToComma(T24),
                  DotToComma(T25),DotToComma(T26),DotToComma(T27),DotToComma(T28),DotToComma(T29),DotToComma(T30),
                  DotToComma(T31),DotToComma(T32),DotToComma(T33),DotToComma(T34),DotToComma(T35),DotToComma(T36),
                  DotToComma(T37),DotToComma(T38),DotToComma(T39),DotToComma(T40),DotToComma(T41),DotToComma(T42),
                  DotToComma(T43),DotToComma(T44),DotToComma(T45),DotToComma(T46),DotToComma(T47),DotToComma(T48),
                  DotToComma(T49),DotToComma(T50),DotToComma(T51),DotToComma(T52),DotToComma(T53),DotToComma(T54),
                  DotToComma(T55),DotToComma(T56),DotToComma(T57),DotToComma(T58),DotToComma(T59),DotToComma(T60),
                  DotToComma(T61),DotToComma(T62),DotToComma(T63))) {
            ReturnValue=1;
            FileFlush(handle);
         }
      }
      opentime = writeperiod==EvryTick ? 0 : iTime_Old(_Symbol,writeperiod,0);
      return(ReturnValue);
   }; //--------------------------------- End Write -------------------------------------
}; //--------------------- End CsvWriter ------------------------------------------------
int CsvWriter::FileCreate(string filename,string Dir="",bool Common=false,bool FileNew=true,
                           periodicity period=EvryTick) {
                           //Print ("Попытка создать файл");
   if(FileNew) {
   //Print ("Новый файл?");
      string NextName;   
      int Pos;
      string Filter = Dir=="" ? "*" : Dir+"\\*";
      long SearchHandle=Common ? FileFindFirst(Filter,NextName,FILE_COMMON) : FileFindFirst(Filter,NextName);
      int Count = StringFind(NextName,filename)>=0 && (Pos=StringFind(NextName,"_"))>0 ? 
                  (int)StringSubstr(NextName,0,Pos) : 0;
      NextName="";
      while(FileFindNext(SearchHandle,NextName))
         if(StringFind(NextName,filename)>=0 && (Pos=StringFind(NextName,"_"))>0)
            Count=MathMax(Count,(int)StringSubstr(NextName,0,Pos));        
      FileFindClose(SearchHandle);
      Count++;
      filename=IntegerToString(Count,6,'0')+"_"+filename;
   }
   filename = (Dir=="" ? filename : Dir+"\\"+filename)+".csv";
   handle= Common ? FileOpen(filename,FILE_CSV|FILE_COMMON|FILE_READ|FILE_WRITE|FILE_SHARE_READ) :
                        FileOpen(filename,FILE_CSV|FILE_READ|FILE_WRITE|FILE_SHARE_READ);
                       // Print ("handle=",handle);
   flag=handle>0;
   if(handle>0) {                          
      FileSeek(handle,0,SEEK_END);
      ulong pos=FileTell(handle);
      SetPeriodicity(period);
   }
   return(handle);   
} //---------------------- End FileCreate ------------------------------------------------
void CsvWriter::SetPeriodicity(periodicity period) {
   writeperiod = period; 
   opentime = period==EvryTick ? 0 : iTime_Old(_Symbol,period,0);
} //---------------------- End SetPeriodicity --------------------------------------------
string CsvWriter::DotToComma(string value) {
   int Pos=0;
   if((Pos=StringFind((string)value,"."))>=0 && StringFind(StringSubstr((string)value,Pos+1),".")<0)
      //value=StringSetChar(value,Pos,',');
      //Print (value);
        StringSetCharacter(value,Pos,',');
      //Print (value);
   return(value);
} //---------------------- End DotToComma ------------------------------------------------
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
datetime iTime_Old(string symbol,int tf,int index)
  {
   if(index < 0) return(-1);
   ENUM_TIMEFRAMES timeframe=TFMigrate_Old(tf);
   datetime Arr[];
   if(CopyTime(symbol,timeframe,index,1,Arr)>0)
      return(Arr[0]);
   else return(-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES TFMigrate_Old(int tf)
  {
   switch(tf)
     {
      case 0: return(PERIOD_CURRENT);
      case 1: return(PERIOD_M1);
      case 5: return(PERIOD_M5);
      case 15: return(PERIOD_M15);
      case 30: return(PERIOD_M30);
      case 60: return(PERIOD_H1);
      case 240: return(PERIOD_H4);
      case 1440: return(PERIOD_D1);
      case 10080: return(PERIOD_W1);
      case 43200: return(PERIOD_MN1);

      case 2: return(PERIOD_M2);
      case 3: return(PERIOD_M3);
      case 4: return(PERIOD_M4);
      case 6: return(PERIOD_M6);
      case 10: return(PERIOD_M10);
      case 12: return(PERIOD_M12);
      case 16385: return(PERIOD_H1);
      case 16386: return(PERIOD_H2);
      case 16387: return(PERIOD_H3);
      case 16388: return(PERIOD_H4);
      case 16390: return(PERIOD_H6);
      case 16392: return(PERIOD_H8);
      case 16396: return(PERIOD_H12);
      case 16408: return(PERIOD_D1);
      case 32769: return(PERIOD_W1);
      case 49153: return(PERIOD_MN1);
      default: return(PERIOD_CURRENT);
     }
  }  
Приложил скрипт целиком
Файлы:
Roffild
1319
Roffild  

78 Мбайт - наверняка там около 1 000 000 строк.

Сначала весь файл копируется в память. Потом 4 массива типа int (8 байт) умножить на количество строк. Конечно, оперативка закончится быстро.

Для работы с большими файлами чтение и запись нужно производить по секторно, а тут даже ненужная память не освобождается.
Aleksey Vyazmikin
15934
Aleksey Vyazmikin  
Roffild:

78 Мбайт - наверняка там около 1 000 000 строк.

Сначала весь файл копируется в память. Потом 4 массива типа int (8 байт) умножить на количество строк. Конечно, оперативка закончится быстро.

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

Строк в файле 606004.

Экслель что, разве не копирует данные в память?

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

Мне нужен полный массив в памяти для дальнейшей работы, иначе я потрачу время на чтение/запись гораздо больше.

Vladimir
1190
Vladimir  
Aleksey Vyazmikin:

Такой  у меня вопрос, есть файл CSV размером 78 мегабайт, хочу обсчитать его, так как эксель очень сильно тупит из-за размеров, думал воспользоваться MT5.

Сделал скрипт, который пока только считывает данные в массивы для каждой строки (57 массивов на чтение из файла и 57 на запись в новый файл), размер массива равен числу строк в файле CSV. Так вот, скрипт съел 8 гигабайт памяти, в то время как эксель менее чем 1,5 гигабайта, и операцию чтение/запись MT5 выполнял аж целых 9 минут!

У Вас 600 тыс. строк, каждая из которых содержит до 57 ячеек, которые считываются в одномерный массив строк       string            m_cells[]; То есть 36 миллионов строковых элементов в массиве. Тип string, помнится, занимает 12 байт даже для пустой строки. Это 400 Мб только служебной (адреса, длины строк) информации, даже если все ячейки пусты. Посмотрите, что происходит, когда Вы делаете resize этого массива при добавлении одной новой строки:

         m_total_rows++;
         ArrayResize(m_cells,m_total_rows*m_total_columns,10000);

- для каждой из 36 миллионов строк-ячеек нужно найти достаточный по длине кусок свободной памяти, захватить его, скопировать значение в новое место, проставить длину. То, что при этом выделяется память еще на 10 тысяч элементов (или байт, не помню), роли не играет - когда придет еще одна строка, m_total_rows опять увеличится, m_total_rows*m_total_columns тоже, и снова память под массив будет перевыделяться с копированием. Это причина длительности работы скрипта.

Память выделяется кусками с длиной, кратной 8 байтам даже для 32-разрядных ОС. Можно предположить, что под m_cells уходит не (400 + 78) Мб, а 1 Гб. Для каждого копирования нужно еще столько же места в памяти, сколько уже занято m_cells, удвоенная память займет 2 Гб памяти. Вместо 78 Мб, которые содержат реальную информацию.

В общем, очень неэффективен способ хранения в строковых ячейках. Говорить конкретнее, не зная задачи, трудно.

Konstantin Erin
2164
Konstantin Erin  
Попробуйте выбросить функции ArraySize() и ArrayResize() - ведь размер Вам известен. На всякий случай возьмите в 2 раза больше... Сообщите результат
Vladislav Andruschenko
161178
Vladislav Andruschenko  
Konstantin Erin:
Попробуйте выбросить функции ArraySize() и ArrayResize() - ведь размер Вам известен. На всякий случай возьмите в 2 раза больше... Сообщите результат
Aleksey Vyazmikin:

Такой  у меня вопрос, есть файл CSV размером 78 мегабайт, хочу обсчитать его, так как эксель очень сильно тупит из-за размеров, думал воспользоваться MT5.

Сделал скрипт, который пока только считывает данные в массивы для каждой строки (57 массивов на чтение из файла и 57 на запись в новый файл), размер массива равен числу строк в файле CSV. Так вот, скрипт съел 8 гигабайт памяти, в то время как эксель менее чем 1,5 гигабайта, и операцию чтение/запись MT5 выполнял аж целых 9 минут!


я когда-то сталкивался с такой проблемой. Делал много исправлений. Всего не помню - это было разовое задание, 

но попробуйте задать здесь ArrayResize(arrRead_01,arrSize);  3 параметр


   int    reserve_size=0        // reserve size value (excess)


поэкспериментируйте. 

Aleksey Vyazmikin
15934
Aleksey Vyazmikin  
Vladimir:

У Вас 600 тыс. строк, каждая из которых содержит до 57 ячеек, которые считываются в одномерный массив строк       string            m_cells[]; То есть 36 миллионов строковых элементов в массиве. Тип string, помнится, занимает 12 байт даже для пустой строки. Это 400 Мб только служебной (адреса, длины строк) информации, даже если все ячейки пусты. Посмотрите, что происходит, когда Вы делаете resize этого массива при добавлении одной новой строки:

         m_total_rows++;
         ArrayResize(m_cells,m_total_rows*m_total_columns,10000);

- для каждой из 36 миллионов строк-ячеек нужно найти достаточный по длине кусок свободной памяти, захватить его, скопировать значение в новое место, проставить длину. То, что при этом выделяется память еще на 10 тысяч элементов (или байт, не помню), роли не играет - когда придет еще одна строка, m_total_rows опять увеличится, m_total_rows*m_total_columns тоже, и снова память под массив будет перевыделяться с копированием. Это причина длительности работы скрипта.

Спасибо за анализ кода.

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

Vladimir:

Память выделяется кусками с длиной, кратной 8 байтам даже для 32-разрядных ОС. Можно предположить, что под m_cells уходит не (400 + 78) Мб, а 1 Гб. Для каждого копирования нужно еще столько же места в памяти, сколько уже занято m_cells, удвоенная память займет 2 Гб памяти. Вместо 78 Мб, которые содержат реальную информацию.

В общем, очень неэффективен способ хранения в строковых ячейках. Говорить конкретнее, не зная задачи, трудно.

Хотелось бы понять откуда берется 400 мегабайт сразу? Я правильно понял, что память выделяется, но не очищается/отдается ранее выделенная?

Aleksey Vyazmikin
15934
Aleksey Vyazmikin  
Konstantin Erin:
Попробуйте выбросить функции ArraySize() и ArrayResize() - ведь размер Вам известен. На всякий случай возьмите в 2 раза больше... Сообщите результат

Откуда выбросить из скрипта или класса? Размер известен, так как я знаю размер файла? Но, файл же может быть другого размера, скрипт делается не на раз...

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий