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>>
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.