Медленный C++
От: anatoly1  
Дата: 26.05.14 08:54
Оценка: :)))
С++ медленнее питона при парсинге файла.

С++ — версия:

#include <string>
#include <vector>
#include <sstream>
#include <fstream>

using namespace std;

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    split(s, delim, elems);
    return elems;
}

int main()
{
    std::ifstream f;
    f.open("test.csv");

    std:string s;
    std::vector<std::string> sv;

    while ( std::getline(f, s) )
    {
        sv = split(s, ';');
    }

    return 0;
}


real    0m18.429s
user    0m15.919s
sys    0m0.259s


Boost'овский split, кстати, ещё медленней работает.

А вот питон — версия:

with open("test.csv", "r") as f:
    for line in f:
        s = line.split(";")


real    0m4.029s
user    0m3.346s
sys    0m0.124s


В чём может быть причина такой низкой производительности у С++?
Re: Медленный C++
От: smeeld  
Дата: 26.05.14 09:33
Оценка: 1 (1) :))
Здравствуйте, anatoly1, Вы писали:

A>С++ медленнее питона при парсинге файла.


Грубое использование string, vector, sstream объектов. Время уходит на запросы памяти
в этих контейнерах. По мне так лучше сначала выделить буферы фиксированного размера,
и в процессе использовать их, с контролем переполнения. Эти буферы можно передавать
и в sstream, и в string/vector, которые будут передаваемые им элементы помещать
в эти буферы, не делая постоянные malloc.
А вообще прикольно писать парсеры не тупо на контейнерах, а примерно так:

struct parser{


 char* parse(char* p, const char* s, char* pp) const {
  
  char *tmp=p; size_t sz=0, len=strlen(s);
   
 do{
while(*p <45 || *p >122){ if(p==pp) return NULL; ++p; };
  tmp=p; sz=0;
while(*p > 44 &&  *p < 123){ if(p==pp) return NULL; ++p; ++sz;};
   if(sz!=len) continue;
   if(strncmp(tmp, s, sz)==0){ 
while(*p <45 || *p >122){ if(p==pp) return NULL; ++p; }; tmp=p;
while(*p > 44 &&  *p < 123){ ++p;  }; *p='\0'; return tmp;
       };

  }while(1);  
 };


template <typename T>
void parse_array(char* p, T* vec, char* pp){

 size_t sz=0; char* tmp;
do{ if(p==pp && *p=='}')  return; 
   while(*p <45 || *p >122){  ++p; if(p==pp || *p=='}')  return; }; tmp=p;
    while(*p > 44 &&  *p < 123){ if(p==pp)  return; ++p; }; *p='\0'; vec[sz]=cast(tmp, vec+sz); ++sz;
     
       }while(1);
    
  };

template <typename T>
T cast(char* s, T* p){   if(typeid(p[0])==typeid(float)){ return std::stof(s); }else{ return std::stoi(s); }; }; 

  };
Re: Медленный C++
От: Aртём Австралия жж
Дата: 26.05.14 09:34
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>

A>std::vector<std::string> split(const std::string &s, char delim) {
A>    std::vector<std::string> elems;
A>    split(s, delim, elems);
 ====>>>> Copy constructor !!!
A>    return elems;
A>}

A>


A>А вот питон — версия:


A>
A>with open("test.csv", "r") as f:
 ====>>>> Generator 
A>    for line in f:
A>        s = line.split(";")
A>



A>В чём может быть причина такой низкой производительности у С++?

В неправильном использовании инструмента.
Re[2]: Медленный C++
От: anatoly1  
Дата: 26.05.14 09:51
Оценка: :))) :)))
Здравствуйте, Aртём, Вы писали:

A>>

A>>std::vector<std::string> split(const std::string &s, char delim) {
A>>    std::vector<std::string> elems;
A>>    split(s, delim, elems);
Aё> ====>>>> Copy constructor !!!
A>>    return elems;
A>>}

A>>


Oh shi
Я же забыл из дебаг-режима переключиться.
Сразу стало нормально:
real    0m0.007s
user    0m0.002s
sys    0m0.003s


Aё> ====>>>> Copy constructor !!!


Компилятор такое сейчас умеет оптимизировать.
Re[2]: Медленный C++
От: anatoly1  
Дата: 26.05.14 09:53
Оценка: +4
Здравствуйте, smeeld, Вы писали:

S>
S>struct parser{
S> ...
S>  };

S>


жесть какая
Re[3]: Медленный C++
От: Aртём Австралия жж
Дата: 26.05.14 10:01
Оценка:
Здравствуйте, anatoly1, Вы писали:

Aё>> ====>>>> Copy constructor !!!


A>Компилятор такое сейчас умеет оптимизировать.

Ссылку?
Re[3]: Медленный C++
От: anatoly1  
Дата: 26.05.14 10:03
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>Я же забыл из дебаг-режима переключиться.

A>Сразу стало нормально:
A>
A>real    0m0.007s
A>user    0m0.002s
A>sys    0m0.003s
A>


Нет, не стало.
Вот результат release-режима:
real    0m12.807s
user    0m11.407s
sys    0m0.201s
Re[4]: Медленный C++
От: anatoly1  
Дата: 26.05.14 10:07
Оценка:
Здравствуйте, Aртём, Вы писали:

