Re[10]: Erlang avalanche
От: Курилка Россия http://kirya.narod.ru/
Дата: 13.12.06 13:31
Оценка:
Здравствуйте, n0name2, Вы писали:

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


К>>ОК, что ты сделаешь с нативными библиотеками?


N>Ничего. В Java они практически нигде не используются. Это большая экзотика если речь идет о типовом бизнес приложении. Разве что — есть ввод/вывод и другие native вызовы в самом JDK, но, они все-таки много времени обычно не занимают и т.к. это SRT то можно ими пренебречь. Кстати, как проблема ввода/вывода в Erlang решается применительно к scheduling?


Есть подозрение, что трудновато будет принебречь, в любом случае тебе надо будет инструментировать весь байткод, причём не факт что это пройдёт безболезненно.
Хотя, если честно, придумывать уже где грабли могут вылезти несколько лень

N>Тотже эксперемент с green threads очень показателен — очевидно, что scheduling в стиле Erlang сделать для JVM довольно легко, но, толку это особого не даст для типовых задач. Кстати, от green threads отказались после того, как scheduler в Linux стал работать гораздо лучше и для типовых задач разница стала незаметной.


Вопрост ещё что кроме "обычности" задач ещё присутствует обычность подходов, в том числе архитектурных. Одна сборка мусора при иммутабельности реально уже офигенно выигрывает. Просто речь о том выигрыш от такого подхода при обычном императивном программинге довольно мал, вот это и показали green threads
Re[8]: Erlang avalanche
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 13.12.06 13:35
Оценка: 34 (3)
Здравствуйте, n0name2, Вы писали:

N>Но, вообще — проще вернуть green threads, вот и все. Собственно, насколько я понию, их так и не убрали из JVM. Только вот никакого особенного эффекта на типовых задачах они не дают, поэтому их и убрали.


Как я понимаю, в java "зелёные" треды — это кооперативная многозадачность. То есть это не тот случай.
Хотя, в конечном итоге, так и делают:

At 10,000 connections, BEA JRockit 3.1 on Windows has 14 times the throughput of any other Java platform---by far, the best network scalability I have ever tested. While other Java vendors waited for better threading support in the operating system or new programming interfaces for the application, the JRockit team solved the Java threads problem right where it originated. The results are remarkable, and BEA made a wise purchase.


N>Честно говоря, вообще я не очень понимаю зачем нужно все это. В Java такого рода задачи делаются немного по другому — заводится пул потоков (практически это OS threads, размер пула определяется исходя из кол-во CPU), и есть входная очередь задач. Соот-но поток взял очередную задачу, обработал ее, взялся за следующую. Особо криминального переключения контекстов или оверхеда на создание тысяч потоков тут нет.


Кстати, вот
Автор(ы): Роман Хациев
Дата: 14.02.2002
Довольно давно я прочитал статью, автор которой объединил две концепции — многозадачность и объектно-ориентированное программирование. В результате получились так называемые "живые объекты". Идея крайне проста — при инициализации объекта создается отдельный поток и объект в нем живет своей жизнью, а создатель объекта по мере необходимости получает информацию о состоянии объекта из его свойств.
(степень актуальности пропустим):

Кол-во потоков     | 2xPIII-1000 Windows NT4 Server издержки
                |
       2          |  0%
      32          | 20%
    1024          | 46%
    8192          | 57%

http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[11]: Erlang avalanche
От: n0name2  
Дата: 13.12.06 13:48
Оценка:
Здравствуйте, Курилка, Вы писали:

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

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

Возможно, что-то и вылезет, я не спорю. А код весь инструментируют, допустим в целях logging иногда. Кстати, у Sun еще есть Solaris и DTrace, который умеет в целях отладки инструментировать native код. В принципе, я когда говорил с Sunовскими представителями, они сказали что дали бы возможность инструментировать native код не только в целях отладки, но боятся

А еще в Solaris есть LWP и маппинг Java потоков на kernel scheduling entity как M на N, соот-но, там оверхед на context switch еще меньше чем при NPTL под Linux. Кстати, Niagara (T1) под Solaris себя отлично чувствует при большем кол-ве switchей.

