BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 16.09.06 11:09
Оценка: 2 (1)
Доброго времени суток!

Понадобилось 'посплитить' строки (вообще задача более сложная, но обо всем по порядку), и по совету “мудрых старцев” (которые по новомодной традиции, при каждом чихе отправляют к boost-у) решил потестировать производительность boost::algoruthm:split.

Честно говоря, результаты меня обескуражили…

Код на C++, STL/BOOST:

int r = 0;

vector<string> tokens(5);

for(int i = 0; i < 1000000; i++)
{
    split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
    r += tokens.size();
}


cout << r;

Компилятор: MS VC 8.0
(Релиз)
Опции: /Ox /Oy /I "C:\WORK\boost_1_32_0\\" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_VC80_UPGRADE=0x0700" /D "_MBCS" /FD /EHsc /MT /GS- /Gy /Za /Yu"stdafx.h" /Fp"Release\aaa.pch" /FA /Fa"Release\\" /Fo"Release\\" /Fd"Release\vc80.pdb" /W3 /nologo /c /Wp64 /Zi /TP /errorReport:prompt /D_SECURE_SCL=0

Время работы: 20 секунд. (и это при полной оптимизации и отключенными проверками !?!)

Код на C#, .NET Framework:


int res = 0;
    
for(int i = 0; i < 1000000; i++)
    res += "123 345 asdf 23453 asdfas".Split(' ').Length;
            
Console.WriteLine(res);


Время работы: ~1 сек, при 10^7 итераций ~6 сек.

Я уж тут подумал на кривизну рук, но пишу/писал на C++ достаточно долго, еще с первых GCC, TCPP 1.0, ..., и с оптимизаторами знаком не понаслышке.
[Есть подозрение на неграмотное дефолтовое аллокирование std::vector и std::string.]

Кстати .NET-ий JIT в Release-е особо не 'химичил' с этим кодом, и честно вызывал split для константной строки и далее inline-ил вызов get_Length() на возвращенном строковом массиве;

Пока переписал с исп. strtok и сделал запасной вариант под .NET.
Может есть что сказать приверженцам BOOST-а, и по возможности объяснить где "кривые руки"?
Re: BOOST, .NET, String.Split и производительность…
От: Cyberax Марс  
Дата: 16.09.06 12:26
Оценка:
Denis2005 wrote:
> split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
> r += tokens.size();
А если вот так:
split(tokens, "123 345 asdf 23453 asdfas", is_any_of(' '));

?
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re: BOOST, .NET, String.Split и производительность…
От: achmed Удмуртия https://www.linkedin.com/in/nail-achmedzhanov-9907188/
Дата: 16.09.06 12:31
Оценка:
Здравствуйте, Denis2005, Вы писали:

D>Доброго времени суток!


D>Понадобилось 'посплитить' строки (вообще задача более сложная, но обо всем по порядку), и по совету “мудрых старцев” (которые по новомодной традиции, при каждом чихе отправляют к boost-у) решил потестировать производительность boost::algoruthm:split.


D>Честно говоря, результаты меня обескуражили…

[skipped]

D>[Есть подозрение на неграмотное дефолтовое аллокирование std::vector и std::string.]

так и есть.

Столкнулся с такой же ситуацией, когда пререписывал анализатор логов написанный на perl на C++,
ожидалось, что программа на C++ будет работать быстрее, но perl функция split выигрывала в скорости в
десятки раз!
В итоге переписал с использованием strtok.



D>Может есть что сказать приверженцам BOOST-а, и по возможности объяснить где "кривые руки"?

ИМХО у разработчиков boost::algoruthm:split, если так хотелось STL интерфейс, то можно было
хотя бы std::list использовать вместо std::vector.
Re[2]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 16.09.06 12:31
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Denis2005 wrote:

>> split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
>> r += tokens.size();
C>А если вот так:
C>
C>split(tokens, "123 345 asdf 23453 asdfas", is_any_of(' '));
C>

C>?

Вообще говоря даже не компилируется.
Кстати .NET-ий имеет сигнатуру String.Split(params char[] separators), поэтому от тоже бежит по коллекции сепараторов.
Re[3]: BOOST, .NET, String.Split и производительность…
От: Cyberax Марс  
Дата: 16.09.06 12:38
Оценка:
Denis2005 wrote:
> Вообще говоря даже не компилируется.
> Кстати .NET-ий имеет сигнатуру String.Split(params char[] separators),
> поэтому от тоже бежит по коллекции сепараторов.
Тогда непонятно. В коде split'а при беглом просмотре нет ничего
криминального. Или баг, или какая-то странная фича (типа использования
локалей).
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[4]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 16.09.06 12:43
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Denis2005 wrote:

>> Вообще говоря даже не компилируется.
>> Кстати .NET-ий имеет сигнатуру String.Split(params char[] separators),
>> поэтому от тоже бежит по коллекции сепараторов.
C>Тогда непонятно. В коде split'а при беглом просмотре нет ничего
C>криминального. Или баг, или какая-то странная фича (типа использования
C>локалей).

Врятли. Как я упоминал в первом сообщении подозрение на дуболомность дефолтовых аллокаторов у std::string и std::vector. У вас случаем не 'завалялось' какого-нибудь смарт-аллокатора для STL-контейнеров?
Re[2]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 16.09.06 12:58
Оценка:
A>ИМХО у разработчиков boost::algoruthm:split, если так хотелось STL интерфейс, то можно было
A>хотя бы std::list использовать вместо std::vector.

Использование std::list не привело к повышению производительности. Более того, оно равно в данном случае, т.к. при конструировании задаётся размер контейнера.
Re: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 16.09.06 13:00
Оценка: 1 (1) +1 :)
Здравствуйте, Denis2005, Вы писали:

D>Я уж тут подумал на кривизну рук, но пишу/писал на C++ достаточно долго, еще с первых GCC, TCPP 1.0, ..., и с оптимизаторами знаком не понаслышке.

D>[Есть подозрение на неграмотное дефолтовое аллокирование std::vector и std::string.]

Вряд ли тут аллокаторы помогут. Тут просто сами строки неправильные. Попробуй поискать реализации const_string наверно будет шустрее. Кстати от компилятора сильно зависит, vc71 отработал у меня за 22 секунды, а gcc3.4 за 7.

D>Кстати .NET-ий JIT в Release-е особо не 'химичил' с этим кодом, и честно вызывал split для константной строки и далее inline-ил вызов get_Length() на возвращенном строковом массиве;


D>Пока переписал с исп. strtok и сделал запасной вариант под .NET.

D>Может есть что сказать приверженцам BOOST-а, и по возможности объяснить где "кривые руки"?

на питон переходи, вот такой код:
r = 0
for i in xrange(1000000):
    r += len("123 345 asdf 23453 asdfas".split(" "))
    
print r

отрабатывает за 2.5 секунды
Re[2]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 16.09.06 13:03
Оценка:
FR>на питон переходи, вот такой код:
FR>
FR>r = 0
FR>for i in xrange(1000000):
FR>    r += len("123 345 asdf 23453 asdfas".split(" "))
    
FR>print r 
FR>

FR>отрабатывает за 2.5 секунды

Зачем мне питон, когда такой пример под .NET отрабатывает за 0.6 сек, и код даже короче (на C#_, чем в приведенном примере.
Re[2]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 16.09.06 13:07
Оценка:
FR>отрабатывает за 2.5 секунды

Хоть напиши свой проц/память. У меня AMD Athlon 64 3000 (1.8), память DDR 667 Mhz.
А то непонятно чего с чем меряем.
Re[3]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 16.09.06 13:45
Оценка:
Здравствуйте, Denis2005, Вы писали:

FR>>на питон переходи, вот такой код:

FR>>
FR>>r = 0
FR>>for i in xrange(1000000):
FR>>    r += len("123 345 asdf 23453 asdfas".split(" "))
    
FR>>print r 
FR>>

FR>>отрабатывает за 2.5 секунды

D>Зачем мне питон, когда такой пример под .NET отрабатывает за 0.6 сек, и код даже короче (на C#_, чем в приведенном примере.


Ты там смайлик видел?
У меня шарп за полторы секунды отработал.
А код на шарпе длинее:
using System;

class MainApp 
{
    public static void Main() 
    { 
        int res = 0;
    
        for(int i = 0; i < 1000000; i++)
            res += "123 345 asdf 23453 asdfas".Split(' ').Length;
            
        Console.WriteLine(res);
    }
}


Re[3]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 16.09.06 13:45
Оценка:
Здравствуйте, Denis2005, Вы писали:

FR>>отрабатывает за 2.5 секунды


D>Хоть напиши свой проц/память. У меня AMD Athlon 64 3000 (1.8), память DDR 667 Mhz.

D>А то непонятно чего с чем меряем.

Cel D 2.6 память не знаю какая, но тормозная.
Re[3]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 16.09.06 14:10
Оценка:
Здравствуйте, Denis2005, Вы писали:

кстати профайлер говорит что процентов 20 времени сидит в ntdll.dll на примерно таком коде:

Samples     Address        Code Bytes             Instruction                  Symbol      CPU 0     
10          0x7c902f10     0x 0B C0               or eax,eax                   tan+210     10        
20          0x7c902f12     0x 74 0C               jz $+0eh (0x7c902f20)        tan+212     20        
29          0x7c902f14     0x 8D 4A FF            lea ecx,[edx-01h]            tan+214     29        
14          0x7c902f17     0x 8B 18               mov ebx,[eax]                tan+217     14        
            0x7c902f19     0x F0 0F C7 4D 00      lock cmpxchg8b [ebp+00h]                           
2842        0x7c902f1e     0x 75 F0               jnz $-0eh (0x7c902f10)       tan+224     2842


Похоже синхронизация неплохо отъедает производительность. Вообще в ntdll.dll сидит 49% времени в основном в строковых функциях и кусочках похожих тому что выше.
Re[2]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 16.09.06 14:17
Оценка:
Здравствуйте, FR, Вы писали:

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


D>>Я уж тут подумал на кривизну рук, но пишу/писал на C++ достаточно долго, еще с первых GCC, TCPP 1.0, ..., и с оптимизаторами знаком не понаслышке.

D>>[Есть подозрение на неграмотное дефолтовое аллокирование std::vector и std::string.]

FR>Вряд ли тут аллокаторы помогут. Тут просто сами строки неправильные. Попробуй поискать реализации const_string наверно будет шустрее.


Даже если сделать такой неправельный const_string (заглушка, чисто для теста):


struct bad_const_str
{
    const char *ptr;

    const_str()
    {
        ptr = NULL;
    }

    const_str(const char *pa, const char *pb)
    {
        ptr = pa;
    }
};


Производительность возрасла всего на 1 секунду, иными словами проблема даже не в тормознутости std::string (как ни странно).
Re: [Benchmark] DMD быстрее всех
От: Андрей Хропов Россия  
Дата: 16.09.06 17:19
Оценка: 3 (1) :))
Здравствуйте, Denis2005, Вы писали:

Обожаю бенчмарки

Померил с использованием таймеров (чтобы не учитывать JIT компиляцию)
Вот результаты (усреднены по 10 запускам)
(Athlon XP 1700+ @ 1.5 GHZ + 512Mb DDR266)
:

1) DMD — 0.775 сек
2) GDC — 0.905 сек
3) С#/Nemerle — 1.1 сек
4) Python — 3.48 сек
5) Python+Psyco — 4.12 (не ускорил!)
6) GCC + Boost — 22.5 сек
7) MS VC++ + Boost — 35 сек

Компиляторы:
DMD — Digital Mars D 0.166
GDC — GNU D Compiler 0.19 для MinGW 3.4.2
C# — MS C# Compiler в составе VS2005
Nemerle — 0.9.3.99(svn) (от 12.09)
Python 2.4.2
Python 2.4.2 + Psyco 1.5
GCC — GCC 3.4.2 (в виде MinGW) + Boost 1.33.1
MS VC++ — MS C++ Compiler в составе VS2005 + Boost 1.33.1

Опции:
dmd -O -release -inline -ofsplit-d.exe split.d
gdc split.d -O99 -osplit-gdc.exe
csc /o+ /out:split-cs.exe split.cs
ncc -out:split-n.exe split.n
g++ split.cpp -If:/boost -O99 -osplit-gpp
сl split.cpp /Ox /Oi /Ot /GT /GL /I "F:\boost" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D_SECURE_SCL=0 /D "_UNICODE" /D "UNICODE" /FD /EHsc /MD /GS- /Fo"Release\\" /Fd"Release\vc80.pdb" /W3 /nologo /c /Wp64 /Zi /TP /errorReport:prompt
/Fesplit-cpp.exe


Исходники:

D:
import std.stdio, std.string, std.perf;

void main()
{
  auto t = new HighPerformanceCounter();
    
  t.start();
  
  uint res = 0;

    for(uint i = 0; i < 1000000; ++i)
    res += split("123 345 asdf 23453 asdfas"," ").length;
                
  t.stop();
    
  writefln("res is ", res ," ", t.milliseconds()," ms elapsed.");
}


C#:

using System;
using System.Diagnostics;

class Runner
{
  public static void Main()
  {
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();
    
    int res = 0;
  
    for(uint i = 0; i < 1000000; ++i)
      res += "123 345 asdf 23453 asdfas".Split(' ').Length;
      
    stopwatch.Stop();
          
    Console.WriteLine("res is {0}, {1} elapsed",
                      res, stopwatch.Elapsed);
  }
}


Nemerle:

using System.Console;
using System.Diagnostics;

def stopwatch = Stopwatch();
stopwatch.Start();
  
mutable res = 0;

repeat(1000000)
  res += "123 345 asdf 23453 asdfas".Split(' ').Length;
  
stopwatch.Stop();
      
WriteLine($"res is $res, $(stopwatch.Elapsed) elapsed");


Python:

import time

start = time.clock()
      
res = 0
for i in xrange(1000000):
    res += len("123 345 asdf 23453 asdfas".split(" "))
    
finish = time.clock()    
    
print 'res is %s, %f sec elapsed' % ( res, finish - start )


Python+Psyco:

import time
import psyco
psyco.full()

start = time.clock()
      
res = 0
for i in xrange(1000000):
    res += len("123 345 asdf 23453 asdfas".split(" "))
    
finish = time.clock()    
    
print 'res is %s, %f sec elapsed' % ( res, finish - start )


С++:

#include <vector>
#include <string>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>

#include <windows.h> // for GetTickCount

using namespace std;
using namespace boost::algorithm;

int main()
{
  DWORD start = GetTickCount();
    
  int res = 0;
  for(int i = 0; i < 1000000; i++)
  {
    // так корректней сравнивать, ведь в др программах мы размер не указывали
    // + по моим тестам почти не повлияло на скорость
    vector<string> tokens; 
    split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
    res += tokens.size();
  }

  DWORD stop = GetTickCount();

  cout << "res is " << res << ',' << stop - start << " ms elapsed\n";
  
  return 0;
}
Re[2]: [Benchmark] DMD быстрее всех
От: CreatorCray  
Дата: 16.09.06 18:08
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>6) GCC + Boost — 22.5 сек

АХ>7) MS VC++ + Boost — 35 сек
А добавьте ка пунктик C++ + самописный split
Бо что то мне кажется что тут надо в "консерватории" что то подправить
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 16.09.06 18:14
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>5) Python+Psyco — 4.12 (не ускорил!)


Psyco не любит когда код в основном теле модуля надо его в функцию засунуть, тогда чуть ускорит:
from time import clock
import psyco
psyco.full()

def run():
    res = 0
    for i in xrange(1000000):
        res += len("123 345 asdf 23453 asdfas".split(" "))
    return res


start = clock()
res = run()   
finish = clock()    
    
print 'res is %s, %f sec elapsed' % ( res, finish - start )

У меня python 2.4.1 ~ 2.6 сек.
python 2.4.1 + psyco 1.5.0 ~ 1.8 сек.
IronPython-1.0 ~ 3.0 сек.
Re[3]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 16.09.06 18:55
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, Андрей Хропов, Вы писали:


АХ>>6) GCC + Boost — 22.5 сек

АХ>>7) MS VC++ + Boost — 35 сек
CC>А добавьте ка пунктик C++ + самописный split
CC>Бо что то мне кажется что тут надо в "консерватории" что то подправить

лучше держи на очень не шустром интерпретаторе:
REBOL [] res: 0
probe loop 1000000 [res: res + length? parse "123 345 asdf 23453 asdfas" { }]

3.6 секунды
Re[4]: [Benchmark] DMD быстрее всех
От: CreatorCray  
Дата: 16.09.06 19:07
Оценка:
Здравствуйте, FR, Вы писали:

CC>>А добавьте ка пунктик C++ + самописный split

CC>>Бо что то мне кажется что тут надо в "консерватории" что то подправить
FR>лучше держи на очень не шустром интерпретаторе:
не, сравнение агоритма boost с алгоримом встроенным в интерпретатор меня не очень то интересует. Больше все таки интересует насколько хреново реализовали split в самом бусте.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: [Benchmark] DMD быстрее всех
От: Denis2005 Россия  
Дата: 16.09.06 19:38
Оценка:
CC>А добавьте ка пунктик C++ + самописный split

Есть такой, итеративно strtok-ом собирает в vector<string> с заранее заданной размерностью.
По результатам производительность чуть ниже .NET-кого варианта.
Вообщем в BOOST-е, чего-то бравые парни перемудрили,
и нулевыми издержками в данном случае совсем не попахивает.
Надеюсь в C++0x это безобразие полностью не попадет,
или если попадет, то в более продуманном варианте.
Re[4]: BOOST, .NET, String.Split и производительность…
От: McSeem2 США http://www.antigrain.com
Дата: 16.09.06 20:07
Оценка: -1
Здравствуйте, FR, Вы писали:

FR>кстати профайлер говорит что процентов 20 времени сидит в ntdll.dll на примерно таком коде:


[. . .]

FR>Похоже синхронизация неплохо отъедает производительность. Вообще в ntdll.dll сидит 49% времени в основном в строковых функциях и кусочках похожих тому что выше.


Во-во. Я тоже с этим сталкивался — isspace на винде отъедал больше половины всего времени работы парсера. Так что язык здесь ни при чем вообще.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: [Benchmark] DMD быстрее всех updated
От: Андрей Хропов Россия  
Дата: 16.09.06 20:28
Оценка:
Здравствуйте, FR, Вы писали:

FR>Здравствуйте, Андрей Хропов, Вы писали:


АХ>>5) Python+Psyco — 4.12 (не ускорил!)


FR>Psyco не любит когда код в основном теле модуля надо его в функцию засунуть, тогда чуть ускорит:


Ммм, да, почесав затылок, вспомнил что он вроде пофункционально оптимизирует.
И у меня теперь ускорил даже совсем не чуть а почти в 2 раза
Теперь обновленная таблица с твоим вариантом выглядит как:

(Athlon XP 1700+ @ 1.5 GHZ + 512Mb DDR266)
:

1) DMD — 0.775 сек
2) GDC — 0.905 сек
3) С#/Nemerle — 1.1 сек
4) Python+Psyco — 2 сек
5) Python — 3.48 сек
6) GCC + Boost — 22.5 сек
7) MS VC++ + Boost — 35 сек

Интересно, а что будет если использовать внутри цикла в C++ вариант python через boost.python .
Поможет ли это реанимировать boost (в смысле будет ли быстрее чем 35 сек)?
Re: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.09.06 20:34
Оценка: :))
Здравствуйте, Denis2005, Вы писали:

D>Честно говоря, результаты меня обескуражили…


D>Время работы: 20 секунд. (и это при полной оптимизации и отключенными проверками !?!)

D>Может есть что сказать приверженцам BOOST-а, и по возможности объяснить где "кривые руки"?

По моему беглому взгляду на реализацию split-а показалось, что дело в реализации is_any_of. В частности, в том, что при каждом обращении к split объект-предикат, который скрывается за is_any_of конструируется заново. И более того, где-то там внутри этот предикат передается в подчиненные функции и сохраняется во вспомогательных объектах по значению.

Образно говоря, происходит что-то похожее на нижеследующий код:
#include <algorithm>
#include <string>
#include <set>

template< class Finder >
class Finder_Holder
    {
    private :
        Finder finder_;

    public :
        Finder_Holder( Finder finder )
            :    finder_( finder )
            {}

        void
        operator()( char c ) { finder_( c ); }
    };

class Finder
    {
    private :
        std::set< char >    tokens_;

    public :
        Finder( std::string tokens )
            :    tokens_( tokens.begin(), tokens.end() )
            {}

        bool
        operator()( char c )
            {
                return tokens_.end() == tokens_.find( c );
            }
    };

Finder_Holder< Finder >
is_any_of( const std::string & value )
    {
        return Finder_Holder< Finder >( Finder( value ) );
    }

template< class Predicate >
void
do_something( const std::string & s, Predicate pred )
    {
        std::for_each( s.begin(), s.end(), pred );
    }

void
test()
    {
        for( int i = 0; i != 1000000; ++i )
            do_something( "123 345 asdf 23453 asdfas", is_any_of( " " ) );
    }

int
main()
    {
        test();

        return 0;
    }


Обратите внимание на то, что в do_something объект pred передается по значению. А is_any_of возвращает объект Finder_Holder так же по значению.
В результате этот код у меня работает за время:
bash-3.1$ time t1.exe

real    0m5.172s
user    0m0.031s
sys     0m0.000s

(cl -O2 -EHsc)

Если же сделать так. чтобы по максимуму сохранять ссылки на объекты:
#include <algorithm>
#include <string>
#include <set>

template< class Finder >
class Finder_Holder
    {
    private :
        const Finder & finder_;

    public :
        Finder_Holder( const Finder & finder )
            :    finder_( finder )
            {}

        void
        operator()( char c ) const { finder_( c ); }
    };

class Finder
    {
    private :
        std::set< char >    tokens_;

    public :
        Finder( const std::string & tokens )
            :    tokens_( tokens.begin(), tokens.end() )
            {}

        bool
        operator()( char c ) const
            {
                return tokens_.end() == tokens_.find( c );
            }
    };

Finder_Holder< Finder >
is_any_of( const std::string & value )
    {
        return Finder_Holder< Finder >( Finder( value ) );
    }

template< class Predicate >
void
do_something( const std::string & s, const Predicate & pred )
    {
        std::for_each( s.begin(), s.end(), pred );
    }

void
test()
    {
        const Finder_Holder< Finder > pred = is_any_of( " " );
        for( int i = 0; i != 1000000; ++i )
            do_something( "123 345 asdf 23453 asdfas", pred );
    }

int
main()
    {
        test();

        return 0;
    }

то получается время:
bash-3.1$ time t2.exe

real    0m0.406s
user    0m0.015s
sys     0m0.015s

при тех же опциях компилятора.

Очень похоже, что именно из-за проблем с is_any_of и наблюдаются тормоза в твоем случае.
А любителям boost-ов я бы напомнил: KISS


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: [Benchmark] DMD быстрее всех
От: Андрей Хропов Россия  
Дата: 16.09.06 20:40
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, Андрей Хропов, Вы писали:


АХ>>6) GCC + Boost — 22.5 сек

АХ>>7) MS VC++ + Boost — 35 сек
CC>А добавьте ка пунктик C++ + самописный split
CC>Бо что то мне кажется что тут надо в "консерватории" что то подправить

Странно почему boost себя так плохо показывает.
Его вроде далеко не новички пишут, да и peer review у них вроде есть.
Надо идти к ним на форум ругаться
А то прям стыд и срам какой-то.

А так напиши универсальный split и запости сюда результаты.
Re[2]: BOOST, .NET, String.Split и производительность…
От: Андрей Хропов Россия  
Дата: 16.09.06 20:58
Оценка:
Здравствуйте, eao197, Вы писали:

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


D>>Честно говоря, результаты меня обескуражили…


D>>Время работы: 20 секунд. (и это при полной оптимизации и отключенными проверками !?!)

D>>Может есть что сказать приверженцам BOOST-а, и по возможности объяснить где "кривые руки"?

E>По моему беглому взгляду на реализацию split-а показалось, что дело в реализации is_any_of. В частности, в том, что при каждом обращении к split объект-предикат, который скрывается за is_any_of конструируется заново. И более того, где-то там внутри этот предикат передается в подчиненные функции и сохраняется во вспомогательных объектах по значению.


Так все оптимизации выкручены по максимуму. Значение аргумента is_any_of известно во время компиляции.
Все это должно заинлайниться до констант. Или этого не происходит, почему?

P.S. Я смотрю у тебя Linux или BSD. Если не лень и стоят компиляторы других языков, то прогони проги из моего бенчмарка.
Наблюдаются ли те же временные пропорции?
Re[3]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.09.06 21:28
Оценка: +1
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Так все оптимизации выкручены по максимуму. Значение аргумента is_any_of известно во время компиляции.

АХ>Все это должно заинлайниться до констант. Или этого не происходит, почему?

Судя по всему не происходит. Да и с чего бы происходить, если аргумент is_any_of неявно приводится к std::string (который может требовать у себя в конструкторе обращения к new), затем is_any_of возвращает какой-то объект, в котором еще что-то требует обращения к new, затем это еще к чему-то обращается и т.д. и т.п. Если есть желание, можешь сам расписать на бумаге цепочку вызовов внутри split-а, посмотри, в какие дебри это тебя заведет.

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

АХ>P.S. Я смотрю у тебя Linux или BSD. Если не лень и стоят компиляторы других языков, то прогони проги из моего бенчмарка.


У меня WinXP + Cygwin. Да и лень


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.06 00:22
Оценка: -5 :))
Здравствуйте, Denis2005, Вы писали:

D>Зачем мне питон, когда такой пример под .NET отрабатывает за 0.6 сек, и код даже короче (на C#_, чем в приведенном примере.


От это ты зря здесь сказал. Сейчас подтянутся eao197 с ГВ и после короткой но продолжительной бесебы в тебе найдут массу недостатков.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.06 00:22
Оценка: -3
Здравствуйте, McSeem2, Вы писали:

MS>Во-во. Я тоже с этим сталкивался — isspace на винде отъедал больше половины всего времени работы парсера. Так что язык здесь ни при чем вообще.


Естественно. Причем библиотеки. Только вот когда любители С++ начинают пенесометрией по скорости заниматься они как-то забывают, что в программе многое от библиотек зависит и все время приводят вручную оптимизированный код. А пожизни в программах может быть уйма вот таких проблемочек которые в купе вырастают в торомоза. Так что лучший друг производительности по прежнему не С++, а профайлер.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: [Benchmark] DMD быстрее всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.06 00:22
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

А где же Оберон?
А то прийдет сами знаете кто и ему даже про синтксический оверхэд будет невозможно поговорить! А вать такй случай предствылч:

АХ>
АХ>#include <vector>
АХ>#include <string>
АХ>#include <iostream>
АХ>#include <boost/algorithm/string/split.hpp>
АХ>#include <boost/algorithm/string/classification.hpp>

АХ>#include <windows.h> // for GetTickCount

АХ>using namespace std;
АХ>using namespace boost::algorithm;

АХ>int main()
АХ>{
АХ>  DWORD start = GetTickCount();
    
АХ>  int res = 0;
АХ>  for(int i = 0; i < 1000000; i++)
АХ>  {
АХ>    // так корректней сравнивать, ведь в др программах мы размер не указывали
АХ>    // + по моим тестам почти не повлияло на скорость
АХ>    vector<string> tokens; 
АХ>    split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
АХ>    res += tokens.size();
АХ>  }

АХ>  DWORD stop = GetTickCount();

АХ>  cout << "res is " << res << ',' << stop - start << " ms elapsed\n";
  
АХ>  return 0;
АХ>}
АХ>
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [Benchmark] DMD быстрее всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.06 00:22
Оценка: +3 :))) :))) :)))
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Странно почему boost себя так плохо показывает.