Aё>Здравствуйте, anatoly1, Вы писали:


Aё>>> ====>>>> Copy constructor !!!


A>>Компилятор такое сейчас умеет оптимизировать.

Aё>Ссылку?

http://en.cppreference.com/w/cpp/language/copy_elision
Re: Медленный C++
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 26.05.14 10:11
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>В чём может быть причина такой низкой производительности у С++?


Память!
Можешь ещё у профайлера спросить.
Re: Медленный C++
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 26.05.14 10:16
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>С++ медленнее питона при парсинге файла.

А как на питоне это делается?
A>В чём может быть причина такой низкой производительности у С++?
В том, что это у тебя не С++.
Sic luceat lux!
Re[2]: Медленный C++
От: anatoly1  
Дата: 26.05.14 10:22
Оценка: +1
Здравствуйте, Kernan, Вы писали:

K>А как на питоне это делается?


В первом посте приведен код.

K>В том, что это у тебя не С++.


А что это тогда такое?
Re[4]: Медленный C++
От: smeeld  
Дата: 26.05.14 10:41
Оценка:
Здравствуйте, anatoly1, Вы писали:


A>Нет, не стало.


Вместо
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems; /* вот это вообще зачем не понятно? */


Можно
 std::vector<std::string> & split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss;
std::string item;
ss.rdbuf()->pubsetbuf(const_cast<char*>(s.c_str()), ss.size());
 while (std::getline(ss, item, delim)) {
        elems.push_back(item);
  return elems;
   }


Для начала.
Потом и свои аллокаторы для string и vector назначить не мешало бы.
Re[5]: Медленный C++
От: anatoly1  
Дата: 26.05.14 10:53
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Для начала.

S>Потом и свои аллокаторы для string и vector назначить не мешало бы.

В такие дебри, конечно, лезть бы не хотелось.
Re: Медленный C++
От: Няшка Россия  
Дата: 26.05.14 13:42
Оценка:
Здравствуйте, anatoly1, Вы писали:

Вот накидал за минуту первое же решение, которое пришло в голову...

int main()
{
std::ifstream f;
f.open("test.csv");

std:string s;
std::vector<std::string> sv;

while ( std::getline(f, s) )
for( std::string::iterator src = s->begin(), last = s->begin(); src != s->end(); ++src)
if ( *src == ';' )
{
std:string snew( last, src );
sv.push_back( snew );
last = src;
}

return 0;
}

p.s. Есть косяки, которые знающий увидит и поправит за 2-ю минуту
80% людей оценивают свое мастерство выше среднего...
Re: Медленный C++
От: _DAle_ Беларусь  
Дата: 26.05.14 13:47
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>С++ медленнее питона при парсинге файла.


A>С++ — версия:


A>В чём может быть причина такой низкой производительности у С++?


А что-нибудь меняется, если первой строкой написать std::ios_base::sync_with_stdio(false); ?
Re[2]: Медленный C++
От: anatoly1  
Дата: 26.05.14 14:27
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>А что-нибудь меняется, если первой строкой написать std::ios_base::sync_with_stdio(false); ?


error: expected constructor, destructor, or type conversion before '(' token
Re[3]: Медленный C++
От: _DAle_ Беларусь  
Дата: 26.05.14 14:32
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>Здравствуйте, _DAle_, Вы писали:


_DA>>А что-нибудь меняется, если первой строкой написать std::ios_base::sync_with_stdio(false); ?


A>
A>error: expected constructor, destructor, or type conversion before '(' token
A>


Первой строкой в main()
Re[4]: Медленный C++
От: anatoly1  
Дата: 26.05.14 14:40
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>Первой строкой в main()


Я уже чуть выше выкладывал результат в release-режиме (в первом посте, по моей невнимательности, был дебаг-режим).
Результат с опцией std::ios_base::sync_with_stdio(false) получился таким:
real    0m11.934s
user    0m10.424s
sys    0m0.186s

Заметного ускорения не наблюдается.
Re[2]: Медленный C++
От: Pavel Dvorkin Россия  
Дата: 26.05.14 14:57
Оценка: 3 (2)
Здравствуйте, smeeld, Вы писали:

S>А вообще прикольно писать парсеры не тупо на контейнерах, а примерно так:


<skipped>

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


#include "stdafx.h"
#include "string.h"


int _tmain(int argc, _TCHAR* argv[])
{
    char str[] ="- This, a sample string.";
    char * pch;
    printf ("Splitting string \"%s\" into tokens:\n",str);
    pch = strtok (str," ,.-");
    while (pch != NULL)
    {
        printf ("%s\n",pch); 
        pch = strtok (NULL, " ,.-");
    }
    return 0;
}


Код взят отсюда

http://www.cplusplus.com/reference/cstring/strtok/
With best regards
Pavel Dvorkin
Re[3]: Медленный C++
От: smeeld  
Дата: 26.05.14 15:13
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А вот так проще. Используем strtok, которая для этого и предназначена. При этом не выделяется ни одного байта памяти. Правда, исходная строка портится, но это не так уж важно.


Покапитанить решили? Не интересно так.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.