К>Вопрост ещё что кроме "обычности" задач ещё присутствует обычность подходов, в том числе архитектурных. Одна сборка мусора при иммутабельности реально уже офигенно выигрывает. Просто речь о том выигрыш от такого подхода при обычном императивном программинге довольно мал, вот это и показали green threads


Не спорю, сборщик мусора, конечно, был бы гораздо эффективнее. Да и оверхед мутатора бы ушел тоже. Но, на сборку мусора тратятся единицы процентов CPU time. Плюс ее можно проводить в паралельном потоке (не на все 100%, но, существенную часть). Так что — овчинка выделки не стоит в данном конкретном случае.
Re[9]: Erlang avalanche
От: n0name2  
Дата: 13.12.06 13:53
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Как я понимаю, в java "зелёные" треды — это кооперативная многозадачность. То есть это не тот случай.


В смысле? В чем принципиальное отличие green threads и Erlang actors с т.з. scheduling?

ANS>

ANS>At 10,000 connections, BEA JRockit 3.1 on Windows has 14 times the throughput of any other Java platform---by far, the best network scalability I have ever tested. While other Java vendors waited for better threading support in the operating system or new programming interfaces for the application, the JRockit team solved the Java threads problem right where it originated. The results are remarkable, and BEA made a wise purchase.


Это, скорее всего, было во времена кривого ядра Linux (до 2.6). Сейчас — не актуально.

ANS>Кстати, вот
Автор(ы): Роман Хациев
Дата: 14.02.2002
Довольно давно я прочитал статью, автор которой объединил две концепции — многозадачность и объектно-ориентированное программирование. В результате получились так называемые "живые объекты". Идея крайне проста — при инициализации объекта создается отдельный поток и объект в нем живет своей жизнью, а создатель объекта по мере необходимости получает информацию о состоянии объекта из его свойств.
(степень актуальности пропустим):

ANS>

ANS>

ANS>Кол-во потоков     | 2xPIII-1000 Windows NT4 Server издержки
ANS>                |
ANS>       2          |  0%
ANS>      32          | 20%
ANS>    1024          | 46%
ANS>    8192          | 57%
ANS>


Ну, во-первых, по большому счету, это всего лишь аргумент в тему почему MS sucks а Solaris rulezzz, во-вторых, 8к потоков зачем создавать? Может, просто пул сделать? Или NIO selectors использовать (non blocking IO)?
Re[10]: Erlang avalanche
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.12.06 13:55
Оценка: +1
Здравствуйте, n0name2, Вы писали:

N>во-вторых, 8к потоков зачем создавать? Может, просто пул сделать? Или NIO selectors использовать (non blocking IO)?


"Одна задача -- один процесс" -- гораздо более простая модель для разработки.
Тем более, что убивать почившие процессы в такой модели гораздо проще, чем потоки в пуле.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[12]: Erlang avalanche
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 13.12.06 13:59
Оценка:
Здравствуйте, n0name2, Вы писали:

N>А еще в Solaris есть LWP и маппинг Java потоков на kernel scheduling entity как M на N


Кстати, это в прошлом. Начиная с 10 солярки, по умолчанию, используется модель 1:1. Мне всегда было интересно, если M:N была такая удобная, то почему от неё отказались?
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[11]: Erlang avalanche
От: n0name2  
Дата: 13.12.06 14:08
Оценка:
E>"Одна задача -- один процесс" -- гораздо более простая модель для разработки.
E>Тем более, что убивать почившие процессы в такой модели гораздо проще, чем потоки в пуле.

Чем принципиально отличается следующие два куска кода с т.з. простоты:

new Thread() {
public void run() {
   System.out.println("Hi!");
}
}.start();


и