АХ>Его вроде далеко не новички пишут, да и peer review у них вроде есть.

У них задачи другие. Они мозг тренируют.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.06 00:22
Оценка:
Здравствуйте, eao197, Вы писали:

E>А любителям boost-ов я бы напомнил: KISS


Ты прочти свое сообщение и подумай кому бы еще о KISS напомнить.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [Benchmark] DMD быстрее всех
От: CreatorCray  
Дата: 17.09.06 01:22
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

CC>>А добавьте ка пунктик C++ + самописный split

CC>>Бо что то мне кажется что тут надо в "консерватории" что то подправить
АХ>Странно почему boost себя так плохо показывает.
Это у них бывает. Похоже народ о производительности не очень то задумывается...
АХ>А так напиши универсальный split и запости сюда результаты.
Появится время и острая потребность — займусь
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: BOOST, .NET, String.Split и производительность…
От: CreatorCray  
Дата: 17.09.06 01:22
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Естественно. Причем библиотеки.


VD>Только вот когда любители С++ начинают пенесометрией по скорости заниматься они как-то забывают, что в программе многое от библиотек зависит и все время приводят вручную оптимизированный код.

Дык библиотеки то в первую очередь надо оптимизировать. К примеру большую часть CRT можно (и нужно) переписывать с нуля с учетом производительности. Потому как тормозная она...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 17.09.06 05:17
Оценка:
Здравствуйте, VladD2, Вы писали:

E>>А любителям boost-ов я бы напомнил: KISS


VD>Ты прочти свое сообщение и подумай кому бы еще о KISS напомнить.


И кому?

Если хочешь позлословить по поводу приведенного мной кода, то это всего лишь популярное изложение части деталей реализации boost::algorithms::is_any_of. К реализации которого я не имею никакого отношения.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[5]: BOOST, .NET, String.Split и производительность…
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 17.09.06 07:03
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Так что язык здесь ни при чем вообще.


C# вроде как под той же виндой тестируют с той же самой ntdll.dll
... << RSDN@Home 1.2.0 alpha rev. 654>>
Re[4]: [Benchmark] DMD быстрее всех updated
От: FR  
Дата: 17.09.06 07:54
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:


АХ>Интересно, а что будет если использовать внутри цикла в C++ вариант python через boost.python .

АХ>Поможет ли это реанимировать boost (в смысле будет ли быстрее чем 35 сек)?

Мерять надо, в принципе накладные расходы на вызов (python — C++) относительно небольшие (у меня миллион вызовов примерно секунда), так что скорее всего будет быстрее
Re[2]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 17.09.06 07:54
Оценка:
Здравствуйте, eao197, Вы писали:

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


D>>Честно говоря, результаты меня обескуражили…


D>>Время работы: 20 секунд. (и это при полной оптимизации и отключенными проверками !?!)

D>>Может есть что сказать приверженцам BOOST-а, и по возможности объяснить где "кривые руки"?

E>По моему беглому взгляду на реализацию split-а показалось, что дело в реализации is_any_of. В частности, в том, что при каждом обращении к split объект-предикат, который скрывается за is_any_of конструируется заново. И более того, где-то там внутри этот предикат передается в подчиненные функции и сохраняется во вспомогательных объектах по значению.



Попробовал с самописным предикатом:
#include <iostream>
#include <vector>
#include <boost/algorithm/string/split.hpp>

using namespace std;
using boost::algorithm::split;

inline bool is_space(char c)
{
return c == ' ';
}

int main(int argc, char *argv[])
{
int r = 0;

vector<string> tokens(5);

for(int i = 0; i < 1000000; i++)
{
    split(tokens, "123 345 asdf 23453 asdfas", is_space);
    r += tokens.size();
}

return 0;
}

результаты(первый с boost::algorithm::is_any_of)
vc71 | 33.2 и 9.7
vc71 + STLport-4.6 | 24.9 и 9.9
gcc3.2 | 10.8 и 3.5

gcc догнал скрипты
Re[2]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 17.09.06 08:27
Оценка:
Здравствуйте, eao197, Вы писали:

E>По моему беглому взгляду на реализацию split-а показалось, что дело в реализации is_any_of.


Даже если написать примитивный предикат:

bool char_is_space(const char c)
{
return c == ' ';
}

то заместо ~20 сек., получаем ~5 сек., на VC++ 8.0.
Re[3]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 17.09.06 09:26
Оценка: 2 (1)
Здравствуйте, Denis2005, Вы писали:

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


E>>По моему беглому взгляду на реализацию split-а показалось, что дело в реализации is_any_of.


D>Даже если написать примитивный предикат:


D>bool char_is_space(const char c)

D>{
D> return c == ' ';
D>}

D>то заместо ~20 сек., получаем ~5 сек., на VC++ 8.0.


угу в бусте явно что-то перемудрили, даже вот такой кошмар:
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;

int main(int argc, char *argv[])
{
int r = 0;
vector<string> tokens(5);

for(int i = 0; i < 1000000; i++)
{
    istringstream istr("123 345 asdf 23453 asdfas");
    string word;
    int k = 0;
    
    while(!istr.eof())
    {
    istr >> word;
    tokens[k++] = word;
    }
    
    r += k;
}

cout << r << endl;

return 0;
}

работает в 8 раз быстрее чем бустовский вариант (vc71 + STLport-4.6)
Re[4]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 17.09.06 10:08
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Странно почему boost себя так плохо показывает.

АХ>Его вроде далеко не новички пишут, да и peer review у них вроде есть.
АХ>Надо идти к ним на форум ругаться
АХ>А то прям стыд и срам какой-то.

АХ>А так напиши универсальный split и запости сюда результаты.


Вот такой не универсальный и наколенный вариант
#include <iostream>
#include <string>
#include <vector>

using namespace std;

void split(vector<string> &out, const char *text, bool (*pred)(char))
{
out.erase(out.begin(), out.end());
const char *begin_word = text;
for(; *text; ++text)
 {
  const char c = *text;
  if(pred(c))
  {
  out.push_back(string(begin_word, text - begin_word));
  begin_word = text + 1;
  }
 }
 
if(text != begin_word)
 out.push_back(string(begin_word, text - begin_word));
}


inline bool is_space(char c)
{
return c == ' ';
}

int main(int argc, char *argv[])
{
int r = 0;

vector<string> tokens(5);

for(int i = 0; i < 1000000; i++)
{
    split(tokens, "123 345 asdf 23453 asdfas", is_space);
    r += tokens.size();
}

cout << r << endl;

/*for(int i = 0; i < tokens.size(); ++i)
 {
 cout << tokens[i] << endl;
 }*/

return 0;
}

уже не оставляет шансов бусту(почти в 30 раз для vc8). Вообще надо разобратся как они умудрились такое тормозное сделать.
Re[5]: [Benchmark] DMD быстрее всех
От: Vermicious Knid  
Дата: 17.09.06 11:58
Оценка: 20 (1)
Здравствуйте, FR, Вы писали:

АХ>>А так напиши универсальный split и запости сюда результаты.

FR>Вот такой не универсальный и наколенный вариант
Твой вариант работает не совсем правильно — попробуй два пробела подряд во входной строке написать.

Кроме того твой тест это чистой воды мухлеж. Если не пересоздавать, а очищать vector на кажой итерации, то бустовский вариант тоже ускорится раза в четыре.

Ниже более универсальный вариант. Вместо std::vector принимает любой контейнер с push_back, вместо строки принимает любой контейнер с последовательным константным итератором.
template <class C, class S, class P>
inline void split(C & c, const S & str, P & is_delimiter)
{
    bool next_token = false;
    typename S::const_iterator it = str.begin(), end = str.end(), token_start = it;
    for(; it != end; ++it)
    {
        if (next_token)
        {
            next_token = false;
            token_start = it;
        }
        if (is_delimiter(*it))
        {
            if (token_start != it)
                c.push_back(S(token_start, it));
            next_token = true;
        }
    }
    if (!next_token && (token_start != it))
        c.push_back(S(token_start, it));
}


Вот на таком тесте у меня этот вариант отрабатывает даже чуть быстрее твоего варианта(на нормальном тесте чуть медленнее, тестировалось на vc7.1 + dinkumware stl):
inline bool is_space(const char c)
{
    return c == ' ';
}

int main()
{
    int r = 0;

    vector<string> tokens(5);
    string str("123 345 asdf 23453 asdfas");

    for(int i = 0; i < 1000000; ++i)
    {
        tokens.erase(tokens.begin(),tokens.end());
        split(tokens, str, is_space);
        r += tokens.size();
    }

    cout << r << endl;
    return 0;
}
Re[6]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 17.09.06 12:40
Оценка: +1
Здравствуйте, Vermicious Knid, Вы писали:

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


АХ>>>А так напиши универсальный split и запости сюда результаты.

FR>>Вот такой не универсальный и наколенный вариант
VK>Твой вариант работает не совсем правильно — попробуй два пробела подряд во входной строке написать.

Читай выше Все без гарантий
Хотя проверил, бустовский сплит работает также как мой, на два пробела выдает пустую строку, так что ошибка у тебя

VK>Кроме того твой тест это чистой воды мухлеж. Если не пересоздавать, а очищать vector на кажой итерации, то бустовский вариант тоже ускорится раза в четыре.


Где это там вектор пересоздается? Не было такого, у меня во всех вариантах vector<string> tokens(5); вынесен из цикла.


VK>Вот на таком тесте у меня этот вариант отрабатывает даже чуть быстрее твоего варианта(на нормальном тесте чуть медленнее, тестировалось на vc7.1 + dinkumware stl):


Угу у меня тоже.
Re[7]: [Benchmark] DMD быстрее всех
От: Vermicious Knid  
Дата: 17.09.06 13:24
Оценка:
Здравствуйте, FR, Вы писали:

FR>Хотя проверил, бустовский сплит работает также как мой, на два пробела выдает пустую строку, так что ошибка у тебя

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

Но раз уж так задумано, то тогда все еще проще, и еще слегка быстрее:
template <class C, class S, class P>
inline void split(C & c, const S & str, P & is_delimiter)
{
    typename S::const_iterator it = str.begin(), token_start = it, end = str.end();
    for(; it != end; ++it)
    {
        if (is_delimiter(*it))
        {
            if (token_start != it)
                c.push_back(S(token_start, it));
            ++(token_start = it);
        }
    }
    if (token_start != it)
        c.push_back(S(token_start, it));
}


FR>Где это там вектор пересоздается? Не было такого, у меня во всех вариантах vector<string> tokens(5); вынесен из цикла.

В твоих примерах нет. Но в примерах на C# и других языках массивы то создаются заново на каждом вызове. Поэтому я согласен с Андреем Хроповым, что так корректнее сравнивать.
Re[7]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.06 13:39
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Дык библиотеки то в первую очередь надо оптимизировать. К примеру большую часть CRT можно (и нужно) переписывать с нуля с учетом производительности. Потому как тормозная она...


А это кому-то надо?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.06 13:39
Оценка:
Здравствуйте, eao197, Вы писали:

VD>>Ты прочти свое сообщение и подумай кому бы еще о KISS напомнить.


E>И кому?


Да действительно, кому?

E>Если хочешь позлословить по поводу приведенного мной кода, то это всего лишь популярное изложение части деталей реализации boost::algorithms::is_any_of. К реализации которого я не имею никакого отношения.


Что там "злословить" то? Проблема выеденного яйца не стоит. А ты тут целый трактат написал. Так что KISS.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: BOOST, .NET, String.Split и производительность…
От: CreatorCray  
Дата: 17.09.06 13:48
Оценка:
Здравствуйте, VladD2, Вы писали:

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


CC>>Дык библиотеки то в первую очередь надо оптимизировать. К примеру большую часть CRT можно (и нужно) переписывать с нуля с учетом производительности. Потому как тормозная она...


VD>А это кому-то надо?

Иногда надо.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[8]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 17.09.06 14:29
Оценка:
Здравствуйте, Vermicious Knid, Вы писали:


FR>>Где это там вектор пересоздается? Не было такого, у меня во всех вариантах vector<string> tokens(5); вынесен из цикла.


VK>В твоих примерах нет. Но в примерах на C# и других языках массивы то создаются заново на каждом вызове. Поэтому я согласен с Андреем Хроповым, что так корректнее сравнивать.


При тех тромозах что показал бустовский сплит не принципиально
Да и добавить нормальный аллокатор вектору и строкам (хотя бы тот же boost::pool) и не будет разницы где разместить.
Re[3]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 17.09.06 14:33
Оценка: +1
Здравствуйте, Denis2005, Вы писали:

E>>По моему беглому взгляду на реализацию split-а показалось, что дело в реализации is_any_of.


D>Даже если написать примитивный предикат:


D>bool char_is_space(const char c)

D>{
D> return c == ' ';
D>}

D>то заместо ~20 сек., получаем ~5 сек., на VC++ 8.0.


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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re: BOOST, .NET, String.Split и производительность…
От: Aznog Россия  
Дата: 17.09.06 15:40
Оценка:
Здравствуйте, Denis2005, Вы писали:

D>Доброго времени суток!

D>...

Если взять STLPort, то результат будет лучше (циферки для AthlonXP@1916 MHz):
MSVC 2003: 20 сек
MSVC 2003 + STLPort 5.0: 6 сек.

Если применить предикат, то время с STLPort сократиться до 2 сек.
Re[2]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 17.09.06 16:09
Оценка:
A>Если взять STLPort, то результат будет лучше (циферки для AthlonXP@1916 MHz):
A>MSVC 2003: 20 сек
A>MSVC 2003 + STLPort 5.0: 6 сек.

A>Если применить предикат, то время с STLPort сократиться до 2 сек.


Это все равно не очень радужный результат. У меня split-'велосипед' на STL-е с MSVC 2005 и strtok, выдает ~0.7 сек.

void my_split(vector<char*> &res, char *str, const char separator[])
{
    char *token = strtok( str, separator );

    while( token != NULL )
    {    
        res.push_back( token );
        token = strtok( NULL, separator );
    }
}


Причем пришлось отказаться от std::string. Конечно, не очень хороший код во многих смыслах
(в частности коверкает исх. строку и раставляет указатели на полученные 'обрывки' str),
но свою задачу решает за приемлемое время.

P.S. Меня больше интересует куда исчезает принцип нулевых издержек из рекомендуемых библиотек C++?
Re[9]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.09.06 00:52
Оценка:
Здравствуйте, CreatorCray, Вы писали:

VD>>А это кому-то надо?

CC>Иногда надо.

Обычно при этом просто пошут свои библиотеки. Темболее, что в стандартных функциональность довольно примитивная.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Заразили,блин.
От: Трурль  
Дата: 18.09.06 06:55
Оценка: :))
Здравствуйте, FR, Вы писали:

FR>лучше держи на очень не шустром интерпретаторе:

FR>
FR>REBOL [] res: 0
FR>probe loop 1000000 [res: res + length? parse "123 345 asdf 23453 asdfas" { }]
FR>

FR>3.6 секунды

Вот ещё на очень не шустром интерпретаторе:
do[1000000;&"123 345 asdf 23453 asdfas"=" "]

0.6с
Для сравнения С#: 1.3c
Re[2]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 18.09.06 08:37
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Здравствуйте, Denis2005, Вы писали:


АХ>Обожаю бенчмарки :)


АХ>Померил с использованием таймеров (чтобы не учитывать JIT компиляцию)

АХ>Вот результаты (усреднены по 10 запускам)
АХ>(Athlon XP 1700+ @ 1.5 GHZ + 512Mb DDR266)
АХ>:

АХ>4) Python — 3.48 сек

АХ>6) GCC + Boost — 22.5 сек


АХ>С++:


АХ>
АХ>#include <vector>
АХ>#include <string>
АХ>#include <iostream>
АХ>#include <boost/algorithm/string/split.hpp>
АХ>#include <boost/algorithm/string/classification.hpp>

АХ>#include <windows.h> // for GetTickCount

АХ>using namespace std;
АХ>using namespace boost::algorithm;

АХ>int main()
АХ>{
АХ>  DWORD start = GetTickCount();
    
АХ>  int res = 0;
АХ>  for(int i = 0; i < 1000000; i++)
АХ>  {
АХ>    // так корректней сравнивать, ведь в др программах мы размер не указывали
АХ>    // + по моим тестам почти не повлияло на скорость
/*
Нет. Так сравнивать некорректно, потому что в других языках массивы могут быть 
реализованы как деки (std::deque) или списки (std::list). std::vector всегда реалочится при увеличении размера, а, например, питоновские «массивы» на самом деле списки, 
поэтому, операции конкатенации для них выполняются гааараздо быстрее. 
Правильнее было бы использовать std::list.
*/
АХ>    vector<string> tokens; 

//
АХ>    split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
АХ>    res += tokens.size();
АХ>  }

АХ>  DWORD stop = GetTickCount();

АХ>  cout << "res is " << res << ',' << stop - start << " ms elapsed\n";
  
АХ>  return 0;
АХ>}
АХ>


Мой вариант:
#include <list>
#include <string>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>

#define OS_POSIX

#ifdef OS_WINDOWS
#include <windows.h> // for GetTickCount
#else // posix
#include <sys/times.h>
#endif

using namespace std;
using namespace boost::algorithm;

int main()
{
#ifdef OS_WINDOWS
  DWORD start = GetTickCount();
#else
struct tms t;
  clock_t start = times(&t);
#endif
    
  int res = 0;
  for(int i = 0; i < 1000000; i++)
  {
    list<string> tokens; 
    split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
    res += tokens.size();
  }


#ifdef OS_WINDOWS
  DWORD stop = GetTickCount();
#else
  clock_t stop = times(&t);
#endif

  cout << "res is/ " << res << ',' << stop - start << " ms elapsed\n";
  
  return 0;
}


# g++ test_with_vector.cpp
# ./a.out
res is/ 5000000,3117 ms elapsed

# g++ -O3 test_with_vector.cpp
# ./a.out
res is/ 5000000,756 ms elapsed

# g++ test_with_deque.cpp
# ./a.out
res is 5000000,2919 ms elapsed

# g++ -O3 test_with_deque.cpp
# ./a.out
res is 5000000,801 ms elapsed

# g++ test_with_list.cpp
# ./a.out
res is 5000000,2673 ms elapsed

# g++ -O3 test_with_list.cpp
# ./a.out
res is 5000000,653 ms elapsed

# python test.py
res is 5000000, 2.100000 sec elapsed

# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 15
model : 3
model name : Intel(R) Pentium(R) 4 CPU 2.80GHz
stepping : 4
cpu MHz : 2794.054
cache size : 1024 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe pni monitor ds_cpl cid xtpr
bogomips : 5589.58

processor : 1
vendor_id : GenuineIntel
cpu family : 15
model : 3
model name : Intel(R) Pentium(R) 4 CPU 2.80GHz
stepping : 4
cpu MHz : 2794.054
cache size : 1024 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe pni monitor ds_cpl cid xtpr
bogomips : 5585.27

# cat /proc/meminfo | grep "Total"
MemTotal: 906172 kB
HighTotal: 0 kB
LowTotal: 906172 kB
SwapTotal: 996020 kB
VmallocTotal: 122580 kB
Re[2]: [Benchmark] DMD быстрее всех
От: _rasta  
Дата: 18.09.06 08:46
Оценка: :)
Здравствуйте, Андрей Хропов, Вы писали:

#include <deque>
#include <string>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>

#ifdef OS_WINDOWS
#include <windows.h> // for GetTickCount
#else // posix
#include <sys/times.h>
#endif

using namespace std;
using namespace boost::algorithm;

int main()
{
#ifdef OS_WINDOWS
  DWORD start = GetTickCount();
#else
struct tms t;
  clock_t start = times(&t);
#endif
    
  int res = 0;
  for(int i = 0; i < 1000000; i++)
  {
    // так корректней сравнивать, ведь в др программах мы размер не указывали
    // + по моим тестам почти не повлияло на скорость
    deque<string> tokens; 
    split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
    res += tokens.size();
  }

 #ifdef OS_WINDOWS
  DWORD stop = GetTickCount();
#else
  clock_t stop = times(&t);
#endif

  cout << "res is " << res << ',' << stop - start << " ms elapsed\n";
  
  return 0;
}


(c) cattus «res is 5000000,815 ms elapsed»
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: [Benchmark] DMD быстрее всех
От: _rasta  
Дата: 18.09.06 08:49
Оценка:
Здравствуйте, cattus, Вы писали:

тьфу блин, предупреждать надо
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 18.09.06 09:08
Оценка:
Здравствуйте, cattus, Вы писали:

C>/*

C>Нет. Так сравнивать некорректно, потому что в других языках массивы могут быть
C>реализованы как деки (std::deque) или списки (std::list). std::vector всегда реалочится при увеличении размера, а, например, питоновские «массивы» на самом деле списки,
C>поэтому, операции конкатенации для них выполняются гааараздо быстрее.
C>Правильнее было бы использовать std::list.
C>*/


Я вообще мерил с вынесенным за цикл вектором разница небольшая, так что дело не в этом.


C># g++ test_with_list.cpp

C># ./a.out
C>res is 5000000,2673 ms elapsed

C># g++ -O3 test_with_list.cpp

C># ./a.out
C>res is 5000000,653 ms elapsed

странные у тебя какие то результаты, у меня с твоим кодом gcc3.2(mingw под WinXP) c -O3 дает res is/ 5000000,6063 ms elapsed
а gcc3.4.4(mingw под WinXP) c -O3 дает вообще res is/ 5000000,19985 ms elapsed
процессор Cel D 2.66
Re[2]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 19.09.06 10:47
Оценка: :)
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Здравствуйте, Denis2005, Вы писали:


АХ>Обожаю бенчмарки :)


АХ>Померил с использованием таймеров (чтобы не учитывать JIT компиляцию)

АХ>Вот результаты (усреднены по 10 запускам)
АХ>(Athlon XP 1700+ @ 1.5 GHZ + 512Mb DDR266)
АХ>:

АХ>1) DMD — 0.775 сек

АХ>2) GDC — 0.905 сек
АХ>3) С#/Nemerle — 1.1 сек
АХ>4) Python — 3.48 сек
АХ>5) Python+Psyco — 4.12 (не ускорил!)
АХ>6) GCC + Boost — 22.5 сек
АХ>7) MS VC++ + Boost — 35 сек

Вот еще одно подтверждение изначальной ущербности теста. Прошу сильно не пинать за код -- я очень долго ничего не писал на Haskell'е.

module Main where

import System.CPUTime (getCPUTime)

{- меня заленило лезть в документацию и искать функцию аналогичную split,
   поэтому я реализовал её сам. -}
split :: (a -> Bool) -> [a] -> [[a]]
split _ [] = []
split p l  = case break p l
             of { (b, [])     -> [b]
                ; ([], _)     -> [[]]
                ; (b, (e:[])) -> [b]
                ; (b, (e:ex)) -> b : (split p ex)
                }

fun :: Int -> Int
fun = fun' 0
    where
    fun' :: Int -> Int -> Int
    fun' l n | n <= 0 = l
             | otherwise 
                 = fun'
                   {- следующая строка вычисляется только 1 раз, 
                      в качестве первого аргумента функции fun' 
                      всегда передается одно и тоже значение. -}
                   (l + (length (split (==' ') "123 345 asdf 23453 asdfas"))) 
                   (n - 1)
       
main :: IO ()
main = do { begin <- getCPUTime
          ; putStr "Res is "
          ; (putStr . show . fun) 1000000
          ; putStr ", "
          ; end <- getCPUTime
          ; (putStr . show) (((fromInteger (end - begin)) :: Double) / (1000000000 :: Double))
          ; putStrLn " ms. elapsed."
          }


# ghc -O3 --make main.hs
# ./a.out
Res is 5000000, 8.998 ms. elapsed.

# ghc --version | head -n1
The Glorious Glasgow Haskell Compilation System, version 6.4.1

# gcc --version | head -n1
gcc (GCC) 4.1.2 20060901 (prerelease) (Debian 4.1.1-13)

# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 15
model : 3
model name : Intel(R) Pentium(R) 4 CPU 2.80GHz
stepping : 4
cpu MHz : 2793.936
cache size : 1024 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe pni monitor ds_cpl cid xtpr
bogomips : 5589.55

processor : 1
vendor_id : GenuineIntel
cpu family : 15
model : 3
model name : Intel(R) Pentium(R) 4 CPU 2.80GHz
stepping : 4
cpu MHz : 2793.936
cache size : 1024 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe pni monitor ds_cpl cid xtpr
bogomips : 5585.23

# cat /proc/meminfo | grep Total
MemTotal: 906172 kB
HighTotal: 0 kB
LowTotal: 906172 kB
SwapTotal: 996020 kB
VmallocTotal: 122580 kB


Аналогичная скорость выполнения достигается на Lispe CMUCL, SBCL, если код реализуется в виде макры.
Re[4]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 19.09.06 10:55
Оценка: -1
Здравствуйте, FR, Вы писали:

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


C>>/*

C>>Нет. Так сравнивать некорректно, потому что в других языках массивы могут быть
C>>реализованы как деки (std::deque) или списки (std::list). std::vector всегда реалочится при увеличении размера, а, например, питоновские «массивы» на самом деле списки,
C>>поэтому, операции конкатенации для них выполняются гааараздо быстрее.
C>>Правильнее было бы использовать std::list.
C>>*/


FR>Я вообще мерил с вынесенным за цикл вектором разница небольшая, так что дело не в этом.



C>># g++ test_with_list.cpp

C>># ./a.out
C>>res is 5000000,2673 ms elapsed

C>># g++ -O3 test_with_list.cpp

C>># ./a.out
C>>res is 5000000,653 ms elapsed

FR>странные у тебя какие то результаты, у меня с твоим кодом gcc3.2(mingw под WinXP) c -O3 дает res is/ 5000000,6063 ms elapsed

FR>а gcc3.4.4(mingw под WinXP) c -O3 дает вообще res is/ 5000000,19985 ms elapsed
FR>процессор Cel D 2.66

Все вопросы к реализации MinGW. И вообще, тестировать надо под нормальными операционками, а не под тормозами от дяди Билла. Попробуй другие компиляторы. Я собирал gcc-4.1.1 и gcc-3.3 ­- в обоих случаях результаты одинаковые, в первом случае линковалось с libstdc++.so.6, во втором ­- с libstdc++.so.5.
Re[3]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 19.09.06 10:58
Оценка:
Небольшая поправочка.

fun :: Int -> Int
fun = fun' 0
    where
    fun' :: Int -> Int -> Int
    fun' l n | n <= 0 = l
             | otherwise 
                 = fun'
                   (l +
                   {- следующая строка вычисляется только 1 раз, 
                      в качестве первого аргумента функции fun' 
                      всегда передается одно и тоже значение. -}
                      (length (split (==' ') "123 345 asdf 23453 asdfas"))) 
                   (n - 1)
Re[3]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 19.09.06 11:17
Оценка: +1
Здравствуйте, cattus, Вы писали:


C>Вот еще одно подтверждение изначальной ущербности теста. Прошу сильно не пинать за код -- я очень долго ничего не писал на Haskell'е.


Тест конечно ущербный, но это уже чистый мухлежь
Просто нужно переписать не с миллионом повторов, а с миллион раз размноженной строкой:
from time import clock

t1 = clock()
print len(("123 345 asdf 23453 asdfas " * 1000000).split(" "))
t2 = clock()

print t2 - t1


C>Аналогичная скорость выполнения достигается на Lispe CMUCL, SBCL, если код реализуется в виде макры.


Если так писать на любом языке время будет близкое к нулю, например:
from time import clock

t1 = clock()
print sum([len("123 345 asdf 23453 asdfas".split(" "))] * 1000000)
t2 = clock()

