Re[9]: Медленный C++
От: jazzer Россия Skype: enerjazzer
Дата: 27.05.14 05:55
Оценка: +4 :))) :)))
Здравствуйте, trop, Вы писали:

T>можно трансформировать монады


можно грабить корованы
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
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: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 26.05.14 15:20
Оценка: 3 (2) +3
Здравствуйте, anatoly1, Вы писали:

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


Прежде всего, вместо создания множества std::string (с аллокацией на каждую), для выделения частей нужно использовать string view, например
typedef boost::iterator_range<std::string::const_iterator> string_view;
boost::algorithm::split умеет с ними работать.

То есть вместо:
std::vector<std::string> parts;
достаточно:
std::vector<string_view> parts;

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

В версии на C++ аллоцируется много мутабельных строк, в то время как в версии на Python строки иммутабельные, для них просто берётся view.
Плюс, у тебя vector аллоцируется каждый раз создаётся заново, а нужно создать его только один раз и переиспользовать его capacity многократно.
Re[5]: Медленный C++
От: Aртём Австралия жж
Дата: 27.05.14 01:58
Оценка: -4 :)
Здравствуйте, anatoly1, Вы писали:

A>http://en.cppreference.com/w/cpp/language/copy_elision


Однако ж, гонка вооружений по прострелу ноги в C++ впечатляет Жесть какая.

Under the following circumstances, the compilers are permitted to omit the copy- and move-constructors of class objects even if copy/move constructor and the destructor have observable side-effects.


Т.е. ладно бы компилятор был обязан отбросить, но он же не обязан- т.е. поведение программы непредсказуемо отличается между debug и release компиляцией и даже release с разными ключиками.

Только Java и C (без плюсанутых) спасут этот мир .
Re[2]: Медленный C++
От: anatoly1  
Дата: 26.05.14 09:53
Оценка: +4
Здравствуйте, smeeld, Вы писали:

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

S>


жесть какая
Re[6]: Медленный C++
От: smeeld  
Дата: 27.05.14 06:10
Оценка: +2 -1 :)
Здравствуйте, Aртём, Вы писали:

Aё>Только Java и C (без плюсанутых) спасут этот мир .


Тут, на форуме, скромно пытаюсь высказать такую же мысль.
Страуструп дополнил чистый C OOП-ом. ООП это важно в ЯП. На этом можно было бы
и остановиться. Но C++ превратился в пастбище праздных академиков, которые
курят то, что даже мыщъху не известно. Они превратили язык в демонстрацию
своей нужности и важности. Лучше бы тесселяционные шейдеры в Mesa разрабатывали,
и вообще занимались чем полезным.
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); }; }; 

  };
Медленный 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[8]: Медленный C++
От: trop Россия  
Дата: 27.05.14 05:52
Оценка: +1 :))
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>непонятно зачем кому-то использовать голое API при наличии готовых библиотек, предоставляющих все необходимые возможности.

зачем с++ ???

код похож на каку, платят за весь тот объём знаний, ухищрений, наработок и костылей мало,
есть же нормальные ФЯ, в которых не нужно задумываться о каком-то токенайзере,
в которых можно строить всевозможные типы данных, хитросплетения функций,
в которых всё легко запараллеливается, кода мало и он красивый

можно трансформировать монады
-
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[2]: Медленный C++
От: smeeld  
Дата: 26.05.14 20:11
Оценка: :))
Здравствуйте, alex_public, Вы писали:

_>И соответственно этот код работает у меня где-то в 2,5 раза быстрее, чем его аналог на Питоне.


Осталось немного, и придёт, наконец, понимание, что здесь, в этой задачке, контейнеры и стримы вообще
ни куда не упёрлись. Их нельзя использовать на каждый чих. Сформировать malloc-ом буфер с содержимым
файла, разбить его на токены или предложения нуль терминатором, последовательно с занесением указателей в массив.
Вот указатели, а лучше их unique_ptr, можно уже складывать в вектор. Только не забыть задать ему первоначальный
размер отличный от нуля, а то vector, созданный дефолтным конструктором, сначала запрашивает память под объект,
потом под два, копируя туда содержание предыдущего буфера и удаляя его, потом под четыре и так далее, кто-то
скажет, что использовать такой способ организации буфера правильно?
Re[7]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 26.05.14 22:15
Оценка: +2
Здравствуйте, smeeld, Вы писали:

S>У alex_public всё как надо, мене не понятно только одно: зачем

S>тащить всякое из boost, когда в любой ОС есть нативные средства
S>маппинга, который boost и врайпит. Мне, года проведшему на чистом
S>posix API в solaris, не понятно, почему такая мода на библиотеки?

1. Кроссплатформенность.
2. Это часть Boost.Iostreams, в которой определен набор концепций-интерфейсов. Соответственно враппер даёт нужный интерфейс, со всеми вытекающими.
3. Идиоматичность — RAII, etc.

Учитывая всё это, мне вот наоборот непонятно зачем кому-то использовать голое API при наличии готовых библиотек, предоставляющих все необходимые возможности.
Re: Медленный C++
От: visual_wind  
Дата: 26.05.14 16:31
Оценка: 2 (1)
Здравствуйте, anatoly1, Вы писали:

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

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

Была уже много лет назад вот эта
Автор: Denis2005
Дата: 16.09.06
тема, в которой полоскали split, правда бустовский. Там вот в этой
Автор: eao197
Дата: 17.09.06
ветке сокрушались о бустовской реализация is_any_of. Возможно, что и на текущий день ситуация со производительностью split кардинально не поменялась. Вот в этой
Автор: Андрей Хропов
Дата: 24.09.06
ветке автор приводил завершающие измерения проиводительности для разных языков.
Re[2]: Медленный C++
От: anatoly1  
Дата: 26.05.14 10:22
Оценка: +1
Здравствуйте, Kernan, Вы писали:

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


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

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