executor.submit(new Runnable() {
public void run() {
   System.out.println("Hi!");
});


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

Non blocking IO — да, это чуть сложнее, согласен. Хотя, над ним уже построили высокоуровневые абстракции и ничего особенно сложного там нет. Да и в типовом проекте это вообще не нужно. Кстати, простота программирования в императивном vs функциональном стиле это отдельная тема, конечно и тут все не столь очевидно.
Re[13]: Erlang avalanche
От: n0name2  
Дата: 13.12.06 15:33
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

N>>А еще в Solaris есть LWP и маппинг Java потоков на kernel scheduling entity как M на N


ANS>Кстати, это в прошлом. Начиная с 10 солярки, по умолчанию, используется модель 1:1. Мне всегда было интересно, если M:N была такая удобная, то почему от неё отказались?


Ну как — если смотреть скорость создания потоков, то тут M:N рвет "новую" реализацию linthreads как тузик грелку, а если смотреть скорость реальных приложений то новый более простой шедулер оказался эффективнее, удалось kernel context switches сделать всего в три раза дороже чем user level switches.

Кстати, нашел тут блог адептов Erlang. Там они делают бенчмарк на message passing Java vs Erlang. Вот оригинальный исходник бенчмарка:

 import java.util.concurrent.*;

    public class SpawnTest extends Thread {
        public static void main(String[] args) {
            int M = Integer.parseInt(args.length > 0 ? args[0] : "1");
            int N = Integer.parseInt(args.length > 1 ? args[1] : "1000000");
            int NpM = N / M;
            BlockingQueue queue = new LinkedBlockingQueue();
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < M; i++) { new Body(queue, NpM).start(); }
            for (int i = 0; i < M; i++) { try { queue.take(); } catch (InterruptedException ie) {} }
            long stopTime = System.currentTimeMillis();
            System.out.println((NpM * M) / ((stopTime - startTime) / 1000.0));
        }

        public static class Body extends Thread {
            BlockingQueue queue;
            int count;
            public Body(BlockingQueue queue, int count) {
                this.queue = queue;
                this.count = count;
            }
            public void run() {
                if (count == 0) {
                    try { queue.put(this); } catch (InterruptedException ie) {}
                } else {
                    new Body(queue, count - 1).start();
                }
            }
        }
    }


Запустив его получаем удручающую скорость — всего 4073 messages/sec (на винде). Но, так на Java ни один вменяемый программист не напишет, модифицировав код всего на пару строк

import java.util.concurrent.*;

public class Test25 extends Thread {
    public static Executor executor;

    public static void main(String[] args) {
        int M = Integer.parseInt(args.length > 0 ? args[0] : "1");
        int N = Integer.parseInt(args.length > 1 ? args[1] : "1000000");
        executor = Executors.newFixedThreadPool(M);
        int NpM = N / M;
        BlockingQueue queue = new LinkedBlockingQueue();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < M; i++) { executor.execute(new Body(queue, NpM)); }
        for (int i = 0; i < M; i++) { try { queue.take(); } catch (InterruptedException ie) {} }
        long stopTime = System.currentTimeMillis();
        System.out.println((NpM * M) / ((stopTime - startTime) / 1000.0));
    }

    public static class Body implements Runnable {
        BlockingQueue queue;
        int count;
        public Body(BlockingQueue queue, int count) {
            this.queue = queue;
            this.count = count;
        }
        public void run() {
            if (count == 0) {
                try { queue.put(this); } catch (InterruptedException ie) {}
            } else {
                if (count % 10000 == 0) System.out.println("" + count);
                executor.execute(new Test25.Body(queue, count - 1));
            }
        }
    }
}


Удалось получить целых 336700 messages/sec Что примерно равно результатам Erlang из тестов здесь

Однако, если применить магическую концепцию императивного программирования под названием цикл и причесать код

import java.util.concurrent.*;

public class Test25 extends Thread {
    public static Executor executor;

