Здравствуйте, 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 и производительность…
Здравствуйте, 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
Не удержался от того, чтобы создать новую расширенную версию.
Померил с использованием таймеров (чтобы не учитывать JIT компиляцию)
Вот результаты (усреднены по 10 запускам)
(Pentium M 1,7 Dothan + 768Mb DDR333)
:
Для стандартной библиотеки (и boost как ее продолжение для C++):
D(DMD) — 0.645 сек
D(GDC) — 0.653 сек
С#/Nemerle — 0.870 сек
Boo — 1.003 сек (*)
Python+Psyco — 1.451 сек
Python — 2.182 сек
Java/Scala — 3.470 сек
C++(GCC),boost,list,is_space — 10.045 сек (**)
C++(MS),boost,list,is_space — 12.708 сек (**)
* для Boo почему-то не работает Split(" "), а только Split(),
поэтому неск медленнее
** взят лучший несамодельный вариант
Самоделки : Nemerle-Tokenizer — 0.738 сек
Nemerle-withLists — 0.896 сек
Java-Bicycle — 1.369 сек
Java-Tokenizer — 2.119 сек
C++(MS),Noname2,list,functor,ref — 2.463 сек (*)
Scala-Tokenizer — 2.642 сек
Scala-withLists — 2.785 сек
C++(GCC),VK,list,functor,val — 3.896 сек (*)
* взят наилучший из самодельных вариантов для данного компилятора
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");
}
}
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");
}
}
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
+
опробованы и разными вариантами (функторы и функции, передача предикатов по ссылке и по значению):
#include <list>
#include <vector>
#include <string>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <windows.h> // for GetTickCountusing 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)
Здравствуйте, Андрей Хропов, Вы писали:
АХ>Не удержался от того, чтобы создать новую расширенную версию.
Вот что выдают твои тесты у меня на компе
тут я только добывал бустовский аллокатор
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 (я писал об этом здесь
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 и производительность…
Здравствуйте, VladD2, Вы писали:
VD>То есть в имя метода вы засовываете некую дополнительную информаци? Ясно. Это знакомо по С/С++. Меня как раз порадовало в Яве и дотнете, что в имена не надо ничего лишнего засовывать. Ну, да у СТ свои особенности.
Я бы сказал, что у "ключевых сообщений" имена с доп.информацией получаются сами собой. Ну, типа тех
at: aKey ifAbsent: [...action...]
и
at: aKey ifAbsentPut: [...some value...]
И в Java мне не нравится именно то, что такие "полные" имена смотрятся там очень неестественно.
VD>Откровенно говоря куда полезнее было бы все же ввести хоть какую-то аннотацияю типов. Хотя бы для параметров и возвращаемого значения методов. Ну, да это вроде тоже было в Строгтоке и он особо популярным не стал.
Ну, ему как бы и не дали. Но история не терпит сослагательных наклонений. Так что гадать не будем.
если уж вы настаиваете чтобы 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();
}
}
лучшего, что смог добиться от вышеприведенного кода, это
~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
N>кстати, я правильно понимаю что D/C/C++ варианты оперирует с 8битными ASCII строками? ИМХО, скорее всего, именно это дает им определенное приемущество.
Проверял на C++ с wstring и L" никакой разницы по скорости.
При таком мелком размере строки я не удивился бы если бы с wstring было шустрее
Re[4]: [Benchmark]:updated - Split на C++,D,C#,Nemerle,Boo,J
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
Здравствуйте, 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
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
Здравствуйте, 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>А вообще приводить результаты тестов без указания процессоров это очень правильно.
Кстати, удалось еще немного выжать из вышеприведенного кода задействовав 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
Здравствуйте, n0name2, Вы писали:
N>на самом деле процент CPU который занимает GC в данном тесте ничтожно мал т.к. живые объекты в некий момент времени можно посчитать по пальцам (StringTokenizer, ArrayList и максимум пяток строк).
На самом деле (с) GC жрет время не только во время сборки мусора, но и во время выделения памяти. Он рассчитан на работу в многопоточной среде и делает блокировки. Так что если сокнурент не делает блокировок или вообще использует стэк для хранения результатов, то скорость у него будет значительно выше. Но это в таких примитивных тестах. А в реальных условиях все компенсируется.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.