А что это тогда такое?
Re: Медленный C++
От: alex_public  
Дата: 26.05.14 18:15
Оценка: +1
Здравствуйте, anatoly1, Вы писали:

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


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

A>...

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

A>...

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


Причина в том, что это у вас абсолютно разные коды. Версия на Питоне просто просматривает файл и всё. А версия на C++ ещё и делает некие дополнительные действия — создаёт копии определённых кусков данных из файла. Если вы хотите получить реальную C++ копию кода на Питоне, то это будет что-то вроде:
auto split(const char* s, const char* e, char d)
{
    vector<pair<const char*, const char*>> r;
    for(const char* c=s; c!=e; ++c) if(*c==d){
        r.emplace_back(s, c);
        s=c+1;
    }
    return r;
}
int main()
{
    mapped_file_source file("test.csv");
    for(auto l: split(file.data(), file.data()+file.size(), '\n'))
        auto s=split(l.first, l.second, ';');
    return 0;
}


И соответственно этот код работает у меня где-то в 2,5 раза быстрее, чем его аналог на Питоне.
Re[2]: Медленный C++
От: Vain Россия google.ru
Дата: 26.05.14 19:01
Оценка: +1
Здравствуйте, smeeld, Вы писали:

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

S>struct parser{
надо создать форум "код по укурке"
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[6]: Медленный C++
От: smeeld  
Дата: 26.05.14 21:44
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>Ты же отвечал на сообщение alex_public? А у него mapped_file_source.


У alex_public всё как надо, мене не понятно только одно: зачем
тащить всякое из boost, когда в любой ОС есть нативные средства
маппинга, который boost и врайпит. Мне, года проведшему на чистом
posix API в solaris, не понятно, почему такая мода на библиотеки?
й
Re[7]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 10:21
Оценка: -1
Здравствуйте, smeeld, Вы писали:

S>Здравствуйте, Няшка, Вы писали:


Н>>2. Рост которого не всегда сопровождается копированием данных — зависит от реализации и аллокатора

S>У аллокатора только спрашивают указатель, вызывая его allocate, и ему же велят удалять кусок памяти, вызывая его deallocate. Всё.
S>С самим данныи контейнер делает что ему хочется. И vector, если вновь помещаемые данные превысят имеющийся объём,
S>вызывает allocate, копирует в новый буфер предыдущий, и вызывает deallocate предыдущему.

если данные не переехали, то их можно и не копировать

Н>>3. Если Вы работаете не только с однобайтовым английским языком, то создать хороший текстовый парсер не на шаблонах будет тугой задачей

Н>>4. Читать весь файл csv в память и разбивать терминатором, чтобы потом копировать memcpy/strcpy — это бредовая идея для домашнего программирования.
Н>> Подумайте внимательно, как будет работать Ваше решение на большом файле?..

S>А никто и не спорит про большие файлы. Большие файлы никто копировать в ram и не собирался, не надо капитанить.

S>Приведённый в треде пример с маппингом и двумя указателями известен всем страждущим. Только в контексте задачи TC,
ТС в глобальном плане задачи не освещал
может он на серваке логи крутить в csv хочет и ищет вариант быстрее...

S>всё это тут накручивать будет лишним. Речь изначально велась об ускорении работы приложения.

Ускорение на 5 кб не имеет значения, любой вариант сгодится. Хоть на регулярках... затраты на современной технике будут копеешные.
Скорость актуальна в бигдата и высоконагруженном программировании.
Сколько миллисекунд там эксель непосредственно будет читать табличку из csv — всем насрать.

S>И парсинг побайтовым сравнением можно проводить на тексте любой кодировки. Шаблон понадобится для определения конкретной специфики

S>сравнения при поиске, и выдачи результатов. И всё спокойно проделывается и без задействования контейнеров.

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

H>> а на сервере в несколько потоков?..

Н>> Какая будет стратегия на ошибки выделения памяти??? Как будете отдавать процессорное время другим задачам??? Куча не нужных проблем появится.

S>И чем здесь именно контейнеры на шаблонах обеспечат threading safe? Разруливать всё придётся так же, как и без использования контейнеров.

Если бахать всё сразу в память, то конечно тут помочь уже нечем.
80% людей оценивают свое мастерство выше среднего...
Re[4]: Медленный C++
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 27.05.14 12:24
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Возможно, но я думаю вряд ли это решающий фактор (это надо было бы очень сильно накосячить) — потому что целый набор аллокаций стандартным аллокатором на каждую итерацию это реально медленно.

EP>Это, кстати, подтверждается новым примером ТС
Автор: anatoly1
Дата: 27.05.14
— избавившись от аллокаций на каждой итерации, он ускорился на порядок.


Я просто помню, что ifstream очень медленный и часто читает файл, если читать его через getline, может у него просто буфер внутри маленький. Я правда ifstream уже не помню когда в последний раз использовал, но судя по тому, что без аллокаций получилось просто достигнуть паритета с питоновским кодом, то дело может быть и в этом. В общем, хорошо бы ТС прочитал файл в память полностью, а потом уже распарсил, тогда можно будет понять в чем проблема.
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[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[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[3]: Медленный C++
От: smeeld  
Дата: 26.05.14 15:13
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


Покапитанить решили? Не интересно так.
Re[4]: Медленный C++
От: Pavel Dvorkin Россия  
Дата: 26.05.14 15:21
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Покапитанить решили? Не интересно так.


Интересно или нет, но эту функцию никто здесь не упомянул. Получилось впечатление, что либо нужно писать что-то совсем уж вручную (как у тебя), или без STL никак не обойтись. Вот я и решил напомнить...
With best regards
Pavel Dvorkin
Re: Медленный C++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 26.05.14 16:07
Оценка:
Здравствуйте, anatoly1, Вы писали:

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


Скорее всего дело не в С++, а в том, как идет работа с файлом.

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

Что бы исключить этот случай, нужно подсунуть вместо file open текстовую простыню. Если и там отстает С++, то дело в стл-структурах.
Re: Медленный C++
От: anatoly1  
Дата: 26.05.14 17:30
Оценка:
Сделал так:

#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;
    for (int i = 0; std::getline(ss, item, delim); i++)
        elems[i] = std::move(item);
    return elems;
}

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

    std:string s;
    std::vector<std::string> sv(201);

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

    return 0;
}


Стало:

real    0m3.087s
user    0m2.569s
sys    0m0.081s
Re[2]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 26.05.14 18:33
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>Сделал так:

A>
A>std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
A>    std::stringstream ss(s);
A>    std::string item;
A>    for (int i = 0; std::getline(ss, item, delim); i++)
A>        elems[i] = std::move(item);
A>    return elems;
A>}
A>