    public static void main(String[] args) throws InterruptedException {
        int M = Integer.parseInt(args.length > 0 ? args[0] : "1");
        int N = Integer.parseInt(args.length > 1 ? args[1] : "1000000");
        executor = Executors.newFixedThreadPool(M);
        int NpM = N / M;
        BlockingQueue queue = new ArrayBlockingQueue(1000 * 1000);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < M; i++) executor.execute(new Body(queue, NpM));
        for (int i = 0; i < N; i++) queue.take();
        long stopTime = System.currentTimeMillis();
        System.out.println((NpM * M) / ((stopTime - startTime) / 1000.0));
    }

    public static class Body implements Runnable {
        BlockingQueue queue;
        int count;
        public Body(BlockingQueue queue, int count) {
            this.queue = queue; this.count = count;
        }
        public void run() {
            try {
                for (int i = 0; i < count; i++) queue.put(this);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }
}


То получается уже 1560062 messages/sec.
Re[10]: Erlang avalanche
От: Sinclair Россия https://github.com/evilguest/
Дата: 13.12.06 15:46
Оценка:
Здравствуйте, n0name2, Вы писали:

N>А зачем поток каждый раз создавать? Ведь можно завести несколько (2-4) потоков, которые обрабатывают общую очередь запросов (mailbox в терминах Erlang).

Речь идет о том, что даже переключение потоков может оказаться слишком дорогим для случая инфинитезимальных единиц работы.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: Erlang avalanche
От: Курилка Россия http://kirya.narod.ru/
Дата: 13.12.06 15:59
Оценка: +1 :)
Здравствуйте, Sinclair, Вы писали:

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


N>>А зачем поток каждый раз создавать? Ведь можно завести несколько (2-4) потоков, которые обрабатывают общую очередь запросов (mailbox в терминах Erlang).

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

каких-каких?
Re[11]: Erlang avalanche
От: n0name2  
Дата: 13.12.06 15:59
Оценка:
Здравствуйте, Sinclair, Вы писали:

N>>А зачем поток каждый раз создавать? Ведь можно завести несколько (2-4) потоков, которые обрабатывают общую очередь запросов (mailbox в терминах Erlang).

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

А зачем потоки вообще переключать если у нас кол-во worker threads в пуле, грубо говоря, равно кол-ву CPU? Ну, конечно, не гарантируется что у нас контексты переключатся не будут, но это будет происходить весьма редко.

Если речь идет об обмене данными м/у процессами (и соот-но происходит блокировка ожидающего потока), то, все-таки в большинстве случаев мы обойдемся spin lockом (+atomic get&set) и все будет происходить чисто на user level, никаких вызовов ядреных операций.

Кроме того, даже в Erlang переключение м/у процессами и обмен данными наверняка не полностью бесплатны, более того, думаю, что в java.util.concurrent это реализовано несколько лучше.
Re[14]: Erlang avalanche
От: Lazy Cjow Rhrr Россия lj://_lcr_
Дата: 13.12.06 16:01
Оценка: +1
n0name2,

N>То получается уже 1560062 messages/sec.


Хорошо. Но строго говоря, его эрланговский вариант тоже не слишком впечатляет. Если мы уж меряем скорость переписываний указателей из одного места в другое (), то почему бы не проставить везде нужные гварды, не скомпилировать hipe (хотя под Дебианом может уже) и не запустить с опцией -hybrid?

Да и потом, 1000 потоков — курам на смех. Хотя бы сотенку тыщщёнок.

Короче, как выразился Влад, "тест из разряда "физики шутят"". Что с той, что с другой стороны.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[15]: Erlang avalanche
От: n0name2  
Дата: 13.12.06 16:08
Оценка:
Здравствуйте, Lazy Cjow Rhrr, Вы писали:

N>>То получается уже 1560062 messages/sec.


LCR>Хорошо. Но строго говоря, его эрланговский вариант тоже не слишком впечатляет. Если мы уж меряем скорость переписываний указателей из одного места в другое (), то почему бы не проставить везде нужные гварды, не скомпилировать hipe (хотя под Дебианом может уже) и не запустить с опцией -hybrid?


На самом деле кроме копирования происходит самое главное — обмен сообщениями м/у потоками. Т.е. используются мутексы и т.д. и т.п.

LCR>Короче, как выразился Влад, "тест из разряда "физики шутят"". Что с той, что с другой стороны.


Тест говорит о том, что мифическое приемущество Erlang в concurrent программировании по сравнению с Java объясняется скорее тем, что Erlangисты не понимают как задачу решить оптимально средствами Java, а не тем, что есть некие фундаментальные ограничения у самой JVM.