print t2 - t1
Re[2]: [Benchmark] DMD быстрее всех
От: _rasta  
Дата: 19.09.06 11:41
Оценка: :)
Здравствуйте, Андрей Хропов, Вы писали:

АХ>1) DMD — 0.775 сек

АХ>2) GDC — 0.905 сек
АХ>3) С#/Nemerle — 1.1 сек
АХ>4) Python — 3.48 сек
АХ>5) Python+Psyco — 4.12 (не ускорил!)
АХ>6) GCC + Boost — 22.5 сек
АХ>7) MS VC++ + Boost — 35 сек

ну пусть будет еще tcl до кучи, раз пошла такая пьянка
#!/bin/sh
# restart using tclsh \
exec tclsh "$0" "$@"

set _len 0
set x [time {
    for {set x 0} {$x<1000000} {incr x} {
        incr _len [llength [split "123 345 asdf 23453 asdfas"]]
    }
}]
puts $x
puts $_len
puts "done"


3944175 microseconds per iteration
5000000
done

# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 15
model : 2
model name : Intel(R) Pentium(R) 4 CPU 2.80GHz
stepping : 9
cpu MHz : 2800.960
cache size : 512 KB
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 2
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe cid xtpr
bogomips : 5605.23
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 19.09.06 11:45
Оценка:
Здравствуйте, cattus, Вы писали:


C>Все вопросы к реализации MinGW. И вообще, тестировать надо под нормальными операционками, а не под тормозами от дяди Билла. Попробуй другие компиляторы. Я собирал gcc-4.1.1 и gcc-3.3 ­- в обоих случаях результаты одинаковые, в первом случае линковалось с libstdc++.so.6, во втором ­- с libstdc++.so.5.


Другие еще сильнее тормозят
А буст у тебя какой версии?
Вообще не верится что от стандартной библиотеки так зависит, я пробовал с boost::pool_allocator не помогло.
Re[4]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 19.09.06 11:48
Оценка: -1 :)
Здравствуйте, FR, Вы писали:

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



C>>Вот еще одно подтверждение изначальной ущербности теста. Прошу сильно не пинать за код -- я очень долго ничего не писал на Haskell'е.


FR>Тест конечно ущербный, но это уже чистый мухлежь :)

FR>Просто нужно переписать не с миллионом повторов, а с миллион раз размноженной строкой:

Ну почему же мухлеж. Ведь мы не знаем ;)), как работает оптимизатор в С++, в D или где-то еще. Данный код на хаскеле полностью соответствует задаче поставленной в тесте и структурно, в основных своих частях, похож на код тестов реализованных на других языках. Никто не запрещает другим компиляторам или интерпретаторам оптимизировать код, зачем запрещать делать это ghc или SBCL'ю.
Re[6]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 19.09.06 11:50
Оценка:
Здравствуйте, FR, Вы писали:

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



C>>Все вопросы к реализации MinGW. И вообще, тестировать надо под нормальными операционками, а не под тормозами от дяди Билла. Попробуй другие компиляторы. Я собирал gcc-4.1.1 и gcc-3.3 ­- в обоих случаях результаты одинаковые, в первом случае линковалось с libstdc++.so.6, во втором ­- с libstdc++.so.5.


FR>Другие еще сильнее тормозят

FR>А буст у тебя какой версии?
FR>Вообще не верится что от стандартной библиотеки так зависит, я пробовал с boost::pool_allocator не помогло.

Boost: 1.33.1.
Re[2]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 19.09.06 11:55
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Здравствуйте, Denis2005, Вы писали:


АХ>Обожаю бенчмарки



http://shootout.alioth.debian.org/debian/benchmark.php?test=all&amp;lang=dlang&amp;lang2=gpp
Re[3]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 19.09.06 12:09
Оценка:
C>Аналогичная скорость выполнения достигается на Lispe CMUCL, SBCL, если код реализуется в виде макры.

Поигравши с лисповыми макрами, мой друг улучьшил время выполнения кода до 0 мс, притом время выполнения совершенно не зависит от N. ;)))
Re[4]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 19.09.06 12:22
Оценка: 29 (1) :))) :)
Здравствуйте, cattus, Вы писали:

C>>Аналогичная скорость выполнения достигается на Lispe CMUCL, SBCL, если код реализуется в виде макры.


C>Поигравши с лисповыми макрами, мой друг улучьшил время выполнения кода до 0 мс, притом время выполнения совершенно не зависит от N. ))


Я тут тоже оптимизировал:
print 50000


Re[3]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 19.09.06 12:22
Оценка: :)
Здравствуйте, cattus, Вы писали:

C>Здравствуйте, Андрей Хропов, Вы писали:


АХ>>Здравствуйте, Denis2005, Вы писали:


АХ>>Обожаю бенчмарки



C>http://shootout.alioth.debian.org/debian/benchmark.php?test=all&amp;lang=dlang&amp;lang2=gpp


фигня
Re[4]: [Benchmark] DMD быстрее всех
От: _rasta  
Дата: 19.09.06 12:37
Оценка:
Здравствуйте, cattus, Вы писали:

C>Поигравши с лисповыми макрами, мой друг улучьшил время выполнения кода до 0 мс, притом время выполнения совершенно не зависит от N. ))


надо полагать сырцы тока завтра будут..?
Re[3]: BOOST, .NET, String.Split и производительность…
От: saproj  
Дата: 19.09.06 15:30
Оценка: 1 (1)
Здравствуйте, Denis2005, Вы писали:

A>>Если взять STLPort, то результат будет лучше (циферки для AthlonXP@1916 MHz):

A>>MSVC 2003: 20 сек
A>>MSVC 2003 + STLPort 5.0: 6 сек.

A>>Если применить предикат, то время с STLPort сократиться до 2 сек.


D>Это все равно не очень радужный результат. У меня split-'велосипед' на STL-е с MSVC 2005 и strtok, выдает ~0.7 сек.


Очевидно что при многократном создании string получается медленне чем с strtok, который только указатели возвращает.

Могу подтвердить результат Aznog. У меня 2 сек. на MSVC 2005 + STLPort 5.1 + быстрый предикат типа isspace или bind2nd(equal_to<char>(),' ').
А если перейти на vector<iterator_range<string::iterator> >, то 1,2 сек.
Re[5]: [Benchmark] DMD быстрее всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.09.06 17:24
Оценка: +1 :)
Здравствуйте, cattus, Вы писали:

C>Все вопросы к реализации MinGW. И вообще, тестировать надо под нормальными операционками, а не под тормозами от дяди Билла.


Ну, вот мы и выяснили в чем проблема С++. Проблема как всегда в деде Билле. Если бы не он, то буст был бы в 30 раз быстрее и удобнее. Я всегда знал что это ЗАГОВОР!
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 19.09.06 17:30
Оценка:
Здравствуйте, saproj, Вы писали:


S>Очевидно что при многократном создании string получается медленне чем с strtok, который только указатели возвращает.


Почему же тогда с самописным split'ом (Re[4]: [Benchmark] DMD быстрее всех
Автор: FR
Дата: 17.09.06
и Re[7]: [Benchmark] DMD быстрее всех
Автор: Vermicious Knid
Дата: 17.09.06
) который работает с теми же string и создает их на каждый чих, получается гораздо шустрее чем с boost::algorithm::split?
Да и скрипты и шарп и D тоже создают строки и обгоняют буст без проблем.

S>Могу подтвердить результат Aznog. У меня 2 сек. на MSVC 2005 + STLPort 5.1 + быстрый предикат типа isspace или bind2nd(equal_to<char>(),' ').

S>А если перейти на vector<iterator_range<string::iterator> >, то 1,2 сек.

А на vc71 + STLport-4.6 с быстрым предикатом STLPort совсем не ускоряет.
Re[5]: [Benchmark] DMD быстрее всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 00:54
Оценка:
Здравствуйте, _rasta, Вы писали:

C>>Поигравши с лисповыми макрами, мой друг улучьшил время выполнения кода до 0 мс, притом время выполнения совершенно не зависит от N. ))


_>надо полагать сырцы тока завтра будут..?


А они кому-то нужны? Все равно идиальнее
Автор: FR
Дата: 19.09.06
чем у FR уже вряд ли получится.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 00:54
Оценка: +1 -1
Здравствуйте, FR, Вы писали:

FR>Почему же тогда с самописным split'ом (Re[4]: [Benchmark] DMD быстрее всех
Автор: FR
Дата: 17.09.06
и Re[7]: [Benchmark] DMD быстрее всех
Автор: Vermicious Knid
Дата: 17.09.06
) который работает с теми же string и создает их на каждый чих, получается гораздо шустрее чем с boost::algorithm::split?

FR>Да и скрипты и шарп и D тоже создают строки и обгоняют буст без проблем.

А разве это не очевидно? Потому, что вместо выпендрежа люди просто писали библиотеки для реальной работы. А те кто писал бустовский сплит основной целью ставили сделать красиво на С++. Цель то была доказать тезис о том, что С++ настолько крут, что в нем все можно сделать в бибилотеке... и лямбду, и замыкание, и черта лысого. Меж тем если выбростиь все навороты, то написать шустрый сплит на С++ не составляет пробелмы.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [Benchmark] DMD быстрее всех
От: _rasta  
Дата: 20.09.06 04:09
Оценка:
Здравствуйте, VladD2, Вы писали:

C>>Все вопросы к реализации MinGW. И вообще, тестировать надо под нормальными операционками, а не под тормозами от дяди Билла.

VD>Ну, вот мы и выяснили в чем проблема С++. Проблема как всегда в деде Билле. Если бы не он, то буст был бы в 30 раз быстрее и удобнее. Я всегда знал что это ЗАГОВОР!

ну вот зачем писать бред?

изначально было:
6) GCC + Boost — 22.5 сек
7) MS VC++ + Boost — 35 сек


время GCC + Boost было достаточно тривиально улучшено до 6063(653) ms, по разным данным, что как минимум 4 (40) раз быстрее. буста у меня, к сожалению, нет, но можно попросить присутствующих собрать представленый код в лялихе с указанными либами и выложить время выполнения. если время будет не сильно отличаться от заявленного cattus-ом, то таки да, вянда традиционно г-но. все же просто...
Re[7]: [Benchmark] DMD быстрее всех
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 20.09.06 04:19
Оценка:
Здравствуйте, _rasta, Вы писали:

_>ну вот зачем писать бред?


_>изначально было:

_>6) GCC + Boost — 22.5 сек
_>7) MS VC++ + Boost — 35 сек


ничего, что также изначально было

C# (под той же виндой) — 1сек ?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Re[8]: [Benchmark] DMD быстрее всех
От: _rasta  
Дата: 20.09.06 04:50
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>ничего, что также изначально было

OE>C# (под той же виндой) — 1сек ?

но с этим-то никто не спорил
кстати было бы интересно посмотреть еще на яву
Re[9]: [Benchmark] DMD быстрее всех
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 20.09.06 05:14
Оценка:
Здравствуйте, _rasta, Вы писали:

OE>>ничего, что также изначально было

OE>>C# (под той же виндой) — 1сек ?
_>но с этим-то никто не спорил

ну дык если под одной и той же виндой результат зависит от языка/библиотек с какой радости может быть "таки да, вянда традиционно г-но"?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Re[10]: [Benchmark] DMD быстрее всех
От: _rasta  
Дата: 20.09.06 05:33
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>>>ничего, что также изначально было

OE>>>C# (под той же виндой) — 1сек ?
_>>но с этим-то никто не спорил
OE>ну дык если под одной и той же виндой результат зависит от языка/библиотек с какой радости может быть "таки да, вянда традиционно г-но"?

я там смайлик забыл
собсно упор делался на то, чтов лялихе же быстрее работает, пока никто не сказал обратного
Re[11]: [Benchmark] DMD быстрее всех
От: FR  
Дата: 20.09.06 08:10
Оценка:
Здравствуйте, _rasta, Вы писали:

_>Здравствуйте, Odi$$ey, Вы писали:


OE>>>>ничего, что также изначально было

OE>>>>C# (под той же виндой) — 1сек ?
_>>>но с этим-то никто не спорил
OE>>ну дык если под одной и той же виндой результат зависит от языка/библиотек с какой радости может быть "таки да, вянда традиционно г-но"?

_>я там смайлик забыл

_>собсно упор делался на то, чтов лялихе же быстрее работает, пока никто не сказал обратного

Это пока неподвержденные данные, жаль не смогу скоро добратся до linux'а с установленным бустом.
Re[6]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 20.09.06 08:24
Оценка: :)
Здравствуйте, VladD2, Вы писали:

Цель то была доказать тезис о том, что С++ настолько крут, что в нем все можно сделать в бибилотеке... и лямбду, и замыкание, и черта лысого.

Насчет черта лысого не уверен, но лямбда удалась на славу:


void MyF1(vector<int>& vec, int s)
{
    transform(vec.begin(), vec.end(), vec.begin(), (s + _1));
}



VC8.0 -O2


?MyF1@@YAXAAV?$vector@HV?$allocator@H@std@@@std@@H@Z PROC ; MyF1, COMDAT
    mov    eax, DWORD PTR _vec$[esp-4]
    mov    ecx, DWORD PTR [eax+4]
    mov    edx, DWORD PTR [eax+8]
    mov    eax, ecx
    cmp    eax, edx
    push    esi
    push    edi
    je    SHORT $LN71@MyF1
    mov    esi, DWORD PTR _s$[esp+4]
$LL82@MyF1:
    mov    edi, DWORD PTR [eax]
    add    edi, esi
    mov    DWORD PTR [ecx], edi
    add    eax, 4
    add    ecx, 4
    cmp    eax, edx
    jne    SHORT $LL82@MyF1
$LN71@MyF1:
    pop    edi
    pop    esi
    ret    0


Очень похоже на нулевые издержки.
Re[7]: BOOST, .NET, String.Split и производительность…
От: WolfHound  
Дата: 20.09.06 09:11
Оценка: +1 -1
Здравствуйте, Denis2005, Вы писали:

D>Насчет черта лысого не уверен, но лямбда удалась на славу:


D>
D>void MyF1(vector<int>& vec, int s)
D>{
D>    transform(vec.begin(), vec.end(), vec.begin(), (s + _1));
D>}
D>

Вот скажи мне на сколько часто тебе нужны такая лямюбда? Мне нужно как минимум обратится к челену класса, а с этим уже все не так красиво... А если нужно както так Obj.Prop1.Prop2.Prop3 то вобще тушите свет.
Короче для людей которые использовали нормальную лямбду очевидно что boost::lambda непригодно для реальной работы.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 20.09.06 10:17
Оценка: +2
Здравствуйте, WolfHound, Вы писали:

WH>Вот скажи мне на сколько часто тебе нужны такая лямюбда? Мне нужно как минимум обратится к челену класса, а с этим уже все не так красиво... А если нужно както так Obj.Prop1.Prop2.Prop3 то вобще тушите свет.

WH>Короче для людей которые использовали нормальную лямбду очевидно что boost::lambda непригодно для реальной работы.

Собственно говоря boost::lambda предназначен для того, чтобы не приходилось писать функции/функторы под простейшие случаи. Немогу не согласится, что для Obj.Prop1.Prop2.Prop3 это просто не пригодно. Вообщем более 'толстые' лямбды я все равно не пишу, предпочитаю функторы, т.к. это более декомпозиционно.
Re[3]: [Benchmark] DMD быстрее всех
От: cattus  
Дата: 20.09.06 10:19
Оценка:
C># g++ test_with_vector.cpp
C># ./a.out
C>res is/ 5000000,3117 ms elapsed

C># g++ -O3 test_with_vector.cpp

C># ./a.out
C>res is/ 5000000,756 ms elapsed

C># g++ test_with_deque.cpp

C># ./a.out
C>res is 5000000,2919 ms elapsed

C># g++ -O3 test_with_deque.cpp

C># ./a.out
C>res is 5000000,801 ms elapsed

C># g++ test_with_list.cpp

C># ./a.out
C>res is 5000000,2673 ms elapsed

C># g++ -O3 test_with_list.cpp

C># ./a.out
C>res is 5000000,653 ms elapsed

C># python test.py

C>res is 5000000, 2.100000 sec elapsed


Перед всеми извиняюсь, ляпнул.

#include <list>
#include <string>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>

#define OS_POSIX

#ifdef OS_WINDOWS
#include <windows.h> // for GetTickCount
#else // posix
#include <sys/times.h>
#endif

using namespace std;
using namespace boost::algorithm;

int main()
{
#ifdef OS_WINDOWS
  DWORD start = GetTickCount();
#else
  struct tms t;
  long ts = sysconf(_SC_CLK_TCK);
  double start = ((double) times(&t) / ts) * 1000;
#endif
    
  int res = 0;
  for(int i = 0; i < 1000000; i++)
  {
    list<string> tokens; 
    split(tokens, "123 345 asdf 23453 asdfas", is_any_of(" "));
    res += tokens.size();
  }


#ifdef OS_WINDOWS
  DWORD stop = GetTickCount();
#else
  double stop = ((double) times(&t) / ts) * 1000;
#endif

  cout << "res is " << res << ',' << stop - start << " ms elapsed\n";
  
  return 0;
}


Так как функция sysconf(_SC_CLK_TCK) (количество тиков в секунду) на моей машине возвращает 100, достаточно каждый из вышеприведённых результатов умножить на 10.

C># g++ test_with_vector.cpp

C># ./a.out
C>res is/ 5000000,31170 ms elapsed

C># g++ -O3 test_with_vector.cpp

C># ./a.out
C>res is/ 5000000,7560 ms elapsed

C># g++ test_with_deque.cpp

C># ./a.out
C>res is 5000000,29190 ms elapsed

C># g++ -O3 test_with_deque.cpp

C># ./a.out
C>res is 5000000,8010 ms elapsed

C># g++ test_with_list.cpp

C># ./a.out
C>res is 5000000,26730 ms elapsed

C># g++ -O3 test_with_list.cpp

C># ./a.out
C>res is 5000000,6530 ms elapsed

То есть лучший результат 6,530 сек.
Re[9]: BOOST, .NET, String.Split и производительность…
От: WolfHound  
Дата: 20.09.06 11:20
Оценка:
Здравствуйте, Denis2005, Вы писали:

D>Собственно говоря boost::lambda предназначен для того, чтобы не приходилось писать функции/функторы под простейшие случаи. Немогу не согласится, что для Obj.Prop1.Prop2.Prop3 это просто не пригодно. Вообщем более 'толстые' лямбды я все равно не пишу, предпочитаю функторы, т.к. это более декомпозиционно.

Что только люди не приюдумают для того чтобы оправдать использование С++.
По сравнению с нормальной лямбдой функторы не рулят совершенно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 11:26
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Что только люди не приюдумают для того чтобы оправдать использование С++.




WH>По сравнению с нормальной лямбдой функторы не рулят совершенно.


Временами рулят и очень сильно. Функторы могут наследоваться. Функторы могут разрастаться до довольно таки сложной логики и приличного размера.

А вот boost::lambda по сравненю с нормальной лямбдой действительно и рядом не стояла.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[11]: BOOST, .NET, String.Split и производительность…
От: WolfHound  
Дата: 20.09.06 11:53
Оценка:
Здравствуйте, eao197, Вы писали:

E>Временами рулят и очень сильно. Функторы могут наследоваться. Функторы могут разрастаться до довольно таки сложной логики и приличного размера.

Код в студию.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[11]: BOOST, .NET, String.Split и производительность…
От: Курилка Россия http://kirya.narod.ru/
Дата: 20.09.06 12:03
Оценка:
Здравствуйте, eao197, Вы писали:

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


WH>>По сравнению с нормальной лямбдой функторы не рулят совершенно.


E>Временами рулят и очень сильно. Функторы могут наследоваться. Функторы могут разрастаться до довольно таки сложной логики и приличного размера.


Т.е. ты декомпозицию делаешь при помощи ООП? При функциональной декомпозиции это будет выглядеть иначе, наследование там вообще как понятие не существует.
Re[12]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 12:25
Оценка: :)))
Здравствуйте, WolfHound, Вы писали:

E>>Временами рулят и очень сильно. Функторы могут наследоваться. Функторы могут разрастаться до довольно таки сложной логики и приличного размера.

WH>Код в студию.

Вот, пример большого функтора:
/*!
    \since v.4.2.7
    \brief Предикат для std::find_if.

    Для очередного состояния проверяет возможность слияния
    с состоянием из другого класса агентов.

    Определяет, есть ли среди всех классов, на которые ссылаются
    состояния, еще не полностью определенные классы.
*/
class    merge_possibility_checker_t
    :    public std::unary_function<
            const state_handler_impl_ptr_vector_t::value_type &,
            bool >
    {
    private :
        /*! Список всех классов. */
        const class_map_t & m_all_classes;

        /*! Список состояний всех классов */
        const std_class_relation_handler_t::class_info_map_t &
            m_classes_state;

        /*! Принимает значение true, если были найдены не
            полностью определенные классы. */
        bool    & m_is_incomplete_class_found;

        /*! Приемник описания ошибки. */
        std::string &    m_error_desc;

    public :
        //! Основной конструктор.
        merge_possibility_checker_t(
            //! Список всех классов.
            const class_map_t & all_classes,
            const std_class_relation_handler_t::class_info_map_t &
                classes_state,
            bool & is_incomplete_class_found,
            //! Приемник описания ошибки.
            std::string & error_desc )
            :    m_is_incomplete_class_found( is_incomplete_class_found )
            ,    m_all_classes( all_classes )
            ,    m_classes_state( classes_state )
            ,    m_error_desc( error_desc )
            {}

        result_type
        operator()( argument_type a );

    private :
        /*! Проверка наличия указанного состояния в указанном
            классе.

            \return true, если состояние найдено. */
        bool
        try_find_state_in_class(
            //! Имя искомого состояния.
            const std::string & state_name,
            //! Класс, в котором состояние нужно найти.
            const class_handler_impl_t & class_handler );
    };

merge_possibility_checker_t::result_type
merge_possibility_checker_t::operator()( argument_type a )
    {
        bool result = false;

        const state_handler_impl_t::merge_list_t & merge_list =
            a->merge_list();

        for( state_handler_impl_t::merge_list_t::const_iterator
                it = merge_list.begin(), it_end = merge_list.end();
            it != it_end;
            ++it )
            {
                bool is_merge_valid = false;

                const state_handler_impl_t::merge_t & m = *it;

                // Должен быть известен класс.
                class_map_t::const_iterator it_class = m_all_classes.find(
                    m.m_class_name );
                if( it_class != m_all_classes.end() )
                    {
                        int state = m_classes_state.find(
                            m.m_class_name )->second.m_state;
                        // Класс должен быть полностью определен.
                        if( std_class_relation_handler_t::state_valid == state )
                            {
                                // Должно быть известно состояние.
                                if( try_find_state_in_class(
                                    m.m_state_name, *( it_class->second ) ) )
                                    // Все хорошо. Поэтому, чтобы перейти к обработке
                                    // следующего состояния, нужно возвратить false.
                                    is_merge_valid = true;
                                else
                                    {
                                        // Состояние не известно.
                                        m_error_desc += std::string( "state '" ) +
                                            a->query_name() +
                                            "' requires merging with undefined state '" +
                                            m.m_state_name + "' from class '" +
                                            m.m_class_name + "';";
                                    }
                            }
                        else if( std_class_relation_handler_t::state_invalid == state )
                            // Нашли ссылку на некорректный класс.
                            m_error_desc += std::string( "state '" ) +
                                a->query_name() +
                                "' requires merging with invalid class '" +
                                m.m_class_name + "';";
                        else
                            {
                                // Класс еще не определен.
                                m_is_incomplete_class_found = true;
                                m_error_desc += std::string( "incomplete class: " ) +
                                    m.m_class_name + ";";
                            }
                    }
                else
                    // Нашли ссылку на неизвестный класс.
                    m_error_desc += std::string( "state '" ) + a->query_name() +
                        "' requires merging with undefined class '" +
                        m.m_class_name + "';";

                // Если текущее слияние не корректно, то и состояние не может
                // быть корректным.
                if( !is_merge_valid )
                    result = true;
            }

        return result;
    }

bool
merge_possibility_checker_t::try_find_state_in_class(
    const std::string & state_name,
    const class_handler_impl_t & class_handler )
    {
        const state_handler_impl_ptr_vector_t & states =
            class_handler.query_state_handlers();
        return ( states.end() != std::find_if(
            states.begin(), states.end(),
            state_by_name_finder_t( state_name ) ) );
    }


который используется так:
int
std_class_relation_handler_t::try_merge_states(
    const class_handler_impl_t & class_handler,
    const class_map_t & all_classes,
    std::string & error_desc )
    {
        // Берем все состояния, которые нуждаются в слиянии.
        state_handler_impl_ptr_vector_t states_for_merging =
            class_handler.states_for_merge();

        // Проверяем возможность проведения слияния.
        bool is_incomplete_class_found = false;
        merge_possibility_checker_t checker( all_classes, m_classes,
            is_incomplete_class_found, error_desc );
        if( states_for_merging.end() != std::find_if(
            states_for_merging.begin(), states_for_merging.end(),
            checker ) )
            // Слияние не возможно. Осталось только определить,
            // по какой причине.
            return ( is_incomplete_class_found ?
                state_not_processed :
                state_invalid );

        // Выполняем слияние.
        std::for_each( states_for_merging.begin(),
            states_for_merging.end(),
            merge_maker_t( all_classes ) );

        return state_valid;
    }


По поводу наследования: в своих OpenSource проектах с ходу не нашел. А код из закрытых проектов не смотрел, т.к. результат все равно не смогу показать. Но раз или два пришлось делать наследование для функторов, чтобы общую функциональность в базовый класс поместить. Ну и простейший пример наследования для функторов -- наследование от std::unary_function .


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[12]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 12:30
Оценка:
Здравствуйте, Курилка, Вы писали:

E>>Временами рулят и очень сильно. Функторы могут наследоваться. Функторы могут разрастаться до довольно таки сложной логики и приличного размера.


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


Не очень понимаю, о чем ты. Мне просто пару раз над элементами контейнеров пришлось делать несколько похожих, но отличающихся в деталях операций (каких именно уже не помню). Поэтому я сделал базовый класс, наследник от std::unary_function, в нем пару виртуальных методов. Затем пару производных классов, в которых эти виртуальные методы перекрывались. А потом в коде вызывал std::for_each то с одним наследником, то с другим.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[13]: BOOST, .NET, String.Split и производительность…
От: Курилка Россия http://kirya.narod.ru/
Дата: 20.09.06 12:40
Оценка: +2
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Курилка, Вы писали:


E>>>Временами рулят и очень сильно. Функторы могут наследоваться. Функторы могут разрастаться до довольно таки сложной логики и приличного размера.


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


E>Не очень понимаю, о чем ты. Мне просто пару раз над элементами контейнеров пришлось делать несколько похожих, но отличающихся в деталях операций (каких именно уже не помню). Поэтому я сделал базовый класс, наследник от std::unary_function, в нем пару виртуальных методов. Затем пару производных классов, в которых эти виртуальные методы перекрывались. А потом в коде вызывал std::for_each то с одним наследником, то с другим.


О том, что если решать эту задачу с т.зр. ФП, то виртуальных методов не будет, а будет функция высшего порядка, в которую будут передаваться функции, которые соотвествуют твоим перекрытым методам.
Просто ты решал задачу в терминах объектов и тебе было так удобнее, кому-то возможно удобнее по-другому.
Re[14]: BOOST, .NET, String.Split и производительность…
От: Cyberax Марс  
Дата: 20.09.06 13:11
Оценка:
Курилка wrote:
> О том, что если решать эту задачу с т.зр. ФП, то виртуальных методов не
> будет, а будет функция высшего порядка, в которую будут передаваться
> функции, которые соотвествуют твоим перекрытым методам.
То же самое, вид сбоку.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[15]: BOOST, .NET, String.Split и производительность…
От: Курилка Россия http://kirya.narod.ru/
Дата: 20.09.06 13:28
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Курилка wrote:

>> О том, что если решать эту задачу с т.зр. ФП, то виртуальных методов не
>> будет, а будет функция высшего порядка, в которую будут передаваться
>> функции, которые соотвествуют твоим перекрытым методам.
C>То же самое, вид сбоку.
Не спорю, просто кому-то удобней может быть такой вид, а кому-то наоборот
Re[7]: [Benchmark] DMD быстрее всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 14:29
Оценка:
Здравствуйте, _rasta, Вы писали:

_>ну вот зачем писать бред?


И я тоже думаю "зачем писать бред" но ты это делашь без зазрения.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: [Benchmark] DMD быстрее всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 14:29
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>ничего, что также изначально было

OE>C# (под той же виндой) — 1сек ?

Думаю, это не важно в контесте разговоров о вредоносности дяди Билла.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: [Benchmark] DMD быстрее всех
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 14:29
Оценка:
Здравствуйте, _rasta, Вы писали:

_>я там смайлик забыл


В следущий раз не забывай. А то без него твои слова выглядят форменным бредом.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 14:29
Оценка:
Здравствуйте, Denis2005, Вы писали:

D>Насчет черта лысого не уверен, но лямбда удалась на славу:


D>
D>void MyF1(vector<int>& vec, int s)
D>{
D>    transform(vec.begin(), vec.end(), vec.begin(), (s + _1));
D>}
D>


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

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

Кстати, даже в такх, примитивных, случаях языки с полноценной поддержкой функций высшего порядка выглядят лучше.
Вот как это будет выглядить не Немерле:
transform.(s + _);

"s + _" автоматом преобразуется в лямбду с одним параметром (никаких лишних скобок и хардкодед-имен вроде "_1" не нужно). Да и отсуствие идиотизма с begin()/end() разгружает код. В итоге получается, что писать функционально конечно на С++ можно, но неудобно, не всегда быстро, и очень громоздко.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 14:29
Оценка:
Здравствуйте, Denis2005, Вы писали:

D>Собственно говоря boost::lambda предназначен для того, чтобы не приходилось писать функции/функторы под простейшие случаи. Немогу не согласится, что для Obj.Prop1.Prop2.Prop3 это просто не пригодно. Вообщем более 'толстые' лямбды я все равно не пишу, предпочитаю функторы, т.к. это более декомпозиционно.


Для тех кто плотно попользовался функцями высшего порядка (ФВП), лямбды и локальные фукнции становятся частью средств декомпозиции кода и они начинают применяться повсеместно. Не важно насколько сложен случай. Уж обращаться к членам классов точно постоянно нужно (особенно в императивном С++).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 14:29
Оценка:
Здравствуйте, eao197, Вы писали:

E>Временами рулят и очень сильно. Функторы могут наследоваться. Функторы могут разрастаться до довольно таки сложной логики и приличного размера.


А что классы в других языках отменили что ли? Просто в других языках нет нужны эмулировать классами функции высшего порядка. Они уже есть в языке шататно.

И тебе ли это не знать? Снова поспорить охота?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 14:29
Оценка:
Здравствуйте, Курилка, Вы писали:

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


Он на Руби пишет, в лучшем случае. А там как и в С++ ООП основное средство декомпозиции. Других практически нет. Одними лямбдами (блоками) сыт не будешь.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 14:29
Оценка:
Здравствуйте, Курилка, Вы писали:

Сколько тебе надо дать дней бани чтобы ты проникся, что цитировать надо только то что необходимо для понимания твоего ответа?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 14:44
Оценка: :)
Здравствуйте, VladD2, Вы писали:

VD>Он на Руби пишет, в лучшем случае. А там как и в С++ ООП основное средство декомпозиции. Других практически нет. Одними лямбдами (блоками) сыт не будешь.


Ага, а тебе еще паттерн-матчинг добавили. Он рулит покруче ООП и лямб вместе взятых.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[13]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 14:46
Оценка:
Кстати, вопрос к тем, кто смайлики ставит: а что смешного?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[13]: BOOST, .NET, String.Split и производительность…
От: WolfHound  
Дата: 20.09.06 14:47
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>По поводу наследования: в своих OpenSource проектах с ходу не нашел. А код из закрытых проектов не смотрел, т.к. результат все равно не смогу показать. Но раз или два пришлось делать наследование для функторов, чтобы общую функциональность в базовый класс поместить. Ну и простейший пример наследования для функторов -- наследование от std::unary_function .

Автор маньякЪ!
Мне лень разбиратся но у меня такое чувство что ты гдето нетак провел декомпозицию.
У меня никогда не возникало жилания сделать такие функторы.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[14]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 20.09.06 14:55
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>Кстати, вопрос к тем, кто смайлики ставит: а что смешного?


размер
Re[15]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 15:05
Оценка:
Здравствуйте, FR, Вы писали:

E>>Кстати, вопрос к тем, кто смайлики ставит: а что смешного?


FR>размер


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

К тому же для реальной (а не форумной пенисометрии) задачи объем получился весьма удовлетворительный: декларация функтора, тело operator() и тело вспомогательного метода, поотдельности занимают не более одной странички A4.

Так что это real life, смешного, как обычно, не много.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 20.09.06 16:03
Оценка:
Здравствуйте, VladD2, Вы писали:

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


D>>Насчет черта лысого не уверен, но лямбда удалась на славу:


D>>
D>>void MyF1(vector<int>& vec, int s)
D>>{
D>>    transform(vec.begin(), vec.end(), vec.begin(), (s + _1));
D>>}
D>>


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


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

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


Невнятные сообщения об ошибках, это вполне нормальный случай, если библиотекой решается, то на, что изначально язык не был ориентирован.

VD>Кстати, даже в такх, примитивных, случаях языки с полноценной поддержкой функций высшего порядка выглядят лучше.

VD>Вот как это будет выглядить не Немерле:
VD>
VD>transform.(s + _);
VD>

VD>"s + _" автоматом преобразуется в лямбду с одним параметром (никаких лишних скобок и хардкодед-имен вроде "_1" не нужно). Да и отсуствие идиотизма с begin()/end() разгружает код. В итоге получается, что писать функционально конечно на С++ можно, но неудобно, не всегда быстро, и очень громоздко.

Без лишних скобок: transform(vec.begin(), vec.end(), vec.begin(), s + _1);
А вот насчет begin()/end() не понял. Чем итераторы то не угодили?
Re[14]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 16:14
Оценка:
Здравствуйте, eao197, Вы писали:

VD>>Он на Руби пишет, в лучшем случае. А там как и в С++ ООП основное средство декомпозиции. Других практически нет. Одними лямбдами (блоками) сыт не будешь.


E>Ага, а тебе еще паттерн-матчинг добавили. Он рулит покруче ООП и лямб вместе взятых.


Он не то чтобы по круче, но в купе с алгебраическими типами во многих случая получается куда как выразительнее, чем без них. В купе же я просто имею больше средств для выражения. Ведь я могу выбирать из довольно широкого списка:
1. ООП (причем отлично реализованный, модульный, компонентный...).
2. Функции высшего порядка (ФВП).
3. Макросы (тяжелая артилерия).
4. Алгебраические типы и паттерн-матчинг.

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

В общем-то я тут согласен с Гапертоном — классы больше подходят для общего дизайна прилоежния. Для реализации ФВП и другие прибмабасы лучше подходят.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 16:36
Оценка:
Здравствуйте, Denis2005, Вы писали:

D>Они хороши только тем, что не потребовали расширения и без того очень 'широкого' языка.


Что широкого в этом языке? Почему его нельзя целенаправлено рсширить действительно общепризнанно удобными возможностями? Зачем их эмулировать на коленке?

Хотя... мне уже по фигу. Меня этот вопрос занимал несколько лет назад. Теперь моя позиция очень простая. Горбатого могила исправит. Пусть гниет дальше.

D>Случаи чуть по сложнее решаются обычно функторами.


"Обычными"? Это где они слали обычными? Что-то я такого чуда природы в языках с функциями высшего прядка вообще не видел. И знаешь, мне кажется, что это потому, что фанкторы на фиг не упали.

D>Невнятные сообщения об ошибках, это вполне нормальный случай,


Серьезно? Дочего можно довести себя самовнушением?!

D>если библиотекой решается, то на, что изначально язык не был ориентирован.


А зачем тогда делать это в библиотеке? Почему не расширить язык тем что многим так нужно? Ведь получится элегантнее, быстрее (код быстрее будет), удобнее и с нормальной диагностикой ошибок. Какова цель згонять популярный язык в угол?

D>Без лишних скобок: transform(vec.begin(), vec.end(), vec.begin(), s + _1);

D>А вот насчет begin()/end() не понял. Чем итераторы то не угодили?

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

Если в коде присуствует vec.begin() и vec.end() — это уже избыточный код. Ведь работа ведется со всем списком и отдельно указывать его голову так же глупо как на вопрос о расстоянии до объекта начинать давать его координаты и координаты место где ты находишся.

В общем, С++, точнее его создатели, нарушили один очень важный принцип KISS. И это его погубит. А пока он не умер, можно извлечь пользу для сбея и своей конторы перейдя на более продуктивный язык и набляюдая как туча ежиков колются, плачут но продолжают с упоением жрать это кактус.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.06 16:51
Оценка: +1
Здравствуйте, eao197, Вы писали:

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


Это зависит... от разрабочика. Разумный разработчик произвел бы декомпозицию функций и получил бы ряд более простых фунций и собераемую из инх более сложную функцию.

Кстати, это как раз тот случай когда как раз функции высшего порядка неимоверно "рулят". ООП обычно не дает детализировать алгоритмы, так как оверхэд на описание классов и их методов превышает выигрышь от самой декомпозиции.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 17:01
Оценка: :)
Здравствуйте, VladD2, Вы писали:

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


VD>Это зависит... от разрабочика. Разумный разработчик произвел бы декомпозицию функций и получил бы ряд более простых фунций и собераемую из инх более сложную функцию.


Ага, и программы у таких разработчиков работают, если в них ошибок нет.

Ты посмотри на код, там нет ничего сложного -- один цикл и несколько if-ов. Объем создает только форматирование и комментарии.

Но самое важное, что это только одна из простых функций, которые вместе реализуют довольно-таки сложный алгоритм. И мне было важно, чтобы на более высоком уровне я мог оперировать конструкциями типа std::for_each, std::find_if, std::transform и делать прозрачным более сложный код.

VD>Кстати, это как раз тот случай когда как раз функции высшего порядка неимоверно "рулят". ООП обычно не дает детализировать алгоритмы, так как оверхэд на описание классов и их методов превышает выигрышь от самой декомпозиции.


Ой-ой-ой. Не поверю.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[15]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 17:05
Оценка: -1
Здравствуйте, VladD2, Вы писали:

VD>Он не то чтобы по круче, но в купе с алгебраическими типами во многих случая получается куда как выразительнее, чем без них. В купе же я просто имею больше средств для выражения. Ведь я могу выбирать из довольно широкого списка:

VD>1. ООП (причем отлично реализованный, модульный, компонентный...).
VD>2. Функции высшего порядка (ФВП).
VD>3. Макросы (тяжелая артилерия).
VD>4. Алгебраические типы и паттерн-матчинг.

Можешь рассказать, какая помощь от макросов в обработке графовых структур?

VD>Причем последний пункт рельно по значемости я бы поставил на первое место.

VD>Оно и не удивильно, что ты в случаях в кторых казалось бы классы на фиг не упали во всю их используешь да еще и "фанкторами" называешь. А меж тем Курилка прав. Подобные задачи без классов решаются только проще.

Нихрена они проще не получаются. Получаются те же продукты, только в профиль. Но об этом уже Cyberax сказал.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[10]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 20.09.06 17:05
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Что широкого в этом языке? Почему его нельзя целенаправлено рсширить действительно общепризнанно удобными возможностями? Зачем их эмулировать на коленке?


VD>А зачем тогда делать это в библиотеке? Почему не расширить язык тем что многим так нужно? Ведь получится элегантнее, быстрее (код быстрее будет), удобнее и с нормальной диагностикой ошибок. Какова цель згонять популярный язык в угол?


Понять жизнь можно лишь оглядываясь назад, но жить-то приходится, смотря вперед. (C) Сёрен Кьеркегор
Была избрана такая политика, чтобы помаксимому давить на библиотеки, т.к. язык и без того слишком сложный и многими местами противоричивый.
Ты же знаешь, сколько времени нужно WG21 X3J16 чтобы принят то или иное решение, особенно если оно касается расширений.
А сколько пройдет когда реальными компиляторами будет поддерживаться введеное расширение?
Вот с библиотекой дела обстоят немного попроще, поэтому на них и делается основной упор.

VD>Хотя... мне уже по фигу. Меня этот вопрос занимал несколько лет назад. Теперь моя позиция очень простая. Горбатого могила исправит. Пусть гниет дальше.


'Горбатый' еще задаст жару молодым неокрепшим умам

D>>Случаи чуть по сложнее решаются обычно функторами.


VD>"Обычными"? Это где они слали обычными? Что-то я такого чуда природы в языках с функциями высшего прядка вообще не видел. И знаешь, мне кажется, что это потому, что фанкторы на фиг не упали.


Я сказал обычно, и применительно для C++. В C# 2.0 нормально обхожусь анонимными делегатами.

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

VD>Если в коде присуствует vec.begin() и vec.end() — это уже избыточный код. Ведь работа ведется со всем списком и отдельно указывать его голову так же глупо как на вопрос о расстоянии до объекта начинать давать его координаты и координаты место где ты находишся.

За всех говорит не стоит. Частенько бывает, что работа ведется с определенными фрагментами коллекции.
Хотя там где производительность особо не важна, можно и полными списками погонять.

VD>В общем, С++, точнее его создатели, нарушили один очень важный принцип KISS. И это его погубит. А пока он не умер, можно извлечь пользу для сбея и своей конторы перейдя на более продуктивный язык и набляюдая как туча ежиков колются, плачут но продолжают с упоением жрать это кактус.



Сам пишу пот .NET уже > 4 лет, если задача позволяет, поэтому про ежиков заканчивай.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: BOOST, .NET, String.Split и производительность…
От: McSeem2 США http://www.antigrain.com
Дата: 20.09.06 17:18
Оценка: +1
Здравствуйте, Odi$$ey, Вы писали:

MS>>Так что язык здесь ни при чем вообще.


OE> C# вроде как под той же виндой тестируют с той же самой ntdll.dll


Разница в том, что C# не вызывает ntdll по isspace (или какой там аналог?). А сишная библиотека от MS по кой-то фиг вызывает (ну или вызывала, не знаю как оно сейчас).
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[18]: BOOST, .NET, String.Split и производительность…
От: WolfHound  
Дата: 20.09.06 17:45
Оценка: -1
Здравствуйте, eao197, Вы писали:

E>конструкциями типа std::for_each, std::find_if, std::transform и делать прозрачным более сложный код.

Это называется функции высшего порядка реализованные через зад автогеном.

VD>>Кстати, это как раз тот случай когда как раз функции высшего порядка неимоверно "рулят". ООП обычно не дает детализировать алгоритмы, так как оверхэд на описание классов и их методов превышает выигрышь от самой декомпозиции.

E>Ой-ой-ой. Не поверю.
А зря. Только к проблеме нужно подходить комплексно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Наколенный вариант 8-летней давности
От: McSeem2 США http://www.antigrain.com
Дата: 20.09.06 18:06
Оценка: :)
Здравствуйте, Denis2005, Вы писали:

D>Компилятор: MS VC 8.0

D>Время работы: 20 секунд. (и это при полной оптимизации и отключенными проверками !?!)

D>Код на C#, .NET Framework:

D>Время работы: ~1 сек, при 10^7 итераций ~6 сек.


#include <stdio.h>
#include <string.h>
#include <time.h>

class tokenizer
{
public:
    enum sep_flag
    {
        single,
        multiple,
        whole_str
    };

    struct token
    {
        const char* ptr;
        unsigned    len;
    };

    tokenizer(const char* sep, 
              const char* trim=0,
              const char* quote="\"",
              char mask_chr='\\',
              sep_flag sf=multiple);

    void set_str(const char* str)
    {
        m_src_string = str; 
        m_start = 0;
    }

    token next_token();

private:
    
    // This function should actually be a template parameter
    static int check_chr(const char *str, char chr)
    {
        return chr == ' ';//int(strchr(str, chr));
    }

private:
    const char* m_src_string;
    int         m_start;
    const char* m_sep;
    const char* m_trim;
    const char* m_quote;
    char        m_mask_chr;
    unsigned    m_sep_len;
    sep_flag    m_sep_flag;
};

//-----------------------------------------------------------------------
tokenizer::tokenizer(const char* sep, 
                     const char* trim,
                     const char* quote,
                     char mask_chr,
                     sep_flag sf) :
    m_src_string(0),
    m_start(0),
    m_sep(sep),
    m_trim(trim),
    m_quote(quote),
    m_mask_chr(mask_chr),
    m_sep_len(sep ? strlen(sep) : 0),
    m_sep_flag(sep ? sf : single)
{
}


//-----------------------------------------------------------------------
tokenizer::token tokenizer::next_token()
{
    unsigned count = 0;
    char quote_chr = 0;
    token tok;

    tok.ptr = 0;
    tok.len = 0;
    if(m_src_string == 0 || m_start == -1) return tok;

    register const char *pstr = m_src_string + m_start;

    if(*pstr == 0) 
    {
        m_start = -1;
        return tok;
    }

    int sep_len = 1;
    if(m_sep_flag == whole_str) sep_len = m_sep_len;

    if(m_sep_flag == multiple)
    {
        while(*pstr && check_chr(m_sep, *pstr)) 
        {
            ++pstr;
            ++m_start;
        }
    }

    if(*pstr == 0) 
    {
        m_start = -1;
        return tok;
    }

    for(count = 0;; ++count) 
    {
        char c = *pstr;
        int found = 0;

        if(quote_chr == 0)
        {
            if(sep_len == 1)
            {
                found = check_chr(m_sep, c);
            }
            else
            {
                found = strncmp(m_sep, pstr, m_sep_len) == 0; 
            }
        }

        ++pstr;

        if(c == 0 || found) 
        {
            if(m_trim)
            {
                while(count && 
                        check_chr(m_trim, m_src_string[m_start]))
                {
                    ++m_start;
                    --count;
                }

                while(count && 
                        check_chr(m_trim, m_src_string[m_start + count - 1]))
                {
                    --count;
                }
            }

            tok.ptr = m_src_string + m_start;
            tok.len = count;

            m_start += count;
            if(c) 
            {
                m_start += sep_len;
                if(m_sep_flag == multiple)
                {
                    while(check_chr(m_sep, m_src_string[m_start])) 
                    {
                        ++m_start;
                    }
                }
            }
            break;
        }

        if(quote_chr == 0)
        {
            if(check_chr(m_quote, c)) 
            {
                quote_chr = c;
                continue;
            }
        }
        else
        {
            if(m_mask_chr && c == m_mask_chr)
            {
                if(*pstr) 
                {
                    ++count;
                    ++pstr;
                }
                continue; 
            }
            if(c == quote_chr) 
            {
                quote_chr = 0;
                continue;
            }
        }
    }
    return tok;
}


int main()
{
    tokenizer tokens(" ", "", "", 0, tokenizer::multiple);
    char dst[100];

    double tm1 = clock();
    for(int i = 0; i < 1000000; ++i)
    {
        tokens.set_str("123 345 asdf 23453 asdfas");
        for(;;)
        {
            tokenizer::token tok = tokens.next_token();
            if(tok.ptr == 0) break;
            if(tok.len)
            {
                // ATTN: DON'T DO THAT! Use std::vector<std::string> instead
                memcpy(dst, tok.ptr, tok.len); 
                dst[tok.len] = 0;
            }
        }
    }
    double tm2 = (clock() - tm1) / CLOCKS_PER_SEC;
    printf("%f\n", tm2);

    return 0;
}


Время: 0.328

IBM Thinkpad T43, Intel Centrino 2GHz
VC7.1
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[19]: BOOST, .NET, String.Split и производительность…
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.09.06 18:12
Оценка:
Здравствуйте, WolfHound, Вы писали:

E>>конструкциями типа std::for_each, std::find_if, std::transform и делать прозрачным более сложный код.

WH>Это называется функции высшего порядка реализованные через зад автогеном.

Мне по барабану, как они называются вообще, а для моего конкретного случая это означало бы, что я не мог бы вызывать внутри алгоритма лямбды на 30-ть строк длиной, а передавал бы в аналог for_each функцию. И вызов:
std::find_if( c.begin(), c.end(), functor )

не сильно отличается от
c.find_if &functor

поскольку тело functor-а и его инициализация определены где-то в другом месте.

VD>>>Кстати, это как раз тот случай когда как раз функции высшего порядка неимоверно "рулят". ООП обычно не дает детализировать алгоритмы, так как оверхэд на описание классов и их методов превышает выигрышь от самой декомпозиции.

E>>Ой-ой-ой. Не поверю.
WH>А зря. Только к проблеме нужно подходить комплексно.

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
pattern matching для питона :)
От: FR  
Дата: 20.09.06 19:47
Оценка: 39 (3)
Здравствуйте, eao197, Вы писали:

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


VD>>Он на Руби пишет, в лучшем случае. А там как и в С++ ООП основное средство декомпозиции. Других практически нет. Одними лямбдами (блоками) сыт не будешь.


E>Ага, а тебе еще паттерн-матчинг добавили. Он рулит покруче ООП и лямб вместе взятых.


Все-таки паттерн матчинг вещь в хозяйстве полезная, неплохо было бы если бы его ввели в питон, да и в руби бы не помешал, притом для ввода например в питон даже не надо больших уж затрат и ломки старого кода, достаточно одного ключевого слова. Ну а пока не ввели, я тут играюсь библиотечными методами, вот например такой эскизик сегодня нарисовал:
class when:
    patterns = []
    
    def __init__(self, expr):
        when.patterns.append(self)
        self.expr = expr

    def __call__(self, func):
        arg0 = tuple(getargspec(func)[0])
        self.func = func
        
        def _wrap(*args):
            d = dict(zip(arg0, args))
            
            for pattern in when.patterns:
                if pattern.func.__name__ == func.__name__ and eval(pattern.expr, globals(), d):
                    return pattern.func(*args)
                 
            raise TypeError("not find pattern: " + repr(d))
        
        return _wrap

использование:
@when("n < 2")
def fib(n):
    return 1

@when("n >= 2")
def fib(n):
    return fib(n - 1) + fib(n - 2)

print fib(8)


@when("a == 0")
def ack(a, b):
    return b + 1

@when("a != 0 and b == 0")
def ack(a, b):
    return ack( a - 1, 1 )

@when("True")
def ack(a, b):
    return ack( a - 1, ack( a, b - 1 ) );

print ack(3, 4)

Так что если очень хочется то и паттерн матчинг можно сделать
Re: pattern matching для питона :)
От: Programmierer AG  
Дата: 21.09.06 07:49
Оценка: +1
FR wrote:
> Так что если очень хочется то и паттерн матчинг можно сделать
Очень забавный фокус, хотя это не паттерн матчинг. Да, похоже на guards,
но в паттерн матчинге важнее выбор пути исполнения в одновременно со
связыванием переменных
, с разбором сложной структуры на части, а
этого в твоем примере ни разу нет.

<offtop>
А по каким словам надо гуглить, чтобы прочитать об этом трюке с @foobar?
Я тут для мелких скриптов начал Питон пробовать, но изучать некогда,
прыгать надо .
</foobar>
Posted via RSDN NNTP Server 2.0
Re[2]: pattern matching для питона :)
От: FR  
Дата: 21.09.06 08:15
Оценка: 7 (1)
Здравствуйте, Programmierer AG, Вы писали:

PA>FR wrote:

>> Так что если очень хочется то и паттерн матчинг можно сделать
PA>Очень забавный фокус, хотя это не паттерн матчинг. Да, похоже на guards,
PA>но в паттерн матчинге важнее выбор пути исполнения в одновременно со
PA>связыванием переменных
, с разбором сложной структуры на части, а
PA>этого в твоем примере ни разу нет.

Угу это скорее ближе к мультиметодам, но упрощает решение тех же задач что паттерн матчинг.
При желании можно и связывание переменных добавить.
А струкуры и сейчас вполне разбираются, аргументом может быть любой логический предикат, при его истиности вызывается связанная функция
@when("isinstance(x, basestring)")
def my_print(x):
    print '<' + x + '>'
       
@when("isinstance(x, list)")
def my_print(x):
    print "["
    for i in x:
        my_print(i)
    print "]"
    
@when("True")
def my_print(x):
    print x


PA><offtop>

PA>А по каким словам надо гуглить, чтобы прочитать об этом трюке с @foobar?
PA>Я тут для мелких скриптов начал Питон пробовать, но изучать некогда,
PA>прыгать надо .
PA></foobar>

По слову decorator.
http://www.python.org/peps/pep-0318.html
Re: pattern matching для питона :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.09.06 08:24
Оценка: 4 (2)
Здравствуйте, FR, Вы писали:

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


Подобные костылики для Ruby придумали: http://www.artima.com/rubycs/articles/patterns_sexp_dsls.html


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[3]: pattern matching для питона :)
От: Programmierer AG  
Дата: 21.09.06 08:49
Оценка:
Здравствуйте, FR, Вы писали:

FR>Угу это скорее ближе к мультиметодам, но упрощает решение тех же задач что паттерн матчинг.

FR>При желании можно и связывание переменных добавить.
FR>А струкуры и сейчас вполне разбираются, аргументом может быть любой логический предикат, при его истиности вызывается связанная функция
Предикат — это не то. Что я буду тебе рассказывать, ты ведь с Хаскелем игрался. Как такое на Питоне изобразить (объединение множеств из стандартной библиотеки Окамла):
let rec union s1 s2 =
      match (s1, s2) with
        (Empty, t2) -> t2
      | (t1, Empty) -> t1
      | (Node(l1, v1, r1, h1), Node(l2, v2, r2, h2)) ->
          if h1 >= h2 then
            if h2 = 1 then add v2 s1 else begin
              let (l2, _, r2) = split v1 s2 in
              join (union l1 l2) v1 (union r1 r2)
            end
          else
            if h1 = 1 then add v1 s2 else begin
              let (l1, _, r1) = split v2 s1 in
              join (union l1 l2) v2 (union r1 r2)
            end


FR>По слову decorator.

FR>http://www.python.org/peps/pep-0318.html
А вот за это — спасибо.
Re[4]: pattern matching для питона :)
От: FR  
Дата: 21.09.06 10:03
Оценка:
Здравствуйте, Programmierer AG, Вы писали:

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


FR>>Угу это скорее ближе к мультиметодам, но упрощает решение тех же задач что паттерн матчинг.

FR>>При желании можно и связывание переменных добавить.
FR>>А струкуры и сейчас вполне разбираются, аргументом может быть любой логический предикат, при его истиности вызывается связанная функция
PA>Предикат — это не то. Что я буду тебе рассказывать, ты ведь с Хаскелем игрался. Как такое на Питоне изобразить (объединение множеств из стандартной библиотеки Окамла):