Аллоцируются строки для каждого элемента в s, stringstream создаётся каждый раз заново. elems должен содержать просто string view.
Да и вообще, в зависимости от задачи, может и elems не нужен — можно обрабатывать по месту.
Re[2]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 26.05.14 18:38
Оценка:
Здравствуйте, alex_public, Вы писали:

_>то это будет что-то вроде:

_>
_>auto split(const char* s, const char* e, char d)
_>{
_>    vector<pair<const char*, const char*>> r;
_>      // [...]
_>    return r;
_>}
_>

_>И соответственно этот код работает у меня где-то в 2,5 раза быстрее, чем его аналог на Питоне.

Можно ещё и vector не аллоцировать каждый раз, а переиспользовать capacity — будет ещё быстрее.
Re[2]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 26.05.14 19:13
Оценка:
Здравствуйте, visual_wind, Вы писали:

_>Была уже много лет назад вот эта
Автор: Denis2005
Дата: 16.09.06
тема, в которой полоскали split, правда бустовский. Там вот в этой
Автор: eao197
Дата: 17.09.06
ветке сокрушались о бустовской реализация is_any_of. Возможно, что и на текущий день ситуация со производительностью split кардинально не поменялась. Вот в этой
Автор: Андрей Хропов
Дата: 24.09.06
ветке автор приводил завершающие измерения проиводительности для разных языков.


У этой темы было продолжение
Автор: Hard_Club
Дата: 15.07.13
.
Re: Медленный C++
От: Ops Россия  
Дата: 26.05.14 20:01
Оценка:
Здравствуйте, anatoly1, Вы писали:

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


Если boost, то есть tokenizer, для такой задачи самое то.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[3]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 26.05.14 20:29
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Осталось немного, и придёт, наконец, понимание, что здесь, в этой задачке, контейнеры и стримы вообще

S>ни куда не упёрлись. Их нельзя использовать на каждый чих. Сформировать malloc-ом буфер с содержимым
S>файла,

Во-первых он файл уже отмэппил файл в память, без всяких аллокаций. А во-вторых, даже если выделять память под весь файл, malloc от вектора практически ничем не будет отличатся в плане скорости

S>разбить его на токены или предложения нуль терминатором, последовательно с занесением указателей в массив.

S>Вот указатели, а лучше их unique_ptr, можно уже складывать в вектор.

Указатели на внутренние элементы массива в unique_ptr?

S>Только не забыть задать ему первоначальный

S>размер отличный от нуля, а то vector, созданный дефолтным конструктором, сначала запрашивает память под объект,

Дефолтный конструктор создаёт пустой вектор, и на популярных реализациях с нулевой capacity.

S> потом под два, копируя туда содержание предыдущего буфера и удаляя его, потом под четыре и так далее, кто-то

S>скажет, что использовать такой способ организации буфера правильно?

При неизвестном конечном размере — вполне себе, добавление amortized O(1) (в системах подверженных фрагментации памяти, лучше брать factor меньше золотого сечения)
А если размер известен, либо есть "типичное" значение, то тогда просто делается .reserve(x).
Re[4]: Медленный C++
От: smeeld  
Дата: 26.05.14 20:54
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>Во-первых он файл уже отмэппил файл в память, без всяких аллокаций. А во-вторых, даже если выделять память под весь файл, malloc от вектора практически ничем не будет отличатся в плане скорости


Если не изменяет память, то ТС в vector пихает структуру std::string, std::basic_string::_Alloc_hider::_M_p которой содержит
указатель на кусок памяти с строкой, который аллоцируется, с копированием строки из файла, в строчке std::getline(ss, item, delim))
Так что кроме мапа файла есть ещё куча кусков, разбросанных по просторам виртуальной памяти.

EP>Указатели на внутренние элементы массива в unique_ptr?

Думал не заметите

EP>Дефолтный конструктор создаёт пустой вектор, и на популярных реализациях с нулевой capacity.

Это понятно, беда начинается, когда начинаем пустому vector делать push_back/emplace_back. Вот тут
он начинает наращивать свою capacity, последовательно-куча новых аллокаций на первых элементах.

EP>При неизвестном конечном размере — вполне себе, добавление amortized O(1) (в системах подверженных фрагментации памяти, лучше брать factor меньше золотого сечения)

EP>А если размер известен, либо есть "типичное" значение, то тогда просто делается .reserve(x).

Это понятно, только у ТС так не сделано, потому и упомянуто.
Re[5]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 26.05.14 21:22
Оценка:
Здравствуйте, smeeld, Вы писали:

EP>>Во-первых он файл уже отмэппил файл в память, без всяких аллокаций. А во-вторых, даже если выделять память под весь файл, malloc от вектора практически ничем не будет отличатся в плане скорости

S>Если не изменяет память, то ТС в vector пихает структуру std::string, std::basic_string::_Alloc_hider::_M_p которой содержит

Ты же отвечал на сообщение alex_public? А у него mapped_file_source.