Проводились ли вообще вменяемые сравнения или ничего поинтереснее адепты Erlang предложить немогут? Скорость создания потоков мне не интересна — обычно массово их не создают а обходятся пулами.
Re[16]: Erlang avalanche
От: fddima  
Дата: 13.12.06 16:23
Оценка:
Здравствуйте, n0name2, Вы писали:

N>Тест говорит о том, что мифическое приемущество Erlang в concurrent программировании по сравнению с Java объясняется скорее тем, что Erlangисты не понимают как задачу решить оптимально средствами Java, а не тем, что есть некие фундаментальные ограничения у самой JVM.

N>Проводились ли вообще вменяемые сравнения или ничего поинтереснее адепты Erlang предложить немогут?
N>Скорость создания потоков мне не интересна — обычно массово их не создают а обходятся пулами.
Уже не раз приводился пример Apache vs YAWS. Apache — хороший представитель пулов, кстати.
Re[12]: Erlang avalanche
От: fddima  
Дата: 13.12.06 16:25
Оценка: 8 (1)
Здравствуйте, Курилка, Вы писали:

N>>>А зачем поток каждый раз создавать? Ведь можно завести несколько (2-4) потоков, которые обрабатывают общую очередь запросов (mailbox в терминах Erlang).

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

К>каких-каких?

Думаю таких.
Re[14]: Erlang avalanche
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 13.12.06 16:40
Оценка:
Здравствуйте, n0name2, Вы писали:

N> executor = Executors.newFixedThreadPool(M);


Это хак. Сродни хаку в тесте для C#
Автор: Андрей Хропов
Дата: 05.12.06
. Почему бы не сделать вообще 1 тред (кстати с какими параметрами ты это запускал?). И выполнить вообще всё последовательно. Ты получиш еще больше количество сообщений в сек.

N> BlockingQueue queue = new LinkedBlockingQueue();
N> long startTime = System.currentTimeMillis();
N> for (int i = 0; i < M; i++) { executor.execute(new Body(queue, NpM)); }


Я не понял. Используется одна общая очередь на все треды? Это баг.

ЗЫ. Тест на Erlang, скорее всего, тоже туфта
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[12]: Erlang avalanche
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 13.12.06 16:47
Оценка:
Здравствуйте, n0name2, Вы писали:

N>А зачем потоки вообще переключать если у нас кол-во worker threads в пуле, грубо говоря, равно кол-ву CPU? Ну, конечно, не гарантируется что у нас контексты переключатся не будут, но это будет происходить весьма редко.


Не фижу как это будет работать если у тебя будет только стандартная сановская JVM.
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[17]: Erlang avalanche
От: n0name2  
Дата: 13.12.06 16:59
Оценка:
Здравствуйте, fddima, Вы писали:

F> Уже не раз приводился пример Apache vs YAWS. Apache — хороший представитель пулов, кстати.


Не, как раз Apache заводит отдельный процесс на каждого клиента. Вообще, приличный Java web server рвет Apache как тузик грелку. А для большого кол-во requestов есть NIO (non blocking IO), в одном потоке можно обрабатывать сколько хочешь клиентов

здесь

Воспроизвести тест как на твоей ссылки конечно мало реально, но, известно что NIO based серверы практически не деградируют при большом кол-ве клиентов.
Re[13]: Erlang avalanche
От: n0name2  
Дата: 13.12.06 17:03
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Не фижу как это будет работать если у тебя будет только стандартная сановская JVM.


Ну во первых есть JRockit во вторых thread pool никто еще не отменял, они используются повсеместно.
Re[14]: Erlang avalanche
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 13.12.06 17:10
Оценка:
Здравствуйте, n0name2, Вы писали:

N>Ну во первых есть JRockit во вторых thread pool никто еще не отменял, они используются повсеместно.


Допустим у тебя 32 проца. Соответсвенно тред пул у тебя на 32 треда. Тебе не кажется это несколько... ограниченным?
http://www.smalltalk.ru | << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.