Просто структуры данных питона очень плохо приспособленны для сопоставления с образцом. Но в принципе решаемо вводом новых типов, с которыми сможет работать сопоставление (аналог variant из nemerle) и плюс адаптеров к встроенным спискам, туплам и т. п. Но это слишком трудоемко Поэтому мне пока более интересно возится с аналогами мультиметодов, они с одной стороны слабее pattern matching'а c другой наооборот мощнее.
Re[2]: pattern matching для питона :)
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 21.09.06 10:47
Оценка: 24 (2)
Здравствуйте, eao197, Вы писали:


E>Подобные костылики для Ruby придумали:


Бывает. Но пользоваться таким я бы не стал.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[3]: pattern matching для питона :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.09.06 12:07
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Бывает. Но пользоваться таким я бы не стал.


Ух-ты! Интереснее, чем в Ruby.

Кстати, Андрей, вопрос в offtopic, а на Smalltalk не GUI-приложения вообще делают, server-side такой жесткий, черный ящик? Не web, про Seaside я знаю.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: pattern matching для питона :)
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 21.09.06 12:34
Оценка: 18 (1)
Здравствуйте, eao197, Вы писали:

E>Кстати, Андрей, вопрос в offtopic, а на Smalltalk не GUI-приложения вообще делают, server-side такой жесткий, черный ящик? Не web, про Seaside я знаю.


Чисто теоретически — никаких ограничений. Для VW идут сразу "безголовые" билды ВМ, то есть ВМ не умеющие работать с графикой. В доке описаны особенности изготовления безголовых приложений и особенности прикручивания к ним гуя назад.
Для Squeak есть опция командной строки, с которой он запускается в безоконном режиме. Хотя там, как я понимаю, фреймбуфер егойный инициализируется всё равно. Кстати, для администрирования удалённых Squeak приложений сделали имплементацию протокола VNC. Типа берёш обычный клиент, подключаешся и смотриш всё, что тебе нужно. Полноту реализиции протокола не знаю, но люди ним практически пользуются.

А чем web-приложение не сервер-сайд?
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[5]: pattern matching для питона :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.09.06 12:37
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>А чем web-приложение не сервер-сайд?


Да самый настоящий. Но это как бы дань моде. Интересно было еще про примеры узнать.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[6]: pattern matching для питона :)
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 21.09.06 13:13
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>Да самый настоящий. Но это как бы дань моде. Интересно было еще про примеры узнать.


На счет не уеб-примеров — это всё таки "заказные" системы. Врядли о них много говорят. Хотя, к примеру, система, которую Бек разрабатывал для Крайслера в замен майнфреймовой системы в предверье миллениума (это с чего началось экстремальное программирование, afair). Сомневаюсь, что это было гуи-приложение. Система управления заводом по производству чипов — опять же, деталей нет но есть стойкое подозрение, что там есть и сервер-сайд компоненты.

Что касается инфраструктуры, то в VW всё есть — и интеграция с CORBA, и облегченный протокол для ST-ST связи и уеб-сервисы. Думаю, что VA тоже не страдает отсутсвием инфраструктуры.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[7]: pattern matching для питона :)
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 21.09.06 14:42
Оценка: 34 (1)
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Что касается инфраструктуры, то в VW всё есть — и интеграция с CORBA, и облегченный протокол для ST-ST связи и уеб-сервисы. Думаю, что VA тоже не страдает отсутсвием инфраструктуры.


Кстати, все доки по VW тут. Изготовление "безголовых" приложений описано в DevGuide. Глава "Creating an Application without a GUI".

В главе "Refactoring" описаны доступные рефакторинги. Это просил Влад, а я забыл сразу ему ссылку кинуть. (Сейчас прочитает и начнёт опять меня в обмане уличать ). Там же было описание Rewrite Rules — "языка" для модификации кода, разработанного Беком в далёком 96гг вместе с RefactoringBrowser-ом, но сейчас я не могу его найти.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[11]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 15:39
Оценка:
Здравствуйте, Denis2005, Вы писали:

D>Понять жизнь можно лишь оглядываясь назад, но жить-то приходится, смотря вперед. (C) Сёрен Кьеркегор


Не тот случай. Как раз С++ делает то, что давно (очень, 30 лет назад) было сделано в других языках. В частности в Лиспе.

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


Язык особой сложностью не обладает. Даже C# имеет более сложный синтаксис и порой более сложную семантику. А вот противоричивость — это да. Что есть того не отнять. Только это даеко не плюс. Это огромный минус. Именно это, и то что язык пытаются расширять не штатнными средствами и приводит к повышению сложности языка. Причем совершенно не поравданной сложности, заметь.

D>Ты же знаешь, сколько времени нужно WG21 X3J16 чтобы принят то или иное решение, особенно если оно касается расширений.


И чьи это проблемы? Это проблемы тех кто сделал ужасный стандарт в 1993-ем и не хотят исправлять своих ошибок сегодня.

D>А сколько пройдет когда реальными компиляторами будет поддерживаться введеное расширение?


Опять же это проблемы дизайна языка. Противоричивость и кривизна его дизайна усложняют компиляторщикам жизнь. Отсюда и задержки. Хотя с последнего стандарта прошло 13 лет. За это время черта лсого можно было сделать. Так что факт недареализованности стандарта основными компиляторами скорее говорит об избыточности и непродуманности стандарта.

Учитывая то что 3 года достаточно для разработки языка с нуля, проблемы С++-ных комитетчиков вообще выглядят очень странно.

D>Вот с библиотекой дела обстоят немного попроще, поэтому на них и делается основной упор.


В библиотеках как мы видим все очень печально. Они просто не могут прыгнуть выше головы. С++ не обладает штатными средствами расширения (за исключением убогих макросов), что приводит к использованию неполноценных нештатных средств. Результат при этом получается удручающий. Ужасное время на компиляцию. Невозможность реализации задуманного на 100%. Ужасно сложная отладка. Никакие сообщения об ошибках. И в добавок огромнеший геморрой при попытках сделать код совместимым с компиляторами разных производителей. В общем, я бы оценил это положение дел как ужасающее.

D>'Горбатый' еще задаст жару молодым неокрепшим умам


Он уже никому ничего не задаст. Он давно перешел в разряд битомолотилки с избыточным синтаксисом. Не удивлюсь если через 10 лет С буедет иметь большую популяроность чем С++.

Сегодняшняя же популярность обуславливается только двумя факторами охринительной разрекламмированностью и человеческими привычками. Они еще долго будут держать С++ в фаворитакх. Вот только проивзодительность руда программистов на этом языке крайне низка. Особенно если речь вести о высококлассных специалистах. И использовать его себе могут позволить только очень богатые конторы (вроде МС и Сана, ну, на худой конец как-нить наш СиБосс и то он себе вубыток работает). Маленькая же контора используя С++ надевает на себя огромный гандикап.

VD>>"Обычными"? Это где они слали обычными? Что-то я такого чуда природы в языках с функциями высшего прядка вообще не видел. И знаешь, мне кажется, что это потому, что фанкторы на фиг не упали.


D>Я сказал обычно, и применительно для C++. В C# 2.0 нормально обхожусь анонимными делегатами.


Вот вот. А C# 2.0 анонимные методы чудовищьно неудобны. Вот в C# 3.0 другое дело.
Так что фанкторы — это самопальный костыль заменяющий то что требуется людям. А бусты — это попытка придать этому костылю приличный вид. Не очень удачная, надо сказать, попытка.

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

VD>>Если в коде присуствует vec.begin() и vec.end() — это уже избыточный код. Ведь работа ведется со всем списком и отдельно указывать его голову так же глупо как на вопрос о расстоянии до объекта начинать давать его координаты и координаты место где ты находишся.

D>За всех говорит не стоит. Частенько бывает, что работа ведется с определенными фрагментами коллекции.


Что значит за всех? Это банальный логический вывод. Если в коде есть vec.begin() и vec.end() одновременно, то это точно перебор всего списка. А раз так, то это явно избыточный код, так как в нем достаточно было бы указать просто "vec".

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


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

В функциональных языках работа со списками является чуть ли не основой возможностью и там давно пришли к выводу, что опереровать нужно понятием "список", а не "открезок". Если есть списко в котором лежат лишние элементы, то сначал проще отфильровать нужные элеметы, а потом уже обработать новый списко. Эффективность от этого нисколько не пострадает.

VD>>В общем, С++, точнее его создатели, нарушили один очень важный принцип KISS. И это его погубит. А пока он не умер, можно извлечь пользу для сбея и своей конторы перейдя на более продуктивный язык и набляюдая как туча ежиков колются, плачут но продолжают с упоением жрать это кактус.


D>

D>Сам пишу пот .NET уже > 4 лет, если задача позволяет, поэтому про ежиков заканчивай.

А что же так? Писали бы на С++. С ним ведь все так здорово!
И ведь донет с C# далеко не лидеры в области выразительности. Сравнение с ним С++ хотя и вглядит тормозом разрабоки, но все же еще как-то смотрится. А вот по сравнению с новыми гибридами вроде Скалы и Немерла он выглядит как недоразумение. Хотя и по сравнению с функциональными языками прошлого вроде Лиспа или ОКамла он тоже выглядит не очень здорово.

Что до "задача позволяет", то лично у меня вообще нет задач которые бы не позволяли использовать дотнет. Думаю, что большинство людей просто недооценивает его (и Явы) возможности.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 16:12
Оценка: +1 :)
Здравствуйте, McSeem2, Вы писали:

MS>Разница в том, что C# не вызывает ntdll по isspace (или какой там аналог?). А сишная библиотека от MS по кой-то фиг вызывает (ну или вызывала, не знаю как оно сейчас).


От МС? А что же тогда на Линусе 20 секунд в лучшем случае? Там тоже МС с ntdll накосявила?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: pattern matching для питона :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 16:12
Оценка:
Здравствуйте, FR, Вы писали:

FR>А струкуры и сейчас вполне разбираются, аргументом может быть любой логический предикат, при его истиности вызывается связанная функция


Ты не понял. Паттерн не всегда являюется придикатом. Даже скажу больше. Хороший паттерн всегд не предикат. Паттерн это описание структуры данных с возможносью задать метапеременные (то есть части этой структуры выразить как wildcards).
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: pattern matching для питона :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 16:12
Оценка:
Здравствуйте, FR, Вы писали:

FR>Просто структуры данных питона очень плохо приспособленны для сопоставления с образцом.


Не "просто", это одна из проблем. Почему ты думаешь при разговоре о паттерн-матчинге все время всплывают алгеброические типы данных (варинаты)? Именно потому, что они сделаны так чтобы по ним можно было делать сложный паттерн-матчинг. Но их наличие это еще не все. Еще нужен ээ... думатель (как точно подметил Ц-Смаил). Этот думатель должен преобразовать паттерн в набор логических предикатов. Это нехилый алгоритм. В Немерле его тупо скомуниздили из одной из реализаций ML-я. Его уже так на коленке не напишишь. Да и в рантайме его отрабатывать слишком накладно.

FR>Но в принципе решаемо вводом новых типов, с которыми сможет работать сопоставление (аналог variant из nemerle) и плюс адаптеров к встроенным спискам, туплам и т. п. Но это слишком трудоемко Поэтому мне пока более интересно возится с аналогами мультиметодов, они с одной стороны слабее pattern matching'а c другой наооборот мощнее.


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

Пойми, паттерн-матчинг только выглядит просто. А внтри это довольно высокотезнологичные алгоритмы.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: pattern matching для питона :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 16:12
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>В главе "Refactoring" описаны доступные рефакторинги. Это просил Влад, а я забыл сразу ему ссылку кинуть. (Сейчас прочитает и начнёт опять меня в обмане уличать ).


О! Не прошло и года. Списибо!

Тогда сразу вопрос. Возьмем к примеру:

Renaming a Method and its References
To rename all implementors of a method, all senders, and all symbols
references, select Rename... from the Method menu.
In addition to strict renaming, this refactoring operation also enables you
to rearrange the method’s parameters. However, when rearranging the
parameters, any symbols that are performed cannot be permuted.


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

Предполжим у мея есть кассы A и B. В обоих содержатся метод MyMethod. Можно ли переименовать метод в классе A на MyMethodEx не трокая метода из класса B и соотвественно корретно исправить все ссылки на переименованный метод.

Если это возможно, то второй вопрос. Как среда отделяет вызовы методов в случае когда например, объект передается в качестве параметра и не ясно что за тип будет у этого объекта?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 21.09.06 16:56
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Не тот случай. Как раз С++ делает то, что давно (очень, 30 лет назад) было сделано в других языках. В частности в Лиспе.


Лисп и С++ создавались для несколько разных целей.
Как говорил Деннис Ричи: "Одни языки создаются для решения задачи, другие для — доказания той или иной точки зрения".
Лисп более относится к последней группы и писать на нем, мягко говоря по труднее чем на С++.

D>>Ты же знаешь, сколько времени нужно WG21 X3J16 чтобы принят то или иное решение, особенно если оно касается расширений.

VD>И чьи это проблемы? Это проблемы тех кто сделал ужасный стандарт в 1993-ем и не хотят исправлять своих ошибок сегодня.

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

VD>Учитывая то что 3 года достаточно для разработки языка с нуля, проблемы С++-ных комитетчиков вообще выглядят очень странно.


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

VD>В библиотеках как мы видим все очень печально. Они просто не могут прыгнуть выше головы. С++ не обладает штатными средствами расширения (за исключением убогих макросов), что приводит к использованию неполноценных нештатных средств. Результат при этом получается удручающий. Ужасное время на компиляцию. Невозможность реализации задуманного на 100%. Ужасно сложная отладка. Никакие сообщения об ошибках. И в добавок огромнеший геморрой при попытках сделать код совместимым с компиляторами разных производителей. В общем, я бы оценил это положение дел как ужасающее.


Об этом много раз уже говорили. Язык сложен, противоречив и т.д. Не нравиться — не пиши, только зачем кричать об этом на каждом углу.

VD>Он уже никому ничего не задаст. Он давно перешел в разряд битомолотилки с избыточным синтаксисом. Не удивлюсь если через 10 лет С буедет иметь большую популяроность чем С++.




VD>Сегодняшняя же популярность обуславливается только двумя факторами охринительной разрекламмированностью и человеческими привычками. Они еще долго будут держать С++ в фаворитакх. Вот только проивзодительность руда программистов на этом языке крайне низка. Особенно если речь вести о высококлассных специалистах. И использовать его себе могут позволить только очень богатые конторы (вроде МС и Сана, ну, на худой конец как-нить наш СиБосс и то он себе вубыток работает). Маленькая же контора используя С++ надевает на себя огромный гандикап.




VD>Вот вот. А C# 2.0 анонимные методы чудовищьно неудобны. Вот в C# 3.0 другое дело.




VD>Так что фанкторы — это самопальный костыль заменяющий то что требуется людям. А бусты — это попытка придать этому костылю приличный вид. Не очень удачная, надо сказать, попытка.


Слишком консервативное заявление, ведь многое зависит от размера/сложности функтора. Да и про декомпозицию не стоит забывать.

Псевдокод:
proc(vec, *func) { // - динамическая передача функтора
        for_each( vec, func() );
}

proc<func>(vec) { // - статическая передача функтора
        for_each( vec, func() );
}


если func — что-то типа выражения {a + _1}, то действительно функтор может быть избыточен.

D>>За всех говорит не стоит. Частенько бывает, что работа ведется с определенными фрагментами коллекции.

VD>Что значит за всех? Это банальный логический вывод. Если в коде есть vec.begin() и vec.end() одновременно, то это точно перебор всего списка. А раз так, то это явно избыточный код, так как в нем достаточно было бы указать просто "vec".

Если уж так хочется, то напиши функцию которая будет инкапсулировать begin()/end().

VD>А что же так? Писали бы на С++. С ним ведь все так здорово!

VD>И ведь донет с C# далеко не лидеры в области выразительности. Сравнение с ним С++ хотя и вглядит тормозом разрабоки, но все же еще как-то смотрится. А вот по сравнению с новыми гибридами вроде Скалы и Немерла он выглядит как недоразумение. Хотя и по сравнению с функциональными языками прошлого вроде Лиспа или ОКамла он тоже выглядит не очень здорово.

Есть задачи которые удобно писать под .NET, и на более простом языке типа C#. Особенно это важно в командных проектах.

VD>Что до "задача позволяет", то лично у меня вообще нет задач которые бы не позволяли использовать дотнет. Думаю, что большинство людей просто недооценивает его (и Явы) возможности.


Попробуй пописать на .NET под GBA (Game Boy Advance) или Nintendo DS, или его где нибудь где он просто не применим.
Mono — не предлагать, по любому ресурсов у обозначенных выше аппаратов не хватит.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 17:23
Оценка: 10 (2)
Здравствуйте, Denis2005, Вы писали:

Ну, раз пошла такая пьянка грех не порекламировать Nemerle .

Вот написал это никчемный тестик. Причем разными спосбами чтобы оценить насколько дорого обходится функционалщина и другие хайтек-изыски в современных языках. Особенноп риятно этот тест сравнивать с вот этоим произведением человеческой мысли .

Сначала результатаы (AMD Атлон 64 3500 (2.2 Ггц):
[123, 345, asdf, 23453, asdfas]
00:00:00.8376620
5000000
00:00:00.2925531
5000000
00:00:00.7282637
5000000

Первый результат — это рукописный Split возвращающий (какой ужас!) динамический списко (то есть на каждый жлемент списка создается по дополнительному объекту с указателем на следующий элемент. Размет каждого доп. объекта 16 байт). Ко всему прочему этот метод строит прямой список для чего ему приходится использовать стек (не использовать концевую рекурсию). Так же для вычисления длинны списка свойство Length делет (ужас то какой!) еще один проход по списку.
Второй результат — это токенайзер возвращающий позицию токена. Интересен он тем, что использует конструкцию yield (то есть является континюэшоном).
Третий результат — это библиотечный метод Split().

А теперь код:
using System.Console;
using  System.Diagnostics.Stopwatch;

module Parse
{
  public Split(this str : string) : list[string]
  {
    def loop(start, i, lst)
    {
      if (i < str.Length)
        match (str[i])
        {
          | ' ' | '\t' => str.Substring(start, i - start) :: loop(i + 1, i + 1, lst)
          | _ => loop(start, i + 1, lst)
        }
      else if (start == i) lst
      else                 [str.Substring(start, i - start)];
    }

    loop(0, 0, []);
  }

  public Tokenize(this str : string) : System.Collections.Generic.IEnumerable[(int * int)]
  {
    def loop(start, i)
    {
      if (i < str.Length)
        match (str[i])
        {
          | ' ' | '\t' =>
            yield (start, i - start);
            loop(i + 1, i + 1)

          | _ => loop(start, i + 1)
        }
      else if (start != i) yield (start, i - start)
      else                 ()
    }

    loop(0, 0);
  }
}

////////////////////////// Далее идут тесты /////////////////////////////////

WriteLine(Parse.Split("123 345 asdf 23453 asdfas"));

/////////////////////////////////////////////////////////////////////////////
// Тестируем сплит написанный что называется в стиле "мама не горюй" (с динамическими списками).
def timer = StartNew();

mutable count = 0;
for(mutable i = 0; i < 1000000; ++i)
  count += Parse.Split("123 345 asdf 23453 asdfas").Length;

WriteLine(timer.Elapsed);
WriteLine(count);

/////////////////////////////////////////////////////////////////////////////
// Тестируем бибилиотечный сплит.
def timer = StartNew();

count = 0;
for(mutable i = 0; i < 1000000; ++i)
  foreach (_ in Parse.Tokenize("123 345 asdf 23453 asdfas"))
    count++;

WriteLine(timer.Elapsed);
WriteLine(count);

/////////////////////////////////////////////////////////////////////////////
// Тестируем токенайзер.
def timer = StartNew();

count = 0;
for(mutable i = 0; i < 1000000; ++i)
  count += "123 345 asdf 23453 asdfas".Split().Length;

WriteLine(timer.Elapsed);
WriteLine(count);

_ = ReadLine();
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 18:00
Оценка: 1 (1)
Здравствуйте, Denis2005, Вы писали:

D>Лисп и С++ создавались для несколько разных целей.

D>Как говорил Деннис Ричи: "Одни языки создаются для решения задачи, другие для — доказания той или иной точки зрения".

А какое отношение Ричи и его миниатюрнинький язычек имеет к С++ и его монструозным порождениям вроде буста?

D>Лисп более относится к последней группы и писать на нем, мягко говоря по труднее чем на С++.


Ой, держите меня семеро. Я сейчас стану защитником Лиспа.

Ты меня извини, то на Лиспе писать то что есть в бусте в 100 раз проще. Язык банально создан для таких вещей. В метапрограммировании он один из лучших.

Как раз Лисп, по твоим словам "созданный для доказания той или иной точки зрения" прекрасно реализует идею "расширения языка за счет библиотек". А С++ тут выглядит очень убого.

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


Элементарно, Ватсон (с). Добавить в язык то что люди безуспешно пытаются прикрутить к нему через одно место. Совместимость от этого не пострадает. К тому же можно ввести некие режимы. Например, в C# можно писать опасный код, но для этого нужно сказтаь об этом компилятору.

D>Я так понимаю ты плохо знаком со стандартом и хронологией его развития.


Да, да. Всегда проще найти проблему в оппоненте. Не признавать же свою неравоту?

D>Кстати стоит учитывать, что это сейчас при уже имеющемся опыте достаточно 3-х лет, но как говорится "всяк силен задним умом".


А что сейчас то изменеилось? Что опыт доступен только избранным? Что мешало проанализировать его 3, 6, 9 лет назад? Он же был. И он никуда не делся и сейчас. Стандарт 0x явно подразумевает что x — это римская 10. Так что время еще есть. Как раз можно успеть к 10-му году если начать работать уже сейчас.

D>Проблема у комитетчиков одна, не развалить до конца, чего и так шатается.


Мне кажется для языка опаснее оставлять все как есть.

D>Об этом много раз уже говорили. Язык сложен, противоречив и т.д. Не нравиться — не пиши, только зачем кричать об этом на каждом углу.


Не нравится. Не пишу. Уже давно. Лет 5 как...

VD>>Так что фанкторы — это самопальный костыль заменяющий то что требуется людям. А бусты — это попытка придать этому костылю приличный вид. Не очень удачная, надо сказать, попытка.


D>Слишком консервативное заявление, ведь многое зависит от размера/сложности функтора. Да и про декомпозицию не стоит забывать.


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

D>Псевдокод:

D>
D>proc(vec, *func) { // - динамическая передача функтора
D>        for_each( vec, func() );
D>}

D>proc<func>(vec) { // - статическая передача функтора
D>        for_each( vec, func() );
D>}
D>


D>если func — что-то типа выражения {a + _1}, то действительно функтор может быть избыточен.


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

D>Если уж так хочется, то напиши функцию которая будет инкапсулировать begin()/end().


А почему ее не написали в библиотеке? Да и как эту инкапсуляцию передавть в те самые функции STD и буста?

D>Есть задачи которые удобно писать под .NET, и на более простом языке типа C#. Особенно это важно в командных проектах.


Ага. Не спорю. Но какие задачи тебе удобно писать на С++? Не уж то ты драйверы пишешь?

D>Попробуй пописать на .NET под GBA (Game Boy Advance) или Nintendo DS, или его где нибудь где он просто не применим.


А ты для них пишешь?

И что С++ это единственный выбор для этих платформ?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: BOOST, .NET, String.Split и производительность…
От: McSeem2 США http://www.antigrain.com
Дата: 21.09.06 18:01
Оценка:
Здравствуйте, VladD2, Вы писали:

MS>>Разница в том, что C# не вызывает ntdll по isspace (или какой там аналог?). А сишная библиотека от MS по кой-то фиг вызывает (ну или вызывала, не знаю как оно сейчас).


VD>От МС? А что же тогда на Линусе 20 секунд в лучшем случае? Там тоже МС с ntdll накосявила?


Влад, ты слова читать умеешь? Напомню, что в моем сообщении речь шла о неком другом случае, а не о split. На Линухе он не проверялся.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[9]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 18:12
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Влад, ты слова читать умеешь? Напомню, что в моем сообщении речь шла о неком другом случае, а не о split. На Линухе он не проверялся.


О како таком другом случае? Я просто уже второй раз тут вижу, что проблемы в МС. Очень интересна эта теория. Люблю, знаете ли, теорию заговора.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: pattern matching для питона :)
От: FR  
Дата: 21.09.06 18:28
Оценка:
Здравствуйте, VladD2, Вы писали:

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


FR>>А струкуры и сейчас вполне разбираются, аргументом может быть любой логический предикат, при его истиности вызывается связанная функция


VD>Ты не понял. Паттерн не всегда являюется придикатом. Даже скажу больше. Хороший паттерн всегд не предикат. Паттерн это описание структуры данных с возможносью задать метапеременные (то есть части этой структуры выразить как wildcards).


Я знаю, пролог изучал правда давно и недавно игрался с языками с паттерн матчингом. Да и не зря я смайлик поставил
Вообще это скорее пример использования скажем так условных мультиметодов
А эта вещь только соприкасается с сопоставлением с образцом, хотя тоже вещь мощная.
Re[6]: pattern matching для питона :)
От: FR  
Дата: 21.09.06 18:28
Оценка:
Здравствуйте, VladD2, Вы писали:

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


FR>>Просто структуры данных питона очень плохо приспособленны для сопоставления с образцом.


VD>Не "просто", это одна из проблем. Почему ты думаешь при разговоре о паттерн-матчинге все время всплывают алгеброические типы данных (варинаты)? Именно потому, что они сделаны так чтобы по ним можно было делать сложный паттерн-матчинг. Но их наличие это еще не все. Еще нужен ээ... думатель (как точно подметил Ц-Смаил). Этот думатель должен преобразовать паттерн в набор логических предикатов. Это нехилый алгоритм. В Немерле его тупо скомуниздили из одной из реализаций ML-я. Его уже так на коленке не напишишь. Да и в рантайме его отрабатывать слишком накладно.


Я знаю (вернее уже почти забыл) как реализовано это в прологе(там вообще примитивно), это не так сложно как кажется. Вернее на порядки проще чем вывод типов. В общем вполне посильная задача.

FR>>Но в принципе решаемо вводом новых типов, с которыми сможет работать сопоставление (аналог variant из nemerle) и плюс адаптеров к встроенным спискам, туплам и т. п. Но это слишком трудоемко Поэтому мне пока более интересно возится с аналогами мультиметодов, они с одной стороны слабее pattern matching'а c другой наооборот мощнее.


VD>В принципе все решаемо. Только это будет уже не Питон, а Гюрза или еще что-то. И решать конечно такие вещи лучше на уровне компилятора, а не на уровне интепретируемого в рантайме метапрограммирования.


Ну эрланг вполне справляется, и в питоне в случае тормозов можно и на си кое что переписать.
Но вообще я пока такую бибилотеку писать не собираюсь, оно хоть и реально, но очень трудоемко
Меня пока устраивают и маленькие трюки типа этого "pattern matching".

VD>Пойми, паттерн-матчинг только выглядит просто. А внтри это довольно высокотезнологичные алгоритмы.


Не совсем, по моему ты переусложняешь.
Re[7]: pattern matching для питона :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 19:03
Оценка: 6 (1)
Здравствуйте, FR, Вы писали:

FR>Я знаю (вернее уже почти забыл) как реализовано это в прологе(там вообще примитивно), это не так сложно как кажется. Вернее на порядки проще чем вывод типов. В общем вполне посильная задача.


Оба алогоритма на одном и том же языке доступны на сйте Немерла. Вывод типоб объемнее, но оно и понятно, он же по всем выражениям работат. К тому же неясно причем тут вывод типов. Питон его вроде как не поддерживал.
http://nemerle.org/svn/nemerle/trunk/ncc/typing/DecisionTreeBuilder.n (28 кил)
http://nemerle.org/svn/nemerle/trunk/ncc/typing/Typer.n (113 кил).