EP>>Дефолтный конструктор создаёт пустой вектор, и на популярных реализациях с нулевой capacity.

S>Это понятно, беда начинается, когда начинаем пустому vector делать push_back/emplace_back. Вот тут
S>он начинает наращивать свою capacity, последовательно-куча новых аллокаций на первых элементах.

Тут основная задача не в том чтобы на каждой итерации была одна аллокация вместо логарифма, а в том чтобы вообще избавится от аллокаций на каждой итерации, т.е. переиспользовать уже имеющуюся capacity. В этом случае от O(log(max_tokens_per_string)) аллокаций на всё приложение не будет никакой беды (хотя конечно reserve не помешает, но не критичен).
Re: Медленный C++
От: Философ Ад http://vk.com/id10256428
Дата: 26.05.14 21:59
Оценка:
Здравствуйте, anatoly1, Вы писали:

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


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


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



Как измерения проводились?
Что означают эти строки?

чем "real" отличается от "sys"?

как я могу повторить ваш эксперимент?
Всё сказанное выше — личное мнение, если не указано обратное.
Re[2]: Медленный C++
От: anatoly1  
Дата: 27.05.14 04:36
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>Как измерения проводились?

Ф>Что означают эти строки?
Ф>чем "real" отличается от "sys"?

http://linux.about.com/library/cmd/blcmdl1_time.htm

Ф>как я могу повторить ваш эксперимент?


Распарсить большой файл, каждая строчка которого имеет формат вида:
a1;a2;a3;a4;...;a200
Необходимо каждую такую строку преобразовать в объект наподобие:
obj = ["a1", "a2", ..., "a200"]
Re[3]: Медленный C++
От: mik1  
Дата: 27.05.14 06:09
Оценка:
Здравствуйте, anatoly1, Вы писали:

Ф>>как я могу повторить ваш эксперимент?


A>Распарсить большой файл, каждая строчка которого имеет формат вида:

A>a1;a2;a3;a4;...;a200
A>Необходимо каждую такую строку преобразовать в объект наподобие:
A>obj = ["a1", "a2", ..., "a200"]

Остаются маленькие вопросы в размере файла, кодировке и в необходимости возвращать коллекции для каждой сторки (итератора / элементов по одному недостаточно?).
Патамучта в случае определенных ответов можно читать байты и отсекать по разделителю и/или newline.
Re[3]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 06:51
Оценка:
Здравствуйте, smeeld, Вы писали:

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


_>>И соответственно этот код работает у меня где-то в 2,5 раза быстрее, чем его аналог на Питоне.


S>Осталось немного, и придёт, наконец, понимание, что здесь, в этой задачке, контейнеры и стримы вообще

S>ни куда не упёрлись. Их нельзя использовать на каждый чих. Сформировать malloc-ом буфер с содержимым
S>файла, разбить его на токены или предложения нуль терминатором, последовательно с занесением указателей в массив.
S>Вот указатели, а лучше их unique_ptr, можно уже складывать в вектор. Только не забыть задать ему первоначальный
S>размер отличный от нуля, а то vector, созданный дефолтным конструктором, сначала запрашивает память под объект,
S> потом под два, копируя туда содержание предыдущего буфера и удаляя его, потом под четыре и так далее, кто-то
S>скажет, что использовать такой способ организации буфера правильно?

Веткой случаем не промахнулись? Вам туда http://rsdn.ru/forum/flame.comp/5578775.1
Автор: alpha21264
Дата: 28.04.14
80% людей оценивают свое мастерство выше среднего...
Re[4]: Медленный C++
От: smeeld  
Дата: 27.05.14 07:04
Оценка:
Здравствуйте, Няшка, Вы писали:


Н>Веткой случаем не промахнулись?


Нет. Шаблоны фундаментальный и необходимый инструмент. Если Вас не затруднит прочитать
внимательней, то поймёте, что речь идёт о неаккуратном, бездумном
использовании контейнеров.
Re[2]: Медленный C++
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 27.05.14 07:14
Оценка:
Здравствуйте, Философ, Вы писали:

Ф>Как измерения проводились?

Ф>Что означают эти строки?
Ф>чем "real" отличается от "sys"?


man time 1


link
Re[5]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 07:48
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Здравствуйте, Няшка, Вы писали:



Н>>Веткой случаем не промахнулись?


S>Нет. Шаблоны фундаментальный и необходимый инструмент. Если Вас не затруднит прочитать

S>внимательней, то поймёте, что речь идёт о неаккуратном, бездумном
S>использовании контейнеров.

1. Vector — это шаблон
2. Рост которого не всегда сопровождается копированием данных — зависит от реализации и аллокатора
3. Если Вы работаете не только с однобайтовым английским языком, то создать хороший текстовый парсер не на шаблонах будет тугой задачей
4. Читать весь файл csv в память и разбивать терминатором, чтобы потом копировать memcpy/strcpy — это бредовая идея для домашнего программирования.
Подумайте внимательно, как будет работать Ваше решение на большом файле?.. а на сервере в несколько потоков?..
Какая будет стратегия на ошибки выделения памяти??? Как будете отдавать процессорное время другим задачам??? Куча не нужных проблем появится.
80% людей оценивают свое мастерство выше среднего...
Re[3]: Медленный C++
От: jazzer Россия Skype: enerjazzer
Дата: 27.05.14 07:49
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>Распарсить большой файл, каждая строчка которого имеет формат вида:

A>a1;a2;a3;a4;...;a200
A>Необходимо каждую такую строку преобразовать в объект наподобие:
A>obj = ["a1", "a2", ..., "a200"]

И что дальше? Обработать каждую строчку и забыть? Или поиметь весь файл в памяти в виде развесистой структуры?

Иными словами, что должно остаться в памяти после окончания парсинга файла?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 07:55
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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


S>>Покапитанить решили? Не интересно так.


PD>Интересно или нет, но эту функцию никто здесь не упомянул. Получилось впечатление, что либо нужно писать что-то совсем уж вручную (как у тебя), или без STL никак не обойтись. Вот я и решил напомнить...


эта функция зависит от кодировки, а шаблоны нет
впрочем, собственная ее реализация для шаблона — копеечный вопрос
80% людей оценивают свое мастерство выше среднего...
Re[4]: Медленный C++
От: anatoly1  
Дата: 27.05.14 08:01
Оценка:
Здравствуйте, jazzer, Вы писали:

J>И что дальше? Обработать каждую строчку и забыть?


Да, именно так.

В итоге, думаю, остановлюсь на таком варианте:

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

    std:string s;
    std::vector<std::string> sv(201);
    std::stringstream ss;
    std::string item;

    while ( std::getline(f, s) )
    {
        ss.clear();
        ss.str(s);
        for (int i = 0; std::getline(ss, item, ';'); i++)
            std::swap(sv[i], item);
    }

    return 0;
}



real    0m2.965s
user    0m2.564s
sys    0m0.104s
Re[6]: Медленный C++
От: Pavel Dvorkin Россия  
Дата: 27.05.14 08:32
Оценка:
Здравствуйте, Няшка, Вы писали:


Н>эта функция зависит от кодировки, а шаблоны нет


Хм... Что тут зависит от кодировки ?

char * __cdecl strtok (
        char * string,
        const char * control
        )
#endif  /* _SECURE_VERSION */
{
        unsigned char *str;
        const unsigned char *ctrl = control;

        unsigned char map[32];
        int count;

#ifdef _SECURE_VERSION

        /* validation section */
        _VALIDATE_RETURN(context != NULL, EINVAL, NULL);
        _VALIDATE_RETURN(string != NULL || *context != NULL, EINVAL, NULL);
        _VALIDATE_RETURN(control != NULL, EINVAL, NULL);

        /* no static storage is needed for the secure version */

#else  /* _SECURE_VERSION */

        _ptiddata ptd = _getptd();

#endif  /* _SECURE_VERSION */

        /* Clear control map */
        for (count = 0; count < 32; count++)
                map[count] = 0;

        /* Set bits in delimiter table */
        do {
                map[*ctrl >> 3] |= (1 << (*ctrl & 7));
        } while (*ctrl++);

        /* Initialize str */

        /* If string is NULL, set str to the saved
         * pointer (i.e., continue breaking tokens out of the string
         * from the last strtok call) */
        if (string)
                str = string;
        else
                str = _TOKEN;

        /* Find beginning of token (skip over leading delimiters). Note that
         * there is no token iff this loop sets str to point to the terminal
         * null (*str == '\0') */
        while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
                str++;

        string = str;

        /* Find the end of the token. If it is not the end of the string,
         * put a null there. */
        for ( ; *str ; str++ )
                if ( map[*str >> 3] & (1 << (*str & 7)) ) {
                        *str++ = '\0';
                        break;
                }

        /* Update nextoken (or the corresponding field in the per-thread data
         * structure */
        _TOKEN = str;

        /* Determine if a token has been found. */
        if ( string == str )
                return NULL;
        else
                return string;
}



Н>впрочем, собственная ее реализация для шаблона — копеечный вопрос
With best regards
Pavel Dvorkin
Re[7]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 08:47
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Няшка, Вы писали:



Н>>эта функция зависит от кодировки, а шаблоны нет


PD>Хм... Что тут зависит от кодировки ?


Пихните туда UTF — узнаете
80% людей оценивают свое мастерство выше среднего...
Re[5]: Медленный C++
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 27.05.14 08:58
Оценка:
Здравствуйте, smeeld, Вы писали:

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

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

really? питонокод в данном примере довольно туп и идиоматичен
Re[8]: Медленный C++
От: smeeld  
Дата: 27.05.14 09:11
Оценка:
Здравствуйте, Няшка, Вы писали:

Н>Пихните туда UTF — узнаете


Если доработать так, чтоб '\0' не вставлялось, то и utf переварит спокойно-
сравнение ведь побайтное, и неважно что означают эти байты и совокупности из них.
Re[2]: Медленный C++
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 27.05.14 09:18
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>В версии на C++ аллоцируется много мутабельных строк, в то время как в версии на Python строки иммутабельные, для них просто берётся view.

EP>Плюс, у тебя vector аллоцируется каждый раз создаётся заново, а нужно создать его только один раз и переиспользовать его capacity многократно.

Может быть дело еще и в ifstream. Возможно там буферизация реализована хуже чем в питоне (я не проверял).
Re[6]: Медленный C++
От: smeeld  
Дата: 27.05.14 09:33
Оценка:
Здравствуйте, Няшка, Вы писали:

Н>1. Vector — это шаблон


Vector-это контейнер, обобщённый с помощью шаблонов.

Н>2. Рост которого не всегда сопровождается копированием данных — зависит от реализации и аллокатора

У аллокатора только спрашивают указатель, вызывая его allocate, и ему же велят удалять кусок памяти, вызывая его deallocate. Всё.
С самим данныи контейнер делает что ему хочется. И vector, если вновь помещаемые данные превысят имеющийся объём,
вызывает allocate, копирует в новый буфер предыдущий, и вызывает deallocate предыдущему.

Н>3. Если Вы работаете не только с однобайтовым английским языком, то создать хороший текстовый парсер не на шаблонах будет тугой задачей

Н>4. Читать весь файл csv в память и разбивать терминатором, чтобы потом копировать memcpy/strcpy — это бредовая идея для домашнего программирования.
Н> Подумайте внимательно, как будет работать Ваше решение на большом файле?..