А вот описание http://www.dina.kvl.dk/~sestoft/papers/match.ps.gz (постскрипт)

FR>Ну эрланг вполне справляется, и в питоне в случае тормозов можно и на си кое что переписать.


Насколько мне извесно паттерн-матчинг в Эрналге встроенный и написан не на Эрланге.

FR>Но вообще я пока такую бибилотеку писать не собираюсь, оно хоть и реально, но очень трудоемко


Вот и я о том же. А результат будет скорее всего не очень хорошим.

FR>Не совсем, по моему ты переусложняешь.


Исходники я привел. Причем это резуальтат достигнут с использованием того самого паттерн-матчинга. Без него все будет намного более объемно и сложно.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 19:03
Оценка:
Здравствуйте, VladD2, Вы писали:

VD> Особенноп риятно этот тест сравнивать с вот этоим произведением человеческой мысли .


Пардон. Забыл ссылку дать. Вот этот код мне больше всего понравился. Истенно в духе С++, т.е. пол лохунгом "зато быстро!".
Re: Наколенный вариант 8-летней давности
Автор: McSeem2
Дата: 20.09.06
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 21.09.06 19:06
Оценка:
Здравствуйте, VladD2, Вы писали:

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


MS>>Влад, ты слова читать умеешь? Напомню, что в моем сообщении речь шла о неком другом случае, а не о split. На Линухе он не проверялся.


VD>О како таком другом случае? Я просто уже второй раз тут вижу, что проблемы в МС. Очень интересна эта теория. Люблю, знаете ли, теорию заговора.


Там на самом деле частично виноват ms только не писатели операционки, а те кто писал рантайм к VC. Поэтому та же первоначальная версия теста откомпилированная со STLPort отрабатывает в полтора раза шустрее.
Re[11]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 19:12
Оценка:
Здравствуйте, FR, Вы писали:

FR>Там на самом деле частично виноват ms только не писатели операционки, а те кто писал рантайм к VC. Поэтому та же первоначальная версия теста откомпилированная со STLPort отрабатывает в полтора раза шустрее.


Извини, а 1.5 раза и 30 раз проигрыша C#-e это сравненимые вещи? А под Линуксом что тормоизило?

А может это и правда заговор? Ну, МС специально подкупили всех писателей библиотек?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: BOOST, .NET, String.Split и производительность…
От: McSeem2 США http://www.antigrain.com
Дата: 21.09.06 19:39
Оценка: +4 :)))
Здравствуйте, VladD2, Вы писали:

VD>Пардон. Забыл ссылку дать. Вот этот код мне больше всего понравился. Истенно в духе С++, т.е. пол лохунгом "зато быстро!".

VD>Re: Наколенный вариант 8-летней давности
Автор: McSeem2
Дата: 20.09.06


Если бы ты был чуть более внимательным, то заметил бы, что тот мой код (напомню — востмилетней давности) умеет еще выполнять trim по ходу дела, выделять токены в кавычках любого вида (аргумент "quote") с маскированием (аргумент mask_chr) и работать с тремя типами разделителей:
single — каждый символ является разделителем (1,,,2 выдаст "1" "" "" "2")
multiple — работает как strtok (1,,,2 выдаст "1" "2")
whole_str — разделителем является вся строка

Все это не нужно в рамках задачи данного треда, но при этом и не мешает. Просто я наивно расчитывал на наличие у тебя некоторых зачатков разума.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[2]: BOOST, .NET, String.Split и производительность…
От: CreatorCray  
Дата: 21.09.06 20:15
Оценка: +2
Здравствуйте, VladD2, Вы писали:

VD>Сначала результатаы (AMD Атлон 64 3500 (2.2 Ггц):

VD>
VD>[123, 345, asdf, 23453, asdfas]
VD>00:00:00.8376620
VD>5000000
VD>00:00:00.2925531
VD>5000000
VD>00:00:00.7282637
VD>5000000
VD>


Господа, ну ей богу как дети малые. Ну выводите вы в единых попугаях значения. Например в % от производительности на тестовой платформе самого первого приведенного исходника. Потому как понять, что быстрее — приведенный код на немерлях или написанный на коленке код на языке ЗЮ, если у меня нет немерле?

А то скучно за вашими писькомерянием наблюдать когда не видно у кого короче

ЗЫ: Все считать стёбом (Коим он собстна и является), кроме предложения "унифицировать" оценку производительности алгоритмов
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 22:38
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Если бы ты был чуть более внимательным, то заметил бы, что тот мой код (напомню — востмилетней давности) умеет еще выполнять trim по ходу дела, выделять токены в кавычках любого вида (аргумент "quote") с маскированием (аргумент mask_chr) и работать с тремя типами разделителей:

MS>single — каждый символ является разделителем (1,,,2 выдаст "1" "" "" "2")
MS>multiple — работает как strtok (1,,,2 выдаст "1" "2")
MS>whole_str — разделителем является вся строка

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

MS>Все это не нужно в рамках задачи данного треда, но при этом и не мешает. Просто я наивно расчитывал на наличие у тебя некоторых зачатков разума.


Ага.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.09.06 22:38
Оценка:
Здравствуйте, CreatorCray, Вы писали:

VD>>Сначала результатаы (AMD Атлон 64 3500 (2.2 Ггц):

VD>>
VD>>[123, 345, asdf, 23453, asdfas]
VD>>00:00:00.8376620
VD>>5000000
VD>>00:00:00.2925531
VD>>5000000
VD>>00:00:00.7282637
VD>>5000000
VD>>


CC>Господа, ну ей богу как дети малые. Ну выводите вы в единых попугаях значения. Например в % от производительности на тестовой платформе самого первого приведенного исходника.


А как ты себе это видишь? Вообще-то тест 3 у меня как раз дотнетный сплит. Так что процент можешь посчитать сам.

За одно можно сделать вывод, что 30% производительности легко заменяются 30% стоимости процессора.

CC> Потому как понять, что быстрее — приведенный код на немерлях или написанный на коленке код на языке ЗЮ, если у меня нет немерле?


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

CC>А то скучно за вашими писькомерянием наблюдать когда не видно у кого короче


Откровенно говоря эта пенисометрия меня не волоновала. Меня интересовало насколько велик оверхэд у функционального подхода и итераторов. Ведь писать с их использованием иногда намного приятнее. И если это не так уж дорого стоит, то почему бы и нет. Самый разфункциональный варинт показал скорость куда выше чем тормоза на С++ (те что с библиотекой, а не с хардкодингом). Если мне захочется написать действительно максимально быстрый вариант, то я его напишу. Но он будет менее красив чем эти.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: BOOST, .NET, String.Split и производительность…
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 22.09.06 03:24
Оценка: +1
Здравствуйте, McSeem2, Вы писали:

MS>Напомню, что в моем сообщении речь шла о неком другом случае


вот меня собственно и озадачило, что к рассматриваемому случаю он никаким боком, разве что по MS проехаться
... << RSDN@Home 1.2.0 alpha rev. 655>>
Re[12]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 22.09.06 03:38
Оценка: -1
Здравствуйте, VladD2, Вы писали:

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


FR>>Там на самом деле частично виноват ms только не писатели операционки, а те кто писал рантайм к VC. Поэтому та же первоначальная версия теста откомпилированная со STLPort отрабатывает в полтора раза шустрее.


VD>Извини, а 1.5 раза и 30 раз проигрыша C#-e это сравненимые вещи? А под Линуксом что тормоизило?


Это уже проблемы бустовцев, как умудрились не знаю, мне некогда серъезно разбиратся.
Ну а проблема со строками в рантайме VC это уже вина ms, это тоже надо умудрится лазить без повода в ядро.

VD>А может это и правда заговор? Ну, МС специально подкупили всех писателей библиотек?


Они еще тестерам на линуксе мозги затуманивают так что нолик лишний пропадает
Re[4]: BOOST, .NET, String.Split и производительность…
От: CreatorCray  
Дата: 22.09.06 04:34
Оценка:
Здравствуйте, VladD2, Вы писали:

CC>>Господа, ну ей богу как дети малые. Ну выводите вы в единых попугаях значения. Например в % от производительности на тестовой платформе самого первого приведенного исходника.

VD>А как ты себе это видишь? Вообще-то тест 3 у меня как раз дотнетный сплит. Так что процент можешь посчитать сам.
Я имел в виду ту черепашку на С++ + буст. Которая 20 секунд ползла... Время других тестов выводить как % от времени исполнения этого черепашьего теста на этой же машине.

VD>За одно можно сделать вывод, что 30% производительности легко заменяются 30% стоимости процессора.


CC>> Потому как понять, что быстрее — приведенный код на немерлях или написанный на коленке код на языке ЗЮ, если у меня нет немерле?

VD>На самом, деле на Немерле можно написать код 1 в 1 и даже чуть быстрее чем версия из библоиотеки. Но какой смысл доказвать, что джит работат (просто работает)?
Нененене! Теоретическое доказательство не интересует. Надо практическое. Потому как в теории — практика не отличается от теории. Но на практике — отличается. (С) "не помню кто"

CC>>А то скучно за вашими писькомерянием наблюдать когда не видно у кого короче

VD>Откровенно говоря эта пенисометрия меня не волоновала.
Сама пенисометрия мне тоже по барабану. Мне больше интересно у которого варианта производительность выше, насколько и почему.
VD>тормоза на С++ (те что с библиотекой, а не с хардкодингом).
Т.е. тормоза самого буста...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: BOOST, .NET, String.Split и производительность…
От: FR  
Дата: 22.09.06 04:38
Оценка:
Здравствуйте, VladD2, Вы писали:

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


MS>>Если бы ты был чуть более внимательным, то заметил бы, что тот мой код (напомню — востмилетней давности) умеет еще выполнять trim по ходу дела, выделять токены в кавычках любого вида (аргумент "quote") с маскированием (аргумент mask_chr) и работать с тремя типами разделителей:

MS>>single — каждый символ является разделителем (1,,,2 выдаст "1" "" "" "2")
MS>>multiple — работает как strtok (1,,,2 выдаст "1" "2")
MS>>whole_str — разделителем является вся строка

VD>Мне влом все это выписваать, но я тебяуверяю, что размер кода будет все равно не сопоставим с твоим.


Вообще то вполне сопоставим, эта не та задача на которй можно демонстрировать большие преимущества функциональщины, даже твой вариант в лоб переписанный на C++ не так уж и страшен:
void split(const char *str, list<string> &lst)
{
struct nevermind 
    {
    static void loop(int start, int i, list<string> &lst, const char *str)
        {
        if(str[i])
         {
         if(str[i] == ' ' || str[i] == '\t' ) 
          {
          lst.push_back(string(str, start, i - start));
          loop(i + 1, i + 1, lst, str);
          }
         else loop(start, i + 1, lst, str);         
         }
        else if (start == i) return;
        else {lst.push_back(string(str, start, i - start)); return;}
        }
    };
    
nevermind::loop(0, 0, lst, str);
}


Re[14]: BOOST, .NET, String.Split и производительность…
От: Denis2005 Россия  
Дата: 22.09.06 08:36
Оценка: 1 (1)
Здравствуйте, VladD2, Вы писали:

VD>Ты меня извини, то на Лиспе писать то что есть в бусте в 100 раз проще. Язык банально создан для таких вещей. В метапрограммировании он один из лучших.

VD>Как раз Лисп, по твоим словам "созданный для доказания той или иной точки зрения" прекрасно реализует идею "расширения языка за счет библиотек". А С++ тут выглядит очень убого.

Неспорю, что макросы Лиспа позволяют это делать. Только вот синтаксис глаза режет, всмысле если это можно назвать синтаксисом. Я помню еще давно на отечественной персоналке "Вектор-06Ц" (проц. i8080) баловался с Форт-ом, тоже было интересное занятие, но я бы не стал его использовать в реальных, командных проектах, т.к. не каждый станет свое сознание переворачивать, для того чтобы писать на этом языке.

VD>Элементарно, Ватсон (с). Добавить в язык то что люди безуспешно пытаются прикрутить к нему через одно место. Совместимость от этого не пострадает. К тому же можно ввести некие режимы. Например, в C# можно писать опасный код, но для этого нужно сказтаь об этом компилятору.


Ох, не рассказывай про C# и опысный код (unsafe) . Обычно 'опасные' места пишу на C/C++ и интеропом добираюсь до этой функиональности.

VD>Да, да. Всегда проще найти проблему в оппоненте. Не признавать же свою неравоту?


Какая неправота? Да язык сложен, да в нем куча проблем, но комитет по крайней мере отсеил кучу дибильных предложений (которые существенно могли усугубить положение), которые предлагадись в свое время с неистовым интузиазмом. Почитай "Дизай и эволюция C++", на досуге, а то получается "чукча не читатель — чукча писатель".

VD>А что сейчас то изменеилось? Что опыт доступен только избранным? Что мешало проанализировать его 3, 6, 9 лет назад? Он же был. И он никуда не делся и сейчас. Стандарт 0x явно подразумевает что x — это римская 10. Так что время еще есть. Как раз можно успеть к 10-му году если начать работать уже сейчас.


К 0x никаких существенных изменений не произойдет, если не хотят растерять оставшихся 'пионеров' метапрограммирования.

VD>Мне кажется для языка опаснее оставлять все как есть.


Иногда лучшее действие — это бездействие.

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

VD>Это еще одна ересь навиваемая С-шными корнями. В современных языках отказваются от указателей вообще. То как передавть объект или фунцию должен определять компилятор и/или рантайм. Если они умны, то без проблем могут вообще устранить сам факт передачи. Ведь код в конечном итоге не более чем инструкции процессора, то есть байты/биты.

Всё, извини, но дальнейшее обсуждение темы "функторы сакс" мне надоели.

D>>Если уж так хочется, то напиши функцию которая будет инкапсулировать begin()/end().


VD>А почему ее не написали в библиотеке?


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

VD>Да и как эту инкапсуляцию передавть в те самые функции STD и буста?


Хоть тресни, но я не вижу неудобства в использовании итераторов.

VD>Ага. Не спорю. Но какие задачи тебе удобно писать на С++? Не уж то ты драйверы пишешь?


Драйвера, нет (хотя раньше бывало), а сейчас:
1). порой приходится писать для старых машинок.
2). важные с точти срезния производительности фрагменты (где .NET-кий аллокатор, ведет себя не лучшим образом).

D>>Попробуй пописать на .NET под GBA (Game Boy Advance) или Nintendo DS, или его где нибудь где он просто не применим.

VD>А ты для них пишешь?

Да, немного.

VD>И что С++ это единственный выбор для этих платформ?


Asm, C/C++ (и представь себе STL).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: BOOST, .NET, String.Split и производительность…
От: gid_vvp  
Дата: 22.09.06 08:41
Оценка: 6 (1) +1
Здравствуйте, Denis2005, Вы писали:

D>Доброго времени суток!


D>Понадобилось 'посплитить' строки (вообще задача более сложная, но обо всем по порядку), и по совету “мудрых старцев” (которые по новомодной традиции, при каждом чихе отправляют к boost-у) решил потестировать производительность boost::algoruthm:split.


D>Честно говоря, результаты меня обескуражили…


на сколько я понял очень много жрёт split_iterator который наследуется от find_iterator_base который в свою очередь принимает предикат который внутри хранится... Внимание! вот таким вот образом
typedef function2<
                    match_type, 
                    input_iterator_type, 
                    input_iterator_type> finder_type;
...

private:
                // Finder
                finder_type m_Finder;


и именно этот предикат и делает практически всю работу.

А boost::function это на мой взгляд не самая быстрая вещь.

вот.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: BOOST, .NET, String.Split и производительность…
От: n0name2  
Дата: 22.09.06 15:35
Оценка:
VD>Сначала результатаы (AMD Атлон 64 3500 (2.2 Ггц):
VD>
VD>[123, 345, asdf, 23453, asdfas]
VD>00:00:00.8376620
VD>5000000
VD>00:00:00.2925531
VD>5000000
VD>00:00:00.7282637
VD>5000000
VD>


второй тест некорректен т.к. substring не делает.

вот результаты java. cpu = AMD Opteron 244 (1792.154Mhz). linux. jvm — sun, 1.5.0, 32bit.
используется только одно ядро, плюс надо бы сделать поправку на меньшую частоту камня...

$ java -server -Xmx512m -Xms512m -cp . Test08
5000000
1096.069
5000000
816.764
5000000
799.736
5000000
804.585
5000000
825.1
-------------
5000000
420.443
5000000
400.156
5000000
502.719
5000000
494.193
5000000
492.967



import java.io.*;
import java.util.*;

class Test08 {
    private static int test() {
        int answer = 0;
        final List<String> list = new ArrayList<String>();
        final String text = "123 345 asdf 23453 asdfas".intern();
        for (int i = 0; i < 1000000; i++) {
            list.clear();
            for (final StringTokenizer strtok = new StringTokenizer(text);
                strtok.hasMoreTokens(); list.add(strtok.nextToken())) ;
            answer += list.size();
        }
        return answer;
    }

    private static int test1() throws UnsupportedEncodingException {
        int answer = 0;
        final String [] array = new String[5];
        final String text = "123 345 asdf 23453 asdfas".intern();
        final byte space = " ".getBytes("windows-1251")[0];
        final byte [] chars = text.getBytes("windows-1251");
        final int clen = chars.length;

        for (int i = 0, l = 0; i < 1000000; i++, l = 0) {
            for (int c = 0, x = 0; c < chars.length; c++) {
                if (chars[c] == space) {
                    array[l++] = text.substring(x, c);
                    x = c + 1;
                } else if (c == chars.length - 1 && clen - x > 1) {
                    array[l++] = text.substring(x, clen);
                }
            }
            answer += l;
        }

        return answer;
    }

    public static void x() {
        long start = System.nanoTime();
        System.out.println(test());
        System.out.println((double)(System.nanoTime() - start) / 1.0e6);
    }

    public static void y() throws UnsupportedEncodingException {
        long start = System.nanoTime();
        System.out.println(test1());
        System.out.println((double)(System.nanoTime() - start) / 1.0e6);
    }

    public static void main(String [] args) throws UnsupportedEncodingException {
        for (int i = 0; i < 5; i++) x();
        System.out.println("-------------");
        for (int i = 0; i < 5; i++) y();
    }
}
Re[9]: pattern matching для питона :)
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 22.09.06 16:07
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Можно.
Только маленькое замечание: из-за ключевых сообщений, не может быть два одинаковых метода с разными списками параметров.

VD>Если это возможно, то второй вопрос. Как среда отделяет вызовы методов в случае когда например, объект передается в качестве параметра и не ясно что за тип будет у этого объекта?


/Я могу рассказать только за VW. С другими средами я недостаточно знаком./

Автоматически — никак. Появляется превью откуда можно удалить лишние методы. По практике, переименовать стандартный метод, например, с именем printString (то что toString() в java) — абсолютно нереально. Невозможно и переименовать какой-то метод в другой, если метод с новым именем уже есть выше в иерархии. Это единственное ограничение, которое меня реально бесило. А вот со своими собственными методами проблем возникает мало, из-за того как образуются имена методов в ST. То есть они скорее уникальны чем нет.

Броузер так-же содержит функцию "Spawn" которая умеет открывать броузер в котором виден только отдельный выбранный пакет или иерархия классов. Что удивительно, функции "find senders/find implementors" учитывают эту информацию и ищут только в пределах отображаемого пакета (или нескольких пакетов), а вот рефакторилка эту информацию игнорит. Подозреваю, что поддержка подобного ограничения области видимости удовлетворила бы всех вообще
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[2]: Синтаксический оверхед!
От: Андрей Хропов Россия  
Дата: 22.09.06 20:59
Оценка: 6 (1)
Здравствуйте, VladD2, Вы писали:

VD>for(mutable i = 0; i < 1000000; ++i)

VD> count += Parse.Split("123 345 asdf 23453 asdfas").Length;

А зачем такой синтаксический оверхед?

Надо
repeat(1000000)
    count += Parse.Split("123 345 asdf 23453 asdfas").Length;


или хотя бы

foreach(_ in $[1 .. 1000000])
    count += Parse.Split("123 345 asdf 23453 asdfas").Length;
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: BOOST, .NET, String.Split и производительность…
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.09.06 01:13
Оценка:
Здравствуйте, CreatorCray, Вы писали:

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


Очень похоже на строку из Двенадцати стульев: "Он бескорыстно любил деньги...".

На самом деле тут все очень просто. Языки имеющие компилирующий и оптимизирующий бэкнэнд позволяют написать подобный код с эффективностью близкой к ассемблерной реализации. Разницу до 1.5-2 раз могут составлять вычираемые компиляторами паттерны и качество оптимизации. Оптимальный вариант должен стараться избегать динамического выделения памяти, так как при таком объеме итераций (сентетическом, не реальным), это становится самым узким местом (что во всю присутствует в первом и последнем примере). Вторым узким местом будет использование виртульных методов (что во всю присутствует во втором моем примере). Но все это актуально если нет явных косяков вроде тех что опосредованно присуствуют в С++-коде.

Оптимальный с точки зрения быстродействия код обычно оказывается убогим и не красивым. Так что, как всегда за красоту приходится платить. Вот мне и интересно сколько стоит та самая красота. В бусте она оказалась неприемлемо дорга. А вот потери в дотнете изменяются в процентах, что лично мне кажется приемлемым.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Синтаксический оверхед!
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.09.06 01:13
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Здравствуйте, VladD2, Вы писали:


VD>>for(mutable i = 0; i < 1000000; ++i)

VD>> count += Parse.Split("123 345 asdf 23453 asdfas").Length;

АХ>А зачем такой синтаксический оверхед?


АХ>Надо

АХ>
АХ>repeat(1000000)
АХ>    count += Parse.Split("123 345 asdf 23453 asdfas").Length;
АХ>


Чтобы у людей лишних вопросов не возникало. Откровенно говоря оверхэд в тестах меня не трогает. Намного интереснее как выглядит алгоритм. Вот явщик меня в этом смысле порадовал
Автор: n0name2
Дата: 22.09.06
. Он наверно думает, что доказал кому-то крутость Явы.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: pattern matching для питона :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.09.06 01:13
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Автоматически — никак. Появляется превью откуда можно удалить лишние методы.


Ясно. В очередной раз подтверждается старая истина, что чудес не бывает.

ANS> По практике, переименовать стандартный метод, например, с именем printString (то что toString() в java) — абсолютно нереально. Невозможно и переименовать какой-то метод в другой, если метод с новым именем уже есть выше в иерархии. Это единственное ограничение, которое меня реально бесило. А вот со своими собственными методами проблем возникает мало, из-за того как образуются имена методов в ST. То есть они скорее уникальны чем нет.


То есть в имя метода вы засовываете некую дополнительную информаци? Ясно. Это знакомо по С/С++. Меня как раз порадовало в Яве и дотнете, что в имена не надо ничего лишнего засовывать. Ну, да у СТ свои особенности.

ANS>Броузер так-же содержит функцию "Spawn" которая умеет открывать броузер в котором виден только отдельный выбранный пакет или иерархия классов. Что удивительно, функции "find senders/find implementors" учитывают эту информацию и ищут только в пределах отображаемого пакета (или нескольких пакетов), а вот рефакторилка эту информацию игнорит. Подозреваю, что поддержка подобного ограничения области видимости удовлетворила бы всех вообще


Откровенно говоря куда полезнее было бы все же ввести хоть какую-то аннотацияю типов. Хотя бы для параметров и возвращаемого значения методов. Ну, да это вроде тоже было в Строгтоке и он особо популярным не стал.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: BOOST, .NET, String.Split и производительность…
От: gid_vvp  
Дата: 23.09.06 15:46
Оценка:
Здравствуйте, Denis2005, Вы писали:

D>Доброго времени суток!


D>Понадобилось 'посплитить' строки (вообще задача более сложная, но обо всем по порядку), и по совету “мудрых старцев” (которые по новомодной традиции, при каждом чихе отправляют к boost-у) решил потестировать производительность boost::algoruthm:split.


D>Честно говоря, результаты меня обескуражили…



Я проводил тесты на компютере с процессором AMD Athlon XP 2500+ (частота 1.84 ГГц)

Исходный тест

    {
        int r = 0;

        std::vector<std::string> tokens(5);

        ttPerformanceCounter pc;

        pc.Start();

        for(int i = 0; i < 1000000; i++)
        {
            boost::split(tokens, "123 345 asdf 23453 asdfas", boost::is_any_of(" "));
            r += tokens.size();
        }
        
        double sec = pc.Finish();

        std::cout << "boost::is_any_of " << sec << " sec" << std::endl; 
    }


выполнялся в среднем за 21.1896 сеунды почти то же что и в оригинале

очень медленным оказался boost::is_any_of, скорее всего потому что сепараторы в нём хранятся так std::set<set_value_type> m_Set; и это отягощается тем что в смом split функтор хранится по значению.
при замене boost::is_any_of на

class IsSpace
{
public:
    bool operator()(char c) const
    {
        return c == ' ';
    }
};


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

далее как ранее я писал, в split итераторе для храниения придиката который производит поиск сепараторов использовалась boost::function

замена её на непосредственно сам предикат позволила ещё немного сократить время выполнения
в среднем время выполнения составило 1.7099 секунды

далее ещё заменил аллокатор и вместо вектора взяд std::list

        {
        int r = 0;

        typedef std::basic_string<
                                        char,
                                        std::char_traits<char>
                                        , boost::fast_pool_allocator<char>
                                > fastString;
    
        std::list    <
                         fastString
                        , boost::fast_pool_allocator<fastString>
                    > tokens(5);

        ttPerformanceCounter pc;

        pc.Start();

        for(int i = 0; i < 1000000; i++)
        {            
            boost::split(tokens, "123 345 asdf 23453 asdfas", IsSpace());
            r += tokens.size();
        }
        
        double sec = pc.Finish();

        std::cout << "IsSpace " << sec << " sec" << std::endl; 
    }


в результате в среднем время выполнения составило 1.14366 секунды

вот такие вот дела

там ещё осталось копирование строк лишнее внутри split, но что то я не нашёл красивого и простого способа от этого избавится

так что всё в принципе нормально.. только имело место быть не задумывание автора split над быстродействием
Re[2]: BOOST, .NET, String.Split и производительность…
От: gid_vvp  
Дата: 23.09.06 15:59
Оценка:
а если использовать такую строку как здесь
Автор: Denis2005
Дата: 16.09.06

то в среднем время выполнения 0.5 секунды
[Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,Java,Sca
От: Андрей Хропов Россия  
Дата: 23.09.06 23:22
Оценка: 61 (6) :)
Не удержался от того, чтобы создать новую расширенную версию.

Померил с использованием таймеров (чтобы не учитывать JIT компиляцию)
Вот результаты (усреднены по 10 запускам)
(Pentium M 1,7 Dothan + 768Mb DDR333)
:

Для стандартной библиотеки (и boost как ее продолжение для C++):

  1. D(DMD) — 0.645 сек
  2. D(GDC) — 0.653 сек
  3. С#/Nemerle — 0.870 сек
  4. Boo — 1.003 сек (*)
  5. Python+Psyco — 1.451 сек
  6. Python — 2.182 сек
  7. Java/Scala — 3.470 сек
  8. C++(GCC),boost,list,is_space — 10.045 сек (**)
  9. C++(MS),boost,list,is_space — 12.708 сек (**)

* для Boo почему-то не работает Split(" "), а только Split(),
поэтому неск медленнее

** взят лучший несамодельный вариант

Самоделки :
  1. Nemerle-Tokenizer — 0.738 сек
  2. Nemerle-withLists — 0.896 сек
  3. Java-Bicycle — 1.369 сек
  4. Java-Tokenizer — 2.119 сек
  5. C++(MS),Noname2,list,functor,ref — 2.463 сек (*)
  6. Scala-Tokenizer — 2.642 сек
  7. Scala-withLists — 2.785 сек
  8. C++(GCC),VK,list,functor,val — 3.896 сек (*)