А никто и не спорит про большие файлы. Большие файлы никто копировать в ram и не собирался, не надо капитанить.
Приведённый в треде пример с маппингом и двумя указателями известен всем страждущим. Только в контексте задачи TC,
всё это тут накручивать будет лишним. Речь изначально велась об ускорении работы приложения.
И парсинг побайтовым сравнением можно проводить на тексте любой кодировки. Шаблон понадобится для определения конкретной специфики
сравнения при поиске, и выдачи результатов. И всё спокойно проделывается и без задействования контейнеров.

H> а на сервере в несколько потоков?..

Н> Какая будет стратегия на ошибки выделения памяти??? Как будете отдавать процессорное время другим задачам??? Куча не нужных проблем появится.

И чем здесь именно контейнеры на шаблонах обеспечат threading safe? Разруливать всё придётся так же, как и без использования контейнеров.
Re[8]: Медленный C++
От: Pavel Dvorkin Россия  
Дата: 27.05.14 10:26
Оценка:
Здравствуйте, Няшка, Вы писали:


PD>>Хм... Что тут зависит от кодировки ?


Н>Пихните туда UTF — узнаете


Вообще-то strtok, как и string.h вообще, не предназначена для того, чтобы работать с UTF. Если UTF сунуть в обычную strlen, то результат, мягко говоря, будет тоже далек от истины. Да и вообще кроме strcpy/strcat мало что будет работать.
With best regards
Pavel Dvorkin
Re[8]: Медленный C++
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 27.05.14 10:40
Оценка:
Здравствуйте, Няшка, Вы писали:

S>>всё это тут накручивать будет лишним. Речь изначально велась об ускорении работы приложения.

Н>Ускорение на 5 кб не имеет значения, любой вариант сгодится. Хоть на регулярках... затраты на современной технике будут копеешные.

Изначально как раз и говорится, что затраты далеко не копеечные.

Н>Скорость актуальна в бигдата и высоконагруженном программировании.

Н>Сколько миллисекунд там эксель непосредственно будет читать табличку из csv — всем насрать.

А эксель на атомном планшете? А эксель на мобилке? Поставим туда ксеон для ускорения?
Re[9]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 11:01
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Здравствуйте, Няшка, Вы писали:


S>>>всё это тут накручивать будет лишним. Речь изначально велась об ускорении работы приложения.

Н>>Ускорение на 5 кб не имеет значения, любой вариант сгодится. Хоть на регулярках... затраты на современной технике будут копеешные.

N>Изначально как раз и говорится, что затраты далеко не копеечные.


А какого размера файл изначально? Явно не 5 кб.

Н>>Скорость актуальна в бигдата и высоконагруженном программировании.

Н>>Сколько миллисекунд там эксель непосредственно будет читать табличку из csv — всем насрать.

N>А эксель на атомном планшете? А эксель на мобилке? Поставим туда ксеон для ускорения?


И там, и там есть. Работают и поверьте никто там над скоростью чтения таблиц голову не ломал, т.к. эксель не предполагает работу с большими таблицами.
80% людей оценивают свое мастерство выше среднего...
Re[9]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 11:05
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, Няшка, Вы писали:



PD>>>Хм... Что тут зависит от кодировки ?


Н>>Пихните туда UTF — узнаете


PD>Вообще-то strtok, как и string.h вообще, не предназначена для того, чтобы работать с UTF. Если UTF сунуть в обычную strlen, то результат, мягко говоря, будет тоже далек от истины. Да и вообще кроме strcpy/strcat мало что будет работать.


Вообще то предназначены, т.к. есть версии этих ф-ций для mb и utf-16 строк.
Просто на шаблонах легко накатать универсальную функцию, которая будет работать не зависимо от типа кодировки.
80% людей оценивают свое мастерство выше среднего...
Re[10]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 11:09
Оценка:
Здравствуйте, Няшка, Вы писали:

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


N>>Здравствуйте, Няшка, Вы писали:


S>>>>всё это тут накручивать будет лишним. Речь изначально велась об ускорении работы приложения.

Н>>>Ускорение на 5 кб не имеет значения, любой вариант сгодится. Хоть на регулярках... затраты на современной технике будут копеешные.

N>>Изначально как раз и говорится, что затраты далеко не копеечные.


Н>А какого размера файл изначально? Явно не 5 кб.


Н>>>Скорость актуальна в бигдата и высоконагруженном программировании.

Н>>>Сколько миллисекунд там эксель непосредственно будет читать табличку из csv — всем насрать.

N>>А эксель на атомном планшете? А эксель на мобилке? Поставим туда ксеон для ускорения?


Н>И там, и там есть. Работают и поверьте никто там над скоростью чтения таблиц голову не ломал, т.к. эксель не предполагает работу с большими таблицами.


Собсно, разговор как-то не туда завернул... Я хотел сказать, что местячковые, типа загнать всё в память, решения это не правильно.
Они дают результат на тестах и локальных задачах, но при переносе на реальные нагрузки дадут больше проблем.
80% людей оценивают свое мастерство выше среднего...
Re[3]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 27.05.14 11:10
Оценка:
Здравствуйте, Lazin, Вы писали:

EP>>В версии на C++ аллоцируется много мутабельных строк, в то время как в версии на Python строки иммутабельные, для них просто берётся view.

EP>>Плюс, у тебя vector аллоцируется каждый раз создаётся заново, а нужно создать его только один раз и переиспользовать его capacity многократно.
L>Может быть дело еще и в ifstream. Возможно там буферизация реализована хуже чем в питоне (я не проверял).

Возможно, но я думаю вряд ли это решающий фактор (это надо было бы очень сильно накосячить) — потому что целый набор аллокаций стандартным аллокатором на каждую итерацию это реально медленно.
Это, кстати, подтверждается новым примером ТС
Автор: anatoly1
Дата: 27.05.14
— избавившись от аллокаций на каждой итерации, он ускорился на порядок.
Re[10]: Медленный C++
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 27.05.14 11:11
Оценка:
Здравствуйте, Няшка, Вы писали:

N>>А эксель на атомном планшете? А эксель на мобилке? Поставим туда ксеон для ускорения?


Н>И там, и там есть. Работают и поверьте никто там над скоростью чтения таблиц голову не ломал, т.к. эксель не предполагает работу с большими таблицами.


Ну, тогда мне просто остаётся надеяться, что ты не разрабатываешь продукты, которыми я пользуюсь. Удачи в работе!
Re[5]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 27.05.14 11:26
Оценка:
Здравствуйте, anatoly1, Вы писали:

A>В итоге, думаю, остановлюсь на таком варианте:

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

A>    std:string s;
A>    std::vector<std::string> sv(201);
A>    std::stringstream ss;
A>    std::string item;

A>    while ( std::getline(f, s) )
A>    {
A>        ss.clear();
A>        ss.str(s);
A>        for (int i = 0; std::getline(ss, item, ';'); i++)
A>            std::swap(sv[i], item);
A>    }

A>    return 0;
A>}
A>


Это конечно далеко не самый быстрый вариант, но можно и так. Тут два основных момента:
1. swap и item не нужны, можно считывать сразу в sv.
2. Размер вектора .size() нельзя уменьшать, иначе потеряется уже аллоцированная capacity в элементах-строках.
Re[8]: Медленный C++
От: smeeld  
Дата: 27.05.14 11:39
Оценка:
Здравствуйте, Няшка, Вы писали:


Н>если данные не переехали, то их можно и не копировать


Реализация emplace_back от gnu


 template<typename _Tp, typename _Alloc>
89  template<typename... _Args>
90  void
91  vector<_Tp, _Alloc>::
92  emplace_back(_Args&&... __args)
93  {
94  if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
95  {
96  _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
97  std::forward<_Args>(__args)...);
98  ++this->_M_impl._M_finish;
99  }
100  else
101  _M_emplace_back_aux(std::forward<_Args>(__args)...);
102  }
103 #endif
104

template<typename _Tp, typename _Alloc>
402  template<typename... _Args>
403  void
404  vector<_Tp, _Alloc>::
405  _M_emplace_back_aux(_Args&&... __args)
406  {
407  const size_type __len =
408  _M_check_len(size_type(1), "vector::_M_emplace_back_aux");
409  pointer __new_start(this->_M_allocate(__len));
410  pointer __new_finish(__new_start);
411  __try
412  {
413  _Alloc_traits::construct(this->_M_impl, __new_start + size(),
414  std::forward<_Args>(__args)...);
415  __new_finish = 0;
416 
417  __new_finish
418  = std::__uninitialized_move_if_noexcept_a
419  (this->_M_impl._M_start, this->_M_impl._M_finish,
420  __new_start, _M_get_Tp_allocator());
421 
422  ++__new_finish;
423  }
424  __catch(...)
425  {
426  if (!__new_finish)
427  _Alloc_traits::destroy(this->_M_impl, __new_start + size());
428  else
429  std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
430  _M_deallocate(__new_start, __len);
431  __throw_exception_again;
432  }
433  std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
434  _M_get_Tp_allocator());
435  _M_deallocate(this->_M_impl._M_start,
436  this->_M_impl._M_end_of_storage
437  - this->_M_impl._M_start);
438  this->_M_impl._M_start = __new_start;
439  this->_M_impl._M_finish = __new_finish;
440  this->_M_impl._M_end_of_storage = __new_start + __len;
441  }
442 #endif
443


__uninitialized_move_if_noexcept_a(_InputIterator __first,
295  _InputIterator __last,
296  _ForwardIterator __result,
297  _Allocator& __alloc)
298  {
299  return std::__uninitialized_copy_a
300  (_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first),
301  _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc);
302  }
303


template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
275  inline _ForwardIterator
276  __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
277  _ForwardIterator __result, allocator<_Tp>&)
278  { return std::uninitialized_copy(__first, __last, __result); }
279



 inline _ForwardIterator
107  uninitialized_copy(_InputIterator __first, _InputIterator __last,
108  _ForwardIterator __result)
109  {
110  typedef typename iterator_traits<_InputIterator>::value_type
111  _ValueType1;
112  typedef typename iterator_traits<_ForwardIterator>::value_type
113  _ValueType2;
114 #if __cplusplus < 201103L
115  const bool __assignable = true;
116 #else
117  // trivial types can have deleted assignment
118  typedef typename iterator_traits<_InputIterator>::reference _RefType;
119  const bool __assignable = is_assignable<_ValueType1, _RefType>::value;
120 #endif
121 
122  return std::__uninitialized_copy<__is_trivial(_ValueType1)
123  && __is_trivial(_ValueType2)
124  && __assignable>::
125  __uninit_copy(__first, __last, __result);
126  }
127



template<bool _TrivialValueTypes>
64  struct __uninitialized_copy
65  {
66  template<typename _InputIterator, typename _ForwardIterator>
67  static _ForwardIterator
68  __uninit_copy(_InputIterator __first, _InputIterator __last,
69  _ForwardIterator __result)
70  {
71  _ForwardIterator __cur = __result;
72  __try
73  {
74  for (; __first != __last; ++__first, ++__cur)
75  std::_Construct(std::__addressof(*__cur), *__first);
76  return __cur;
77  }
78  __catch(...)
79  {
80  std::_Destroy(__result, __cur);
81  __throw_exception_again;
82  }
83  }
84  };
85



 template<typename _T1, typename... _Args>