* взят наилучший из самодельных вариантов для данного компилятора

Информация(только новое относительно Re: [Benchmark] DMD быстрее всех
Автор: Андрей Хропов
Дата: 16.09.06
).

Компиляторы:
Boo — Boo Compiler version 0.7.6.2237 (CLR v2.0.50727.42)
Java — Java HotSpot(TM) Client VM (build 1.5.0_08-b03, mixed mode, sharing)
Scala — Scala compiler 2.1.6

Опции:
booc split.boo -optimize+ -o:split-boo.exe
javac split.java
scalac -Xcloselim -Xgenerics split.scala


Исходники:

Boo:
import System;
import System.Diagnostics;

stopwatch = Stopwatch();
stopwatch.Start();

res = 0;

for i in range(1000000):
    res += "123 345 asdf 23453 asdfas".Split().Length;
  
stopwatch.Stop();
      
Console.WriteLine("Boo: res is ${res}, ${stopwatch.Elapsed} elapsed");


Java:
import java.io.*;
import java.util.*;

class splitjava {
    public static void main(String[] args) {
        long start = System.nanoTime();
        
        int res = 0;
        
        for(int i = 0;i < 1000000;i++)
          res += "123 345 asdf 23453 asdfas".split(" ").length;
          
        long stop = System.nanoTime();
        System.out.println("Java-StdLib: res = "  + res + ", " + ((double)(stop - start) / 1.0e6) + " ms elapsed");
    }
}


Scala:
import java.io;
import java.util;

object splitscala {
    def main(args : Array[String]) = {
        val start = System.nanoTime();
        
        var res = 0;
        
        for (val i <- Iterator.range(0, 1000000)) 
          res = res + "123 345 asdf 23453 asdfas".split(" ").length;
          
        val stop = System.nanoTime();
        System.out.println("Scala-StdLib: res = "  + res + ", " + ((stop - start) / 1.0e6) + " ms elapsed");
    }
}


Самоделки:

Nemerle-withLists/Tokenizer (взято отсюда (с) VladD2
Автор: VladD2
Дата: 21.09.06
+ космет. изменения )
using System.Console;
using System.Diagnostics;

module Parse
{
  public SplitToList(this str : string) : list[string]
  {
    def loop(start, i, lst)
    {
      if (i < str.Length)
        match (str[i])
        {
          | ' '  => str.Substring(start, i - start) :: loop(i + 1, i + 1, lst)
          | _ => loop(start, i + 1, lst)
        }
      else if (start == i) lst
      else                 [str.Substring(start, i - start)];
    }

    loop(0, 0, []);
  }

  public Tokenize(this str : string) : System.Collections.Generic.IEnumerable[string]
  {
    def loop(start, i)
    {
      if (i < str.Length)
        match (str[i])
        {
          | ' ' =>
            yield str.Substring(start, i - start);
            loop(i + 1, i + 1)

          | _ => loop(start, i + 1)
        }
      else if (start != i) yield str.Substring(start, i - start)
      else                 ()
    }

    loop(0, 0);
  }
}

////////////////////////// Далее идут тесты /////////////////////////////////

WriteLine(Parse.SplitToList("123 345 asdf 23453 asdfas"));

def stopwatch = Stopwatch();

/////////////////////////////////////////////////////////////////////////////
// Тестируем сплит написанный что называется в стиле "мама не горюй" (с динамическими списками).

stopwatch.Start();

mutable count = 0;
repeat(1000000)
  count += Parse.SplitToList("123 345 asdf 23453 asdfas").Length;
  
stopwatch.Stop();

WriteLine($"Nemerle-withLists: res=$count, $(stopwatch.Elapsed) elapsed");


/////////////////////////////////////////////////////////////////////////////
// Тестируем токенайзер.

stopwatch.Reset();
stopwatch.Start();

count = 0;
repeat(1000000)
  foreach (_ in Parse.Tokenize("123 345 asdf 23453 asdfas"))
    count++;

stopwatch.Stop();

WriteLine($"Nemerle-Tokenizer: res=$count, $(stopwatch.Elapsed) elapsed");



Java-Bicycle/Tokenizer (взято отсюда (с) n0name2
Автор: n0name2
Дата: 22.09.06
и подправлено чтобы было как везде )
import java.io.*;
import java.util.*;

class SplitNoname2 {
    private static int testTokenizer() {
        int answer = 0;
        for (int i = 0; i < 1000000; i++) {
            final List<String> list = new ArrayList<String>();
            final String text = "123 345 asdf 23453 asdfas".intern();
            for (final StringTokenizer strtok = new StringTokenizer(text);
                strtok.hasMoreTokens(); list.add(strtok.nextToken())) ;
            answer += list.size();
        }
        return answer;
    }

    private static int testNoname2() throws UnsupportedEncodingException {
        int answer = 0;
        final byte space = " ".getBytes("windows-1251")[0];
        
        for (int i = 0; i < 1000000; i++) {
            final List<String> array = new ArrayList<String>();
            final String text = "123 345 asdf 23453 asdfas".intern();//.getBytes("windows-1251");
            final int clen = text.length();
            
            for (int c = 0, x = 0; c < clen; c++) {
                if (text.charAt(c) == space) {
                    array.add( text.substring(x, c));
                    x = c + 1;
                } else if (c == clen - 1 && clen - x > 1) {
                    array.add( text.substring(x, clen) );
                }
            }
            answer += array.size();
        }

        return answer;
    }

    public static void main(String [] args) throws UnsupportedEncodingException {
        long start = System.nanoTime();
        int res = testTokenizer();
        long stop = System.nanoTime();
        System.out.println("Java-Tokenizer: res = "  + res + ", " + ((double)(stop - start) / 1.0e6) + " ms elapsed");
        
        start = System.nanoTime();
        res = testNoname2();
        stop = System.nanoTime();
        System.out.println("Java-Noname2: res = "  + res + ", " + ((double)(stop - start) / 1.0e6) + " ms elapsed");
    }
}


Scala-withLists/Tokenizer (взято отсюда (с) VladD2
Автор: VladD2
Дата: 21.09.06
и портировано мной на Scala )
import java.io;
import java.util;
import System.out._

object SplitVlad
{
  def SplitToList(str : String) : List[String] = {
    def loop(start : Int, i : Int, lst : List[String] ) : List[String] = {
      if(i < str.length)
        str(i) match
        {
          case ' '  => str.substring(start, i) :: loop(i + 1, i + 1, lst);
          case _    => loop(start, i + 1, lst);
        }
      else if (start == i) lst;
      else                 List(str.substring(start, i));
    };

    loop(0, 0, Nil);
  }
  
  def Tokenize(str : String) = new Iterator[String]{
    var start : Int = 0
    var i : Int = 0
    var r : String = "";
 
    def hasNext : boolean = 
    {
      if (i < str.length)
          str(i) match
          {
            case ' ' =>
              r = str.substring(start, i);
              i = i + 1; start = i;
              true;
            case _ => 
              i = i + 1;
              hasNext;
          }
      else if (start != i) { r = str.substring(start, i); start = i; true }
      else                 false
    }
    
    def next = r;
  }
 
  def main(args : Array[String]) = {
  
     // check
     print("SplitToList: [");
     for(val s <- SplitToList("123 345 asdf 23453 asdfas") )
        print(s + ",");
     print("]\n");     
     
     print("Tokenizer: [");
     for(val s <- Tokenize("123 345 asdf 23453 asdfas") )
        print(s + ",");
     print("]\n");     
  
    var start = System.nanoTime();
    
    var res = 0;
    
    for (val i <- Iterator.range(0, 1000000)) 
      res = res + SplitToList("123 345 asdf 23453 asdfas").length;
      
    var stop = System.nanoTime();
    println("Scala-SplitToList: res = "  + res + ", " + ((stop - start) / 1.0e6) + " ms elapsed");
    
    start = System.nanoTime();
    
    res = 0;
    
    for (val i <- Iterator.range(0, 1000000)) 
      for(val s <- Tokenize("123 345 asdf 23453 asdfas") )
        res = res + 1;
      
    stop = System.nanoTime();
    println("Scala-Tokenizer: res = "  + res + ", " + ((stop - start) / 1.0e6) + " ms elapsed"); 
  }
}


По сравнению с Nemerle мне показалось менее выразительным:
1) Генераторы реализуются довольно неизящно
2) Для рекурсивно вызываемых функций type inference не работает
3) Синтаксис pattern-matching а более громоздкий


C++: разные варианты с boost + взяты самоделки от VK
Автор: Vermicious Knid
Дата: 17.09.06
и портирована с Java отсюда (с) n0name2
Автор: n0name2
Дата: 22.09.06
+
опробованы и разными вариантами (функторы и функции, передача предикатов по ссылке и по значению):

#include <list>
#include <vector>
#include <string>
#include <iostream>

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>

#include <windows.h> // for GetTickCount

using namespace std;
using namespace boost::algorithm;

class SplitNoname2
{
public:
  template <class C, class P>
  inline static void SplitVal(C& tokens, const string& str, P is_delimiter)
  {
      size_t inpSize = str.size();
      
      for (size_t c = 0, x = 0; c < inpSize; ++c ) {
          if( is_delimiter(str[c]) ) {
              tokens.push_back( str.substr(x,c-x) );
              x = c + 1;
          } else if (c == inpSize - 1 && inpSize - x > 1) {
              tokens.push_back( str.substr(x,inpSize-x) );
          }
      }
  }
  template <class C, class P>
  inline static void SplitRef(C& tokens, const string& str, const P& is_delimiter)
  {
      size_t inpSize = str.size();
      
      for (size_t c = 0, x = 0; c < inpSize; ++c ) {
          if( is_delimiter(str[c]) ) {
              tokens.push_back( str.substr(x,c-x) );
              x = c + 1;
          } else if (c == inpSize - 1 && inpSize - x > 1) {
              tokens.push_back( str.substr(x,inpSize-x) );
          }
      }
  }
};

class SplitVK
{
public:
  template <class C, class P>
  inline static void SplitVal(C& tokens, const string& str, P is_delimiter)
  {
      typename string::const_iterator it = str.begin(), token_start = it, end = str.end();
      for(; it != end; ++it)
      {
          if (is_delimiter(*it))
          {
              if (token_start != it)
                  tokens.push_back(string(token_start, it));
              ++(token_start = it);
          }
      }
      if (token_start != it)
          tokens.push_back(string(token_start, it));
  }
  template <class C, class P>
  inline static void SplitRef(C& tokens, const string& str, const P& is_delimiter)
  {
      typename string::const_iterator it = str.begin(), token_start = it, end = str.end();
      for(; it != end; ++it)
      {
          if (is_delimiter(*it))
          {
              if (token_start != it)
                  tokens.push_back(string(token_start, it));
              ++(token_start = it);
          }
      }
      if (token_start != it)
          tokens.push_back(string(token_start, it));
  }
};

class MyIsSpace
{
public:
  inline bool operator()(char c) const { return c == ' '; } 
};

inline bool myIsSpace(char c){ return c == ' '; }

template<class C, class Pred>
inline void TestBoost( const string& testName, Pred pred )
{
  DWORD start = GetTickCount();
  
  string str = "123 345 asdf 23453 asdfas";

  size_t res = 0;
  for(int i = 0; i < 1000000; i++)
  {
    C tokens; 
    split(tokens, str, pred);
    res += tokens.size();
  }

  DWORD stop = GetTickCount();

  cout << "C++,boost," << testName << ": res is " << res << ',' << stop - start << " ms elapsed\n";
}

template<class Splitter, class C, class Pred>
inline void Test( const string& testName, Pred pred )
{
  DWORD start = GetTickCount();
  
  const string str = "123 345 asdf 23453 asdfas";

  size_t res = 0;
  for(int i = 0; i < 1000000; i++)
  {
    C tokens; 
    Splitter::SplitVal(tokens, str, pred );
    res += tokens.size();
  }

  DWORD stop = GetTickCount();

  cout << "C++," << testName << ",val: res is " << res << ',' << stop - start << " ms elapsed\n";
  
  start = GetTickCount();

  res = 0;
  for(int i = 0; i < 1000000; i++)
  {
    C tokens; 
    Splitter::SplitRef(tokens, str, pred );
    res += tokens.size();
  }

  stop = GetTickCount();

  cout << "C++," << testName << ",ref: res is " << res << ',' << stop - start << " ms elapsed\n";
}

int main()
{
  
  TestBoost< vector<string> >("vector,is_any_of", is_any_of(" ") );
  TestBoost< list<string> >("list,is_any_of", is_any_of(" ") );
  
  TestBoost< vector<string> >("vector,is_space", is_space() );
  TestBoost< list<string> >("list,is_space", is_space() );
  
  TestBoost< vector<string> >("vector,myIsSpace", myIsSpace );
  TestBoost< list<string> >("list,myIsSpace", myIsSpace );
  
  Test< SplitVK,vector<string> >("VK,vector,function", myIsSpace);
  Test< SplitVK,list<string> >("VK,list,function", myIsSpace);
  
  Test< SplitNoname2,vector<string> >("Noname2,vector,function", myIsSpace);
  Test< SplitNoname2,list<string> >("Noname2,list,function", myIsSpace);
  
  Test< SplitVK,vector<string> >("VK,vector,functor", MyIsSpace() );
  Test< SplitVK,list<string> >("VK,list,functor", MyIsSpace() );
  
  Test< SplitNoname2,vector<string> >("Noname2,vector,functor", MyIsSpace() );
  Test< SplitNoname2,list<string> >("Noname2,list,functor", MyIsSpace() );
  
  return 0;
}


а вот полные таблицы результатов для компилятора от MS(VC++ 8) и GCC (3.4.2 под MinGW):

MS:

C++,boost,vector,is_any_of: 23914 ms elapsed
C++,boost,list,is_any_of: 21801 ms elapsed
C++,boost,vector,is_space: 14842 ms elapsed
C++,boost,list,is_space: 12708 ms elapsed
C++,boost,vector,myIsSpace: 7220 ms elapsed
C++,boost,list,myIsSpace: 5298 ms elapsed
C++,VK,vector,function,val: 4887 ms elapsed
C++,VK,vector,function,ref: 4857 ms elapsed
C++,VK,list,function,val: 2594 ms elapsed
C++,VK,list,function,ref: 2613 ms elapsed
C++,Noname2,vector,function,val: 4837 ms elapsed
C++,Noname2,vector,function,ref: 4847 ms elapsed
C++,Noname2,list,function,val: 2554 ms elapsed
C++,Noname2,list,function,ref: 2534 ms elapsed
C++,VK,vector,functor,val: 4797 ms elapsed
C++,VK,vector,functor,ref: 4777 ms elapsed
C++,VK,list,functor,val: 2513 ms elapsed
C++,VK,list,functor,ref: 2514 ms elapsed
C++,Noname2,vector,functor,val: 4747 ms elapsed
C++,Noname2,vector,functor,ref: 4746 ms elapsed
C++,Noname2,list,functor,val: 2474 ms elapsed
C++,Noname2,list,functor,ref: 2463 ms elapsed

GCC:

C++,boost,vector,is_any_of: 16633 ms elapsed
C++,boost,list,is_any_of: 15893 ms elapsed
C++,boost,vector,is_space: 10515 ms elapsed
C++,boost,list,is_space: 10045 ms elapsed
C++,boost,vector,myIsSpace: 7070 ms elapsed
C++,boost,list,myIsSpace: 6329 ms elapsed
C++,VK,vector,function,val: 4737 ms elapsed
C++,VK,vector,function,ref: 4797 ms elapsed
C++,VK,list,function,val: 4076 ms elapsed
C++,VK,list,function,ref: 4036 ms elapsed
C++,Noname2,vector,function,val: 4997 ms elapsed
C++,Noname2,vector,function,ref: 4997 ms elapsed
C++,Noname2,list,function,val: 4246 ms elapsed
C++,Noname2,list,function,ref: 4256 ms elapsed
C++,VK,vector,functor,val: 4647 ms elapsed
C++,VK,vector,functor,ref: 4606 ms elapsed
C++,VK,list,functor,val: 3896 ms elapsed
C++,VK,list,functor,ref: 3946 ms elapsed
C++,Noname2,vector,functor,val: 4887 ms elapsed
C++,Noname2,vector,functor,ref: 4877 ms elapsed
C++,Noname2,list,functor,val: 4116 ms elapsed
C++,Noname2,list,functor,ref: 4196 ms elapsed

Видно, что выгоднее использовать функторы (немного) и намного выгоднее списки (для особенно для MS)

Ну и наконец tokenizer от McSeem2 8-летней давности
Автор: McSeem2
Дата: 20.09.06
выполняется у меня в среднем за

C++(MS),McSeem2 — 0.470 сек
C++(GCC),McSeem2 — 0.713 сек

но он вне зачета поскольку не создает новые строки.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,Java
От: gid_vvp  
Дата: 24.09.06 08:09
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>Не удержался от того, чтобы создать новую расширенную версию.


Вот что выдают твои тесты у меня на компе

тут я только добывал бустовский аллокатор

C++,boost,vector,is_any_of: res is 5000000,21859 ms elapsed
C++,boost,list,is_any_of: res is 5000000,20157 ms elapsed
C++,boost,vector,is_space: res is 5000000,6703 ms elapsed
C++,boost,list,is_space: res is 5000000,5734 ms elapsed
C++,boost,vector,myIsSpace: res is 5000000,5688 ms elapsed
C++,boost,list,myIsSpace: res is 5000000,4703 ms elapsed
C++,boost,vector,MyIsSpace: res is 5000000,5578 ms elapsed
C++,boost,list,MyIsSpace: res is 5000000,4547 ms elapsed
C++,boost,vector,boost::pool,is_any_of: res is 5000000,20750 ms elapsed
C++,boost,list,boost::pool,is_any_of: res is 5000000,18609 ms elapsed
C++,boost,vector,boost::pool,is_space: res is 5000000,6391 ms elapsed
C++,boost,list,boost::pool,is_space: res is 5000000,3906 ms elapsed
C++,boost,vector,boost::pool,myIsSpace: res is 5000000,5375 ms elapsed
C++,boost,list,boost::pool,myIsSpace: res is 5000000,3047 ms elapsed
C++,boost,vector,boost::pool,MyIsSpace: res is 5000000,5234 ms elapsed
C++,boost,list,boost::pool,MyIsSpace: res is 5000000,2860 ms elapsed
C++,VK,vector,function,val: res is 5000000,3593 ms elapsed
C++,VK,vector,function,ref: res is 5000000,3563 ms elapsed
C++,VK,list,function,val: res is 5000000,2250 ms elapsed
C++,VK,list,function,ref: res is 5000000,2281 ms elapsed
C++,Noname2,vector,function,val: res is 5000000,3594 ms elapsed
C++,Noname2,vector,function,ref: res is 5000000,3594 ms elapsed
C++,Noname2,list,function,val: res is 5000000,2406 ms elapsed
C++,Noname2,list,function,ref: res is 5000000,2344 ms elapsed
C++,VK,vector,functor,val: res is 5000000,3437 ms elapsed
C++,VK,vector,functor,ref: res is 5000000,3453 ms elapsed
C++,VK,list,functor,val: res is 5000000,2156 ms elapsed
C++,VK,list,functor,ref: res is 5000000,2157 ms elapsed
C++,Noname2,vector,functor,val: res is 5000000,3515 ms elapsed
C++,Noname2,vector,functor,ref: res is 5000000,3516 ms elapsed
C++,Noname2,list,functor,val: res is 5000000,2266 ms elapsed
C++,Noname2,list,functor,ref: res is 5000000,2265 ms elapsed

а это результаты тех же тустов но на boost::split который я модифицировал таким образом чтоб убрать оттуда boost::function (я писал об этом здесь
Автор: gid_vvp
Дата: 23.09.06
)

C++,boost,vector,is_any_of: res is 5000000,19047 ms elapsed
C++,boost,list,is_any_of: res is 5000000,17594 ms elapsed
C++,boost,vector,is_space: res is 5000000,4593 ms elapsed
C++,boost,list,is_space: res is 5000000,3453 ms elapsed
C++,boost,vector,myIsSpace: res is 5000000,3813 ms elapsed
C++,boost,list,myIsSpace: res is 5000000,2765 ms elapsed
C++,boost,vector,MyIsSpace: res is 5000000,3547 ms elapsed
C++,boost,list,MyIsSpace: res is 5000000,2609 ms elapsed
C++,boost,vector,boost::pool,is_any_of: res is 5000000,18282 ms elapsed
C++,boost,list,boost::pool,is_any_of: res is 5000000,15734 ms elapsed
C++,boost,vector,boost::pool,is_space: res is 5000000,4344 ms elapsed
C++,boost,list,boost::pool,is_space: res is 5000000,2062 ms elapsed
C++,boost,vector,boost::pool,myIsSpace: res is 5000000,3516 ms elapsed
C++,boost,list,boost::pool,myIsSpace: res is 5000000,1312 ms elapsed
C++,boost,vector,boost::pool,MyIsSpace: res is 5000000,3344 ms elapsed
C++,boost,list,boost::pool,MyIsSpace: res is 5000000,1156 ms elapsed
C++,VK,vector,function,val: res is 5000000,3219 ms elapsed
C++,VK,vector,function,ref: res is 5000000,3188 ms elapsed
C++,VK,list,function,val: res is 5000000,2156 ms elapsed
C++,VK,list,function,ref: res is 5000000,2156 ms elapsed
C++,Noname2,vector,function,val: res is 5000000,3375 ms elapsed
C++,Noname2,vector,function,ref: res is 5000000,3375 ms elapsed
C++,Noname2,list,function,val: res is 5000000,2313 ms elapsed
C++,Noname2,list,function,ref: res is 5000000,2390 ms elapsed
C++,VK,vector,functor,val: res is 5000000,3094 ms elapsed
C++,VK,vector,functor,ref: res is 5000000,3094 ms elapsed
C++,VK,list,functor,val: res is 5000000,2078 ms elapsed
C++,VK,list,functor,ref: res is 5000000,2094 ms elapsed
C++,Noname2,vector,functor,val: res is 5000000,3422 ms elapsed
C++,Noname2,vector,functor,ref: res is 5000000,3437 ms elapsed
C++,Noname2,list,functor,val: res is 5000000,2250 ms elapsed
C++,Noname2,list,functor,ref: res is 5000000,2266 ms elapsed

как видно самым быстрым является boost::split (поправленный немного) и std::list с boost::fast_pool_allocator
Re[2]: BOOST, .NET, String.Split и производительность…
От: gid_vvp  
Дата: 24.09.06 08:39
Оценка:
_>так что всё в принципе нормально.. только имело место быть не задумывание автора split над быстродействием

а рекордсменом является вот такое извращение
в среднем 0.74254 sec

struct bad_const_str
{
    const char *begin;
    const char *end;

    bad_const_str()
        : begin(NULL)
        , end(NULL)
    {        
    }

    bad_const_str(const char *first, const char *last)
        : begin(first)
        , end(last)
    {        
    }
};


    {
        int r = 0;


        typedef std::list    <
                        bad_const_str
                        , boost::fast_pool_allocator<bad_const_str>
                    > fastList;

        ttPerformanceCounter pc;

        pc.Start();

        for(int i = 0; i < 1000000; i++)
        {            
            fastList tokens;
            boost::split(tokens, "123 345 asdf 23453 asdfas", IsSpace());
            
            for(fastList::iterator it = tokens.begin(), itEnd = tokens.end(); it != itEnd; ++it)
            {
                std::string str(it->begin, it->end);
                r += str.length();
            }
        }
        
        double sec = pc.Finish();
        
        std::cout << "bad_const_str && IsSpace " << sec << " sec" << ", lenght = " << r << std::endl; 
    }
Re[11]: pattern matching для питона :)
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 25.09.06 06:43
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>То есть в имя метода вы засовываете некую дополнительную информаци? Ясно. Это знакомо по С/С++. Меня как раз порадовало в Яве и дотнете, что в имена не надо ничего лишнего засовывать. Ну, да у СТ свои особенности.


Я бы сказал, что у "ключевых сообщений" имена с доп.информацией получаются сами собой. Ну, типа тех
at: aKey ifAbsent: [...action...]

и
at: aKey ifAbsentPut: [...some value...]


И в Java мне не нравится именно то, что такие "полные" имена смотрятся там очень неестественно.

VD>Откровенно говоря куда полезнее было бы все же ввести хоть какую-то аннотацияю типов. Хотя бы для параметров и возвращаемого значения методов. Ну, да это вроде тоже было в Строгтоке и он особо популярным не стал.


Ну, ему как бы и не дали. Но история не терпит сослагательных наклонений. Так что гадать не будем.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,Java
От: serb Россия  
Дата: 25.09.06 08:45
Оценка:
попробуй пример для Java отсюда
http://www.rsdn.ru/Forum/Message.aspx?mid=2120556&amp;only=1
Автор: Obel
Дата: 21.09.06
Re: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,Java
От: n0name2  
Дата: 25.09.06 09:12
Оценка:
Здравствуйте, Андрей Хропов, Вы писали:

АХ>
  • Java/Scala — 3.470 сек
    АХ>
  • Java-Bicycle — 1.369 сек
    АХ>
  • Java-Tokenizer — 2.119 сек

    несогласен с результатами.

    АХ>Java-Bicycle/Tokenizer (взято отсюда (с) n0name2
    Автор: n0name2
    Дата: 22.09.06
    и подправлено чтобы было как везде )


    если уж вы настаиваете чтобы ArrayList аллоцировался миллион раз — пожалуйста. но, intern() не надо делать в цикле тогда, это JNI вызов и он имеет смысл только в некоторых случаях. кроме того, надо дать JVM несколько секунд на то, чтобы он скомпилировал код (либо проставить специальные флаги в command line). и ОБЯЗАТЕЛЬНО использовать -server.

    вот такой код:


    import java.util.*;
    import java.io.*;
    
    class Test08 {
        private static int test() {
            int answer = 0;
            for (int i = 0; i < 1000000; i++) {
                final List<String> list = new ArrayList<String>();
                final String text = "123 345 asdf 23453 asdfas";
                for (final StringTokenizer strtok = new StringTokenizer(text);
                    strtok.hasMoreTokens(); list.add(strtok.nextToken())) ;
                answer += list.size();
            }
            return answer;
        }
    
        private static int test1() throws UnsupportedEncodingException {
            int answer = 0;
            final char space = " ".charAt(0);
    
            for (int i = 0; i < 1000000; i++) {
                final List<String> list = new ArrayList<String>();
                final String text = "123 345 asdf 23453 asdfas";
                final char [] chars = text.toCharArray();
                final int clen = chars.length;
    
                for (int c = 0, x = 0; c < clen; c++) {
                    if (chars[c] == space) {
                        list.add(text.substring(x, c));
                        x = c + 1;
                    } else if (c == chars.length - 1 && clen - x > 1) {
                        list.add(text.substring(x, clen));
                    }
                }
                answer += list.size();
            }
    
            return answer;
        }
    
        public static void x() {
            long start = System.nanoTime();
            System.out.println(test());
            System.out.println((double)(System.nanoTime() - start) / 1.0e6);
        }
    
        public static void y() throws UnsupportedEncodingException {
            long start = System.nanoTime();
            System.out.println(test1());
            System.out.println((double)(System.nanoTime() - start) / 1.0e6);
        }
    
        public static void main(String [] args) throws UnsupportedEncodingException {
            for (int i = 0; i < 5; i++) x();
            System.out.println("-------------");
            for (int i = 0; i < 5; i++) y();
        }
    }


    результаты на AMD 1.8Ghz

    [denis@ds-3748:~/tmp]$ java -cp . -server -Xmx256m -Xms256m Test08
    5000000
    1070.663
    5000000
    811.254
    5000000
    803.68
    5000000
    806.756
    5000000
    795.188
    -------------
    5000000
    616.175
    5000000
    504.352
    5000000
    504.923
    5000000
    504.356
    5000000
    504.788

    причем, надо смотреть только на последние замеры, первые как раз включают компиляцию байт кода.
  • Re[2]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: n0name2  
    Дата: 25.09.06 09:41
    Оценка:
    лучшего, что смог добиться от вышеприведенного кода, это
    ~631ms — StringTokenizer (в среднем за 20 проходов)
    ~477ms — самописный код (в среднем за 20 проходов)

    на BEA jrockit-R26.4.0 используя коммандную строку java -server -cp . -Xmx256m -Xms256m -XXaggressive:opt Test08

    кстати, я правильно понимаю что D/C/C++ варианты оперирует с 8битными ASCII строками? ИМХО, скорее всего, именно это дает им определенное приемущество.
    Java использует UTF16 и соот-но строка может содержать огромное кол-во кодировок.
    Re[3]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: FR  
    Дата: 25.09.06 10:40
    Оценка: +1
    Здравствуйте, n0name2, Вы писали:


    N>кстати, я правильно понимаю что D/C/C++ варианты оперирует с 8битными ASCII строками? ИМХО, скорее всего, именно это дает им определенное приемущество.


    Проверял на C++ с wstring и L" никакой разницы по скорости.
    При таком мелком размере строки я не удивился бы если бы с wstring было шустрее
    Re[4]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: Obel  
    Дата: 25.09.06 10:55
    Оценка:
    здесь
    Автор: Obel
    Дата: 25.09.06
    Re[5]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: FR  
    Дата: 25.09.06 13:21
    Оценка:
    Здравствуйте, Obel, Вы писали:

    O>здесь
    Автор: Obel
    Дата: 25.09.06


    мужлеж
    Re[6]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: Obel  
    Дата: 25.09.06 14:34
    Оценка:
    Здравствуйте, FR, Вы писали:

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


    O>>здесь
    Автор: Obel
    Дата: 25.09.06


    FR>мужлеж


    Формально все чесно
    Re[3]: BOOST, .NET, String.Split и производительность…
    От: JavaBean Украина  
    Дата: 25.09.06 15:01
    Оценка:
    n0name2 wrote:
    > private static int test() {
    > int answer = 0;
    > final List<String> list = new ArrayList<String>();
    > final String text = "123 345 asdf 23453 asdfas".intern();
    > for (int i = 0; i < 1000000; i++) {
    > list.clear();
    > for (final StringTokenizer strtok = new StringTokenizer(text);
    > strtok.hasMoreTokens(); list.add(strtok.nextToken())) ;
    > answer += list.size();
    > }
    > return answer;
    > }

    Для подсчета количества токенов хватит и такого кода
    private static int test() {
    int answer = 0;
    String text = "123 345 asdf 23453 asdfas";
    for (int i = 0; i < 1000000; i++) {
    final StringTokenizer strtok = new StringTokenizer(text);
    answer += strtok.countTokens();
    }
    return answer;
    }
    Posted via RSDN NNTP Server 2.0
    Re[7]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: FR  
    Дата: 25.09.06 15:01
    Оценка: :)
    Здравствуйте, Obel, Вы писали:

    FR>>мужлеж


    O>Формально все чесно


    Re[3]: [Benchmark] DMD быстрее всех
    Автор: FR
    Дата: 19.09.06


    Xотя если ты тестируешь не сплит а скорость вывода на консоль тогда конечно все честно
    Re[3]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 25.09.06 23:16
    Оценка:
    Здравствуйте, n0name2, Вы писали:

    N>кстати, я правильно понимаю что D/C/C++ варианты оперирует с 8битными ASCII строками? ИМХО, скорее всего, именно это дает им определенное приемущество.

    N>Java использует UTF16 и соот-но строка может содержать огромное кол-во кодировок.

    Думаю все проще. D или вооще не использует GC для локальных строк или его GC очень примитивен и на таких тестах дает выигрышь. А Явский GC рассчитан на рботу с огромными массивми объектов и на таких примитивных задачах себя проявить не может.

    А вообще приводить результаты тестов без указания процессоров это очень правильно.
    ... << RSDN@Home 1.2.0 alpha rev. 637>>
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[2]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: JavaBean Украина  
    Дата: 26.09.06 07:17
    Оценка:
    n0name2 wrote:
    > class Test08 {
    > private static int test() {
    > int answer = 0;
    > for (int i = 0; i < 1000000; i++) {
    > final List<String> list = new ArrayList<String>();
    > final String text = "123 345 asdf 23453 asdfas";
    > for (final StringTokenizer strtok = new StringTokenizer(text);
    > strtok.hasMoreTokens(); list.add(strtok.nextToken())) ;
    > answer += list.size();
    > }
    > return answer;
    > }
    Во всех примерах был только подсчет токенов и не нужно было
    инициализировать никаких масивов поэтому еще раз говорю — нужно просто
    использовать конструкцию вида
    final StringTokenizer strtok = new StringTokenizer(text);
    answer += strtok.countTokens();
    Posted via RSDN NNTP Server 2.0
    Re[4]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: n0name2  
    Дата: 26.09.06 08:45
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    N>>кстати, я правильно понимаю что D/C/C++ варианты оперирует с 8битными ASCII строками? ИМХО, скорее всего, именно это дает им определенное приемущество.

    N>>Java использует UTF16 и соот-но строка может содержать огромное кол-во кодировок.
    VD>Думаю все проще. D или вооще не использует GC для локальных строк или его GC очень примитивен и на таких тестах дает выигрышь. А Явский GC рассчитан на рботу с огромными массивми объектов и на таких примитивных задачах себя проявить не может.

    на самом деле процент CPU который занимает GC в данном тесте ничтожно мал т.к. живые объекты в некий момент времени можно посчитать по пальцам (StringTokenizer, ArrayList и максимум пяток строк). Если версия с разрядностью символов отпадает, то у меня остается версия с тем, что в C/C++ строки можно аллоцировать на стеке. К сожалению, в Java6 не успели в Mustang включить данную фичу и Escape Analysis используется пока только для удаления неиспользуемых synchronized блоков (что, конечно, тоже хорошо, но, в микробенчмарках не всегда получается это показать)...

    VD>А вообще приводить результаты тестов без указания процессоров это очень правильно.


    Процессор я вообще-то указывал выше: AMD Opteron(tm) Processor 244, 1.8Ghz, 1Mb L2, bogomips 3589.22

    Кстати, удалось еще немного выжать из вышеприведенного кода задействовав TLA по полной программе (Thread Local Allocation, т.е. объекты аллоцируются не в общей куче а в отдельной для каждого потока см. http://edocs.bea.com/jrockit/geninfo/memman/concepts.html)

    [denis@ds-3748:~/tmp]$ time /usr/java/jrockit-R26.4.0-jdk1.5.0_06/bin/java -server -cp . -Xmx256m -Xms256m -XXaggressive -XgcReport -XXthroughputCompaction -XXlargeObjectLimit6K -XXtlaSize128k Test08
    583.8475263999999
    392.6505215999998
    [memory ]
    [memory ] Memory usage report
    [memory ]
    [memory ] old collections
    [memory ] number of collections = 86
    [memory ] total promoted = 0 (size 0)
    [memory ] max promoted = 0 (size 0)
    [memory ] total GC time = 0.597 s (pause 0.597 s)
    [memory ] mean GC time = 6.945 ms (pause 6.945 ms)
    [memory ] maximum GC Pauses = 11.461 , 13.531, 32.736 ms
    [memory ]
    [memory ] number of parallel mark phases = 86
    [memory ] number of parallel sweep phases = 86
    real 0m53.842s
    user 0m54.408s
    sys 0m0.560s

    GC занял всего 0.6сек из 54сек, второе ядро практически не использовалось т.к. user > real всего на 0.8сек.

    [denis@ds-3748:~/tmp]$ /usr/java/jrockit-R26.4.0-jdk1.5.0_06/bin/java -server -version
    java version "1.5.0_06"
    Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
    BEA JRockit(R) (build R26.4.0-63-63688-1.5.0_06-20060626-2259-linux-ia32, )

    [denis@ds-3748:~/tmp]$ uname -a
    Linux ****** 2.6.9-34.ELsmp #1 SMP Fri Feb 24 16:54:53 EST 2006 i686 athlon i386 GNU/Linux



    JavaBean,
    .countTokens() использовать нельзя т.к. тестируется не подсчет кол-ва токенов а именно split на список строк.
    Re[5]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 26.09.06 13:24
    Оценка:
    Здравствуйте, n0name2, Вы писали:

    N>на самом деле процент CPU который занимает GC в данном тесте ничтожно мал т.к. живые объекты в некий момент времени можно посчитать по пальцам (StringTokenizer, ArrayList и максимум пяток строк).


    На самом деле (с) GC жрет время не только во время сборки мусора, но и во время выделения памяти. Он рассчитан на работу в многопоточной среде и делает блокировки. Так что если сокнурент не делает блокировок или вообще использует стэк для хранения результатов, то скорость у него будет значительно выше. Но это в таких примитивных тестах. А в реальных условиях все компенсируется.
    ... << RSDN@Home 1.2.0 alpha rev. 637>>
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[6]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: n0name2  
    Дата: 26.09.06 14:33
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>На самом деле (с) GC жрет время не только во время сборки мусора, но и во время выделения памяти. Он рассчитан на работу в многопоточной среде и делает блокировки. Так что если сокнурент не делает блокировок или вообще использует стэк для хранения результатов, то скорость у него будет значительно выше. Но это в таких примитивных тестах. А в реальных условиях все компенсируется.


    собственно, за счет TLA удалось улучшить время исполнения с ~500ms до ~400ms. ну, и за счет некоторых других опций (в т.ч. другой стратегии memory compactification).

    The allocating Java thread requests a thread-local area (TLA) from the nursery (generational garbage collector) or from the heap (single-generational garbage collector) for allocation of these objects. The TLA is reserved from the heap or the nursery and given to the thread for exclusive use. This allows the thread to allocate small objects in its own TLA without taking any kind of lock. When the TLA gets full the thread simply requests a new TLA.


    a thread will try to allocate the object in the currently held TLA. It puts the object at the beginning of the free space in the TLA and moves the free space pointer forward to the end of the object.


    плюс ко всему и строки несколько по другому по сравнению с C работают, сама строка это ссылка на массив char [], плюс индекс начала и длинна а не просто ссылка на данные. всякие runtime проверки на индекс в массиве и т.д.
    Re[7]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 26.09.06 14:58
    Оценка: +1
    Здравствуйте, n0name2, Вы писали:

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


    VD>>На самом деле (с) GC жрет время не только во время сборки мусора, но и во время выделения памяти. Он рассчитан на работу в многопоточной среде и делает блокировки. Так что если сокнурент не делает блокировок или вообще использует стэк для хранения результатов, то скорость у него будет значительно выше. Но это в таких примитивных тестах. А в реальных условиях все компенсируется.


    N>собственно, за счет TLA удалось улучшить время исполнения с ~500ms до ~400ms.


    Исходников не вижу, так что и сказать ничего не могу. Но TLA (это видимо то что под Виндовс назвается LTS, т.е. локальное хранилище потока), тоже не беслатное. Оно значительно медленее стековой переменной. Так что на С всегда можено сделать чуточку быстрее.

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

    С++ в таких тестах перегнать практически невозможно, так как на нем всегда можно скатитсья в С-стиль с оптимизацией каждого бита. Вот только это неоправданно дорого и бессмысленно.
    ... << RSDN@Home 1.2.0 alpha rev. 637>>
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[8]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: n0name2  
    Дата: 26.09.06 15:18
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>Исходников не вижу, так что и сказать ничего не могу. Но TLA (это видимо то что под Виндовс назвается LTS, т.е. локальное хранилище потока), тоже не беслатное. Оно значительно медленее стековой переменной. Так что на С всегда можено сделать чуточку быстрее.


    с т.з. исходников использование TLA (в BEA имплементации JVM) или TLAB (так это называется в Sun имплементации JVM) полностью прозрачно. т.е. обчыный new делается не в основном heap а в TLA cache. виндовые TLS требуют явного использования, да и это несколько другая фишка вообще.

    насколько я понимаю, Windows TLS http://windowssdk.msdn.microsoft.com/en-us/library/ms686749.aspx это слоты, в которых можно записывать некие значения, а аллоцировать собственно память нужно отдельно.

    TLA/TLAB в Java это просто способ аллокации памяти, когда потоку выделяется сразу большой кусок памяти (скажем, 512kb) и после этого он внутри его аллоцирует мелкие объекты вроде строк, массивов и т.п. причем, уже нет необходимости синхронизировать аллокацию с другими потоками.

    VD>Вот только кому это нужно. Код подобных оптимизаций неприлично большой.


    как раз Sun придерживается той политики что такого рода оптимизации происходят на 100% внутри JVM и программисты об этом думать не должны в момент написания кода. именно поэтому value типы не были реализованы, по мнению Sun это должно (и будет) делаться с помощью escape analysis.
    Re[12]: BOOST, .NET, String.Split и производительность…
    От: vdimas Россия  
    Дата: 26.09.06 18:26
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    FR>>Там на самом деле частично виноват ms только не писатели операционки, а те кто писал рантайм к VC. Поэтому та же первоначальная версия теста откомпилированная со STLPort отрабатывает в полтора раза шустрее.


    VD>Извини, а 1.5 раза и 30 раз проигрыша C#-e это сравненимые вещи? А под Линуксом что тормоизило?


    VD>А может это и правда заговор? Ну, МС специально подкупили всех писателей библиотек?


    Я малость недоумеваю. Вы тут всерьез спорите или как? В С++ строки передаются по значению, то бишь копируются (В C# — по ссылке). Причем, каждый раз создается копия в стандартной куче. Кстати, никто не догадался прогнать этот тест ну хотя бы в однопоточной версии CTR? Или прикрутить минимальный аллокатор для локальной кучи (можно в виндах получить кучу в свое единоличное распоряжение). Там же блокировка происходит каждый раз при обращении к стандартному пулу памяти.

    И для таких задач, как правильно заметили, есть const_string. Но опять же, выигрышь будет только со локальным, по отношению к треду, пулом памяти, где брать и возвращать память можно без блокировок.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[3]: BOOST, .NET, String.Split и производительность…
    От: vdimas Россия  
    Дата: 26.09.06 18:26
    Оценка:
    Здравствуйте, FR, Вы писали:

    А попробуй, плиз, то же самое, но для однопоточной версии рантайма.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[4]: BOOST, .NET, String.Split и производительность…
    От: vdimas Россия  
    Дата: 26.09.06 18:26
    Оценка:
    Здравствуйте, eao197, Вы писали:

    E>Ну мужики, я ведь только заглянул в split и увидел большое количество копирований предиката. А дальше я не смотрел. Очень вероятно, что сам алгоритм поиска и выделения подстрок грешит таким же избыточным количеством копирований и передачи аргументов по значению.


    Да, предикаты должны иметь нулевые издержки при копировании. В STL те же грабли. Либо можно явно указывать не сам тип предиката, а константную ссылку на него. Т.е. создать предикат на стеке, а при вызове ф-ции явно указать тип константной ссылки на предикат в аргументах шаблона.

    Ну и так же я опять прошу проверить это все на однопоточной версии рантайма.
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[8]: BOOST, .NET, String.Split и производительность…
    От: vdimas Россия  
    Дата: 26.09.06 18:26
    Оценка: :)
    Здравствуйте, WolfHound, Вы писали:


    WH>Вот скажи мне на сколько часто тебе нужны такая лямюбда? Мне нужно как минимум обратится к челену класса, а с этим уже все не так красиво... А если нужно както так Obj.Prop1.Prop2.Prop3 то вобще тушите свет.

    WH>Короче для людей которые использовали нормальную лямбду очевидно что boost::lambda непригодно для реальной работы.

    Уже обсуждали. Бустовская лямбда хороша для мелких вещей по-месту. Для "крупных" нет проблем нарисовать 2 лишние строки для введения своего функтора:
    struct MyFunctor {}
    и в нем
    void operator()(arg&) {...}
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[9]: BOOST, .NET, String.Split и производительность…
    От: WolfHound  
    Дата: 26.09.06 18:34
    Оценка:
    Здравствуйте, vdimas, Вы писали:

    V>Уже обсуждали. Бустовская лямбда хороша для мелких вещей по-месту. Для "крупных" нет проблем нарисовать 2 лишние строки для введения своего функтора:

    А Obj.Prop1.Prop2.Prop3 это крупный или мелкий случай?
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Пусть это будет просто:
    просто, как только можно,
    но не проще.
    (C) А. Эйнштейн
    Re[10]: BOOST, .NET, String.Split и производительность…
    От: vdimas Россия  
    Дата: 26.09.06 19:43
    Оценка: 6 (1)
    Здравствуйте, WolfHound, Вы писали:

    V>>Уже обсуждали. Бустовская лямбда хороша для мелких вещей по-месту. Для "крупных" нет проблем нарисовать 2 лишние строки для введения своего функтора:

    WH>А Obj.Prop1.Prop2.Prop3 это крупный или мелкий случай?

    для этого есть var().

    In sum, var(x) creates a nullary lambda functor, which stores a reference to the variable x. When the lambda functor is invoked, a reference to x is returned.


    юзать так:
    var(obj).Prop1.Prop2


    Что характерно, так это вот такая особенность:
    var(obj.Prop1).Prop2


    Понял, в чем прикол?
    В общем, var явным образом определяет границы замыкания.
    Как такое уточненное замыкание на C# сделать? Я не знаю (кроме как путем превращения мелкого однострочного случая в многострочный путем введения дополнительных "закрываемых" переменных).

    А на Nemerle как это сделать элегантно?


    -----------
    Есть еще constant() для обратного: для насильного вычисления аргумента в момент создания замыкания.

    И кстати, lambda-выражения в этой либе можно делать многострочными, с сохранениями промежуточных результатов. Для этого есть еще пара хелперов: var_type и constant_type. (Я что-то не видел примеров здесь на RSDN, наверно мужики не в курсе )
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[3]: [Benchmark] DMD быстрее всех
    От: R.K. Украина  
    Дата: 26.09.06 19:53
    Оценка:
    Здравствуйте, cattus, Вы писали:

    АХ>>Померил с использованием таймеров (чтобы не учитывать JIT компиляцию)

    АХ>>Вот результаты (усреднены по 10 запускам)
    АХ>>(Athlon XP 1700+ @ 1.5 GHZ + 512Mb DDR266)
    АХ>>:

    АХ>>1) DMD — 0.775 сек

    АХ>>2) GDC — 0.905 сек
    АХ>>3) С#/Nemerle — 1.1 сек
    АХ>>4) Python — 3.48 сек
    АХ>>5) Python+Psyco — 4.12 (не ускорил!)
    АХ>>6) GCC + Boost — 22.5 сек
    АХ>>7) MS VC++ + Boost — 35 сек

    C>Вот еще одно подтверждение изначальной ущербности теста. Прошу сильно не пинать за код -- я очень долго ничего не писал на Haskell'е.


    Достаточно такого:
    mapM_ (return.length.words) $ replicate 1000000 "123 345 asdf 23453 asdfas"

    На P4-2.8: (0.19 secs, 126628556 bytes), для 10 млн. строк — (1.89 secs, 1281372792 bytes)
    You aren't expected to absorb this
    Re[4]: BOOST, .NET, String.Split и производительность…
    От: FR  
    Дата: 26.09.06 20:32
    Оценка:
    Здравствуйте, vdimas, Вы писали:

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


    V>А попробуй, плиз, то же самое, но для однопоточной версии рантайма.


    Попробовал почему-то примерно на 10% медленей (VC7.1)
    Re[13]: BOOST, .NET, String.Split и производительность…
    От: FR  
    Дата: 26.09.06 20:32
    Оценка:
    Здравствуйте, vdimas, Вы писали:

    V>Я малость недоумеваю. Вы тут всерьез спорите или как? В С++ строки передаются по значению, то бишь копируются (В C# — по ссылке). Причем, каждый раз создается копия в стандартной куче. Кстати, никто не догадался прогнать этот тест ну хотя бы в однопоточной версии CTR? Или прикрутить минимальный аллокатор для локальной кучи (можно в виндах получить кучу в свое единоличное распоряжение). Там же блокировка происходит каждый раз при обращении к стандартному пулу памяти.


    boost::pool прикручивал польза близкая к нулю.
    Re[11]: BOOST, .NET, String.Split и производительность…
    От: Vermicious Knid  
    Дата: 27.09.06 01:57
    Оценка: +3
    Здравствуйте, vdimas, Вы писали:

    WH>>А Obj.Prop1.Prop2.Prop3 это крупный или мелкий случай?

    V>для этого есть var().
    Я думаю WolfHound совсем не "это" имел в виду. Он говорил о доступе к членам параметра лямбды. А с этим у boost::lambda совсем туго, и иначе и быть не может. Вместо таких безобразий:
    _1 ->* &B::foo
    bind(&A::data, _1)

    На Nemerle можно написать:
    _.foo
    _.data

    Что делать в случае obj.Prop1.Prop2.Prop3 для boost::lambda я затрудняюсь сказать, но что-то мне подсказывает, что ничего хорошего сделать здесь нельзя. А вот на Nemerle это просто:
    obj => obj.Prop1.Prop2.Prop3


    V>Понял, в чем прикол?

    V>В общем, var явным образом определяет границы замыкания.
    Скорее var здесь создает иллюзию замыкания. Если значение, на которое этот var ссылается умрет, то думаю все накроется медным тазом. А если подсунуть ему rvalue, то просто не скомпилируется.

    V>А на Nemerle как это сделать элегантно?

    По-моему на Nemerle лучше "этого" не делать, так как весьма сомнительная это вещь. Ничего кроме усложнения понимания кода она не несет.

    Вот скажем слегка измененный пример из документации:
    int index = 0; 
    for_each(a.end(), a.end(), cout << ++index << ':' << _1 << '\n');

    Нормальная лямбда с нормальными замыканиями не напечатала бы ничего. А это недоразумение естественно напечатает 1:. А var это всего лишь костыль для частичного обхода подобных случаев.

    Так что не нужно нам таких "элегантных" способов. В Nemerle есть нормальные замыкания, а если понадобится подобная сомнительная вещь, то можно будет сделать — язык вполне позволяет.
    Re[11]: BOOST, .NET, String.Split и производительность…
    От: night beast СССР  
    Дата: 27.09.06 04:24
    Оценка: +1 :)
    Здравствуйте, vdimas, Вы писали:

    V>>>Уже обсуждали. Бустовская лямбда хороша для мелких вещей по-месту. Для "крупных" нет проблем нарисовать 2 лишние строки для введения своего функтора:

    WH>>А Obj.Prop1.Prop2.Prop3 это крупный или мелкий случай?

    V>для этого есть var().


    V>

    V>In sum, var(x) creates a nullary lambda functor, which stores a reference to the variable x. When the lambda functor is invoked, a reference to x is returned.


    V>юзать так:

    V>
    V>var(obj).Prop1.Prop2
    V>


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

    V>Что характерно, так это вот такая особенность:

    V>
    V>var(obj.Prop1).Prop2
    V>


    V>Понял, в чем прикол?


    я не понял.

    V>И кстати, lambda-выражения в этой либе можно делать многострочными, с сохранениями промежуточных результатов. Для этого есть еще пара хелперов: var_type и constant_type. (Я что-то не видел примеров здесь на RSDN, наверно мужики не в курсе )


    наверно потому что это выглядит ужасно
    Re[5]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: JavaBean Украина  
    Дата: 27.09.06 07:32
    Оценка:
    n0name2 wrote:
    > JavaBean,
    > .countTokens() использовать нельзя т.к. тестируется не подсчет кол-ва
    > токенов а именно split на список строк.
    Учел твои пожелания
         private static int test() {
             int answer = 0;
             for (int i = 0; i < 1000000; i++) {
                 answer+=StringUtils.split("123 345 asdf 23453 asdfas", " 
    ").length;
             }
             return answer;
         }

    Для сплита была взята либа commons lang 2.1

    5000000
    1139.989
    Posted via RSDN NNTP Server 2.0
    Re[6]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
    От: n0name2  
    Дата: 27.09.06 07:51
    Оценка:
    Здравствуйте, JavaBean, Вы писали:

    JB> answer+=StringUtils.split("123 345 asdf 23453 asdfas", "

    JB>Для сплита была взята либа commons lang 2.1
    JB>5000000
    JB>1139.989

    это очень медленно. мой рекорд на JRockit с StringTokenizer — 583ms, без него — 392ms
    Re[12]: BOOST, .NET, String.Split и производительность…
    От: vdimas Россия  
    Дата: 27.09.06 10:55
    Оценка:
    Здравствуйте, night beast, Вы писали:


    V>>юзать так:

    V>>
    V>>var(obj).Prop1.Prop2
    V>>


    NB>так юзать не получится

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

    А как-то так:
    template<typename T>
    var_type<T&>::type lvar(T& obj) { return obj; }

    и подставить lvar в приведенный пример? (нет под рукой компилятора, не проверил)
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[13]: BOOST, .NET, String.Split и производительность…
    От: night beast СССР  
    Дата: 27.09.06 11:51
    Оценка: 16 (1)
    Здравствуйте, vdimas, Вы писали:

    V>>>юзать так:

    V>>>
    V>>>var(obj).Prop1.Prop2
    V>>>


    NB>>так юзать не получится

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

    V>А как-то так:

    V>
    V>template<typename T>
    V>var_type<T&>::type lvar(T& obj) { return obj; }
    V>

    V>и подставить lvar в приведенный пример?

    дык та же фигня, только в профиль.
    var — это функция которая возвращает объект типа lambda_functor< identity<T&> > (var_type<T>::type это тайпдеф этого-же типа).
    так-вот, в типе lambda_functor нет никаких переменных Prop1.
    сделать то, что ты написал в си нельзя. даже макросами.
    извращаются через бинд
    bind(&A::Prop1, _1);

    такие дела
    Re[14]: BOOST, .NET, String.Split и производительность…
    От: vdimas Россия  
    Дата: 29.09.06 09:50
    Оценка: +1
    Здравствуйте, WolfHound, Вы писали:

    WH>Автор маньякЪ!

    WH>Мне лень разбиратся но у меня такое чувство что ты гдето нетак провел декомпозицию.
    WH>У меня никогда не возникало жилания сделать такие функторы.

    Вообще-то нет. Посмотри, там действительно несколько вложенных if-ов. Имеет ли смысл их декомпозировать? У меня бывают участки подобного if-кода и подлиннее, особенно в той самой логике, котору почему-то называют "бизнес-". (когда позволяют типы аргументов, то это делается через switch-case, но суть не меняется).
    ... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
    Re[15]: BOOST, .NET, String.Split и производительность…
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 29.09.06 17:44
    Оценка:
    Здравствуйте, vdimas, Вы писали:

    V>Вообще-то нет. Посмотри, там действительно несколько вложенных if-ов. Имеет ли смысл их декомпозировать?


    Имеет, если в языке есть средства которыми это можно сделать. В С++ с ними туго, вот и получаются монстрики.

    Я когда пишу такой код, то чувствую что халтурю. По крайней мере получить удовлетворения от такого я не могу. Удовлетворительный код почему-то всегда получается за одно и хорошо структурированным (с хорошей декомпозицией).
    ... << RSDN@Home 1.2.0 alpha rev. 637>>
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.