73  inline void
74  _Construct(_T1* __p, _Args&&... __args)
75  { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
76 #else
77  template<typename _T1, typename _T2>
78  inline void
79  _Construct(_T1* __p, const _T2& __value)
80  {
81  // _GLIBCXX_RESOLVE_LIB_DEFECTS
82  // 402. wrong new expression in [some_]allocator::construct
83  ::new(static_cast<void*>(__p)) _T1(__value);
84  }
85


Как видно, при if (this->_M_impl._M_finish == this->_M_impl._M_end_of_storage) конструируются объекты по новому месту жительства, с переносом состояния.
Старому буферу делается Dealloc
Re[11]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 11:41
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Ну, тогда мне просто остаётся надеяться, что ты не разрабатываешь продукты, которыми я пользуюсь. Удачи в работе!


Перфекционисты такие перфекционисты... Ты тогда вообще массовым ПО не пользуйся. Винду / макьось / линукс выключить не забудь
80% людей оценивают свое мастерство выше среднего...
Re[9]: Медленный C++
От: Няшка Россия  
Дата: 27.05.14 11:52
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Здравствуйте, Няшка, Вы писали:



Н>>если данные не переехали, то их можно и не копировать


S>Реализация emplace_back от gnu


так это ж дефолтный вариант
а выделенное жирным не заметил

Если искать скорость то менеджмент памяти нужен свой и начиная с memcpy все переписывать надобно...
80% людей оценивают свое мастерство выше среднего...
Re[10]: Медленный C++
От: Pavel Dvorkin Россия  
Дата: 27.05.14 12:08
Оценка:
Здравствуйте, Няшка, Вы писали:


Н>Вообще то предназначены, т.к. есть версии этих ф-ций для mb и utf-16 строк.


utf-16 , точно, есть, wcstok, но она опять же работает независимо от кодировки. Для mb — не знаю, по крайней мере в VC++

Н>Просто на шаблонах легко накатать универсальную функцию, которая будет работать не зависимо от типа кодировки.


Медленнее. При любой кодировке, кроме кодировок с одинаковым количеством байт, придется вместо p++ делать нечто более сложное.
With best regards
Pavel Dvorkin
Re[10]: Медленный C++
От: smeeld  
Дата: 27.05.14 12:13
Оценка:
Здравствуйте, Няшка, Вы писали:

Н>так это ж дефолтный вариант

Н>а выделенное жирным не заметил

Н>Если искать скорость то менеджмент памяти нужен


Дык и я о том же, пользуем контейнеры, но правильно.

>свой и начиная с memcpy все переписывать надобно...


memcpy можно оставить как есть.
Re[5]: Медленный C++
От: Evgeny.Panasyuk Россия  
Дата: 27.05.14 12:47
Оценка:
Здравствуйте, Lazin, Вы писали:

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


Выше были ссылки
Автор: Evgeny.Panasyuk
Дата: 26.05.14
на темы, где было сравнение скорости кода разбиения строк C++ vs Python без считывания файлов, полностью в памяти.
Re: Медленный C++
От: __kot2  
Дата: 28.05.14 21:04
Оценка:
Здравствуйте, anatoly1, Вы писали:
A>С++ медленнее питона при парсинге файла.
питон это вообще просто продвинутая версия shell


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

A> std::stringstream ss(s);
A> std::string item;
A> while (std::getline(ss, item, delim)) {
A> elems.push_back(item); МЕДЛЕННО, НУЖНО ПРЕАЛЛОЦИРОВАТЬ БУФЕР
A> }
A> return elems;
A>}

A>std::vector<std::string> split(const std::string &s, char delim) { ВОЗВРАТ МАССИВА ПО ЗНАЧЕНИЮ ЭТО РАЗРУШЕНИЕ СТАРОГО И КОНСТРУИРОВАНИЕ НОВОГО. ОЧЕНЬ МЕДЛЕННО


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

A>В чём может быть причина такой низкой производительности у С++?
обычно, кстати в split нет никакого смысла. мы или что-то ищем конкретное или обрабатываем данные кусками. зачем сплитить массив перед обработкой? Поэтому правильное время работы split в С++ 0 секунд, потому что split там не нужен
Re: Медленный C++
От: Erop Россия  
Дата: 29.05.14 18:56
Оценка:
Здравствуйте, anatoly1, Вы писали:

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

Руки выпрямлять пробовали?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Медленный C++
От: neFormal Россия  
Дата: 30.05.14 09:35
Оценка:
Здравствуйте, __kot2, Вы писали:

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

A>>В чём может быть причина такой низкой производительности у С++?
__>обычно, кстати в split нет никакого смысла. мы или что-то ищем конкретное или обрабатываем данные кусками. зачем сплитить массив перед обработкой? Поэтому правильное время работы split в С++ 0 секунд, потому что split там не нужен

действительно. дело не в плюсах. это задача недостаточно хорошая для них.
...coding for chaos...
Re[3]: Медленный C++
От: __kot2  
Дата: 30.05.14 13:49
Оценка:
Здравствуйте, neFormal, Вы писали:
F>действительно. дело не в плюсах. это задача недостаточно хорошая для них.
эта задача — подготовка данных для обработки инструментами питона. она бессмысленна сама по себе без питона
Re[9]: Медленный C++
От: Философ Ад http://vk.com/id10256428
Дата: 31.05.14 09:32
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Реализация emplace_back от gnu


какой ужас!
Всё сказанное выше — личное мнение, если не указано обратное.
Re[4]: Медленный C++
От: neFormal Россия  
Дата: 01.06.14 21:05
Оценка:
Здравствуйте, __kot2, Вы писали:

F>>действительно. дело не в плюсах. это задача недостаточно хорошая для них.

__>эта задача — подготовка данных для обработки инструментами питона. она бессмысленна сама по себе без питона

split нужен только для питона?
мм, ясно, понятно.
...coding for chaos...
Re[10]: Медленный C++
От: smeeld  
Дата: 04.06.14 16:40
Оценка:
Здравствуйте, Философ, Вы писали:


S>>Реализация emplace_back от gnu


Ф>какой ужас!


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