Мучения сборщика мусора. Часть II
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 15.11.04 15:17
Оценка:
Недавно я задался вопросом как наибыстрейшим способом "прикончить сборщик мусора". Стал придумывать примеры как бы сборщик мусора так нагрузить, чтобы он "захлебнулся мусором". По возможности, исходный код таких примеров должен быть как можно компактнее, чтобы, как говорится, все было "дешево и сердито".

1) Первое что пришло на ум, это создать N объектов в динамической памяти, таких чтобы они все ссылались друг на друга (включая самих себя), так что количество взаимных ссылок между ними было бы в точности равно N*N — максимально возможное количество (разных) ссылок между N объектами. После создания этого конгломерата объектов и ссылок между ними надо натравить на эту динамическую структуру сборщик мусора и посмотреть что получиться. Сборщик мусора, по идее, должен был бы "подавиться" распутывая эти N^2 взаимоссылок.

2) Второе что пришло на ум была совсем тривиальная вещь: создать N объектов в динамической памяти, ссылки на них записать в массив, а потом в цикле много раз создавать N+1'вый объект и записывать ссылку на него в этот самый массив вместо какой-то другой ссылки, старая ссылка, стало быть теряется и сборщик мусора должен тот старый объект уничтожить, таким образом объектов опять должно остаться ровно N штук.

Эксперименту над задачкой пункта (1) посвящена другая ветка форума:
http://www.rsdn.ru/Forum/Message.aspx?mid=897841&only=1
Автор: Сергей Губанов
Дата: 13.11.04

http://www.rsdn.ru/Forum/Message.aspx?mid=897965&only=1
Автор: Сергей Губанов
Дата: 14.11.04

http://www.rsdn.ru/Forum/Message.aspx?mid=898825&only=1
Автор: Сергей Губанов
Дата: 15.11.04


Сдесь же, давайте рассмотрим пункт (2).

Исходный код программы на языке C#:
namespace TestGC2
{
    class Object
    {
        public byte[] data;
    }

    class Program
    {
        static void f(int N)
        {
            Object[] arr = new Object[N];
            for (int n = 1; n < 100*N; n++)
            {
                Object x = new Object();
                x.data = new byte[1000];
                arr[n % N] = x;
            }
        }

        static void Main(string[] args)
        {
            const int N = 100000;
            long t;
            //-----------------------------------//
            t = System.Environment.TickCount;
            f(N);
            t = System.Environment.TickCount - t;
            //-----------------------------------//
            System.Console.WriteLine("N = {0}, t = {1}", N, t);
            System.Console.ReadLine();
        }
    }
}

Эта программа создает N = 100'000 объектов. Каждый объект занимает в памяти дополнительно 1'000 байтов (смотри строчку: x.data = new byte[1000]; ). Стало быть, суммарный объем полученной динамической структуры можно оценить в N*1000 = 100 мегабайтов + незначительные накладные расходы связанные с RTTI информацией хранимой в объектах (число в 100 мегабайтов обусловлено еще и тем, что на компьютере на котором я проводил эксперимент свободно как раз около 100-150 мегабайтов оперативной памяти). Массив заполняется 100 раз: for(int n = 1; n < 100*N; n++), стало быть, поскольку оперативной памяти хватает лишь только на 1-1.5 таких массива (а не на 100 массивов), то сборщик мусора должен запускаться несколько десятков раз. В идеале, если бы сборщик мусора был бы супер умным, то он должен был бы использовать не всю доступную память, а лишь только столько памяти сколько необходимо для N+1 объектов.
Язык   : C#
Железо : процессор Athlon 1.47Mhz, память 256Mb DDR266
Софт   : Windows XP SP2, MS Visual Studio .NET 2003, MS .NET Framework 1.1
Время выполнения программы = 163 секунды, т. е. 2 минуты 43 секунды.


Аналогичную программу я написал на языке Component Pascal
MODULE TestGC2;

IMPORT StdLog, Services;

PROCEDURE f(N: INTEGER);
TYPE Data    = POINTER TO ARRAY OF BYTE;
     Object  = POINTER TO RECORD data: Data END;
     Objects = POINTER TO ARRAY OF Object;
VAR arr: Objects; x: Object; n: INTEGER;
BEGIN
  NEW(arr, N);
  FOR n := 1 TO 100*N DO NEW(x); NEW(x.data, 1000); arr[n MOD N] := x END
END f;

PROCEDURE Test* ();
CONST N = 100000;
VAR t: LONGINT;
BEGIN
  t := Services.Ticks();
  f(N);
  t := Services.Ticks() - t;
  StdLog.String("N ="); StdLog.Int(N);
  StdLog.String(", t ="); StdLog.Int(t); StdLog.String(" ms");
  StdLog.Ln();
END Test; 
    
END TestGC2.

Собственно, первоначально, я сделал данные объекта не динамическим массивом, а статическим, то есть было так:
  Object  = POINTER TO RECORD 
      data: ARRAY 1000 OF BYTE;
    END;

но потом мне пришлось заменить статический массив на динамический, так как в языке C#, на сколько я его знаю, статических массивов не бывает, и, стало быть, я не смогу написать эквивалентную программу. Может быть я ошибаюсь? Есть в C# статические массивы или нет? Ну ладно, пока пусть будет динамический...
Язык   : Component Pascal
Железо : <тоже самое>
Софт   : <тоже самое> + Oberon Microsystems, Inc BlackBox 1.4
Время выполнения программы = 50 секунд.
Когда я использовал в качестве data статический массив байтов, то время выполнения составляло 38 секунд.

И .NET-товский и BlackBox-совский сборщики мусора не порадовали экономным использованием памяти (всего для N+1 объектов), и тот и другой захватывали максимальное доступное на компьютере количество оперативной памяти (150 мегабайтов).



В данном конкретном тесте, .NET-товский сборщик мусора работал в 163/50 = 3.26 раза медленнее чем BlackBox-совский сборщик мусора. Если вспомнить про задачку с N^2 ссылками между N объектами, то там тоже .NET-товский сборщик мусора работал более чем в 3 раза медленнее чем BlackBox-совский сборщик мусора.
 N    кол.связей   один объект  вся структура   BlackBox   .NET        Отношение времен .NET/BlackBox
                                                                    
2000    4 млн         8 Kb        16 Mb          0.23 сек    0.83 сек    3.60 раз
3000    9 млн        12 Kb        36 Mb          0.55 сек    2.27 сек    4.13 раз
4000   16 млн        16 Kb        64 Mb          1.17 сек    3.99 сек    3.41 раз
5000   25 млн        20 Kb       100 Mb          1.70 сек    6.37 сек    3.75 раз
6000   36 млн        24 Kb       144 Mb          2.67 сек   10.03 сек    3.76 раз
7000   49 млн        28 Kb       196 Mb          4.17 сек   18.12 сек    4.35 раз
8000   64 млн        32 Kb       256 Mb          4.12 сек   22.22 сек    5.39 раз

И что же это такое получается? Вот уже на двух совершенно разных задачах .NET-товский сборщик мусора работает более чем в 3 раза медленнее чем BlackBox-совский сборщик мусора. Как это объяснить? Может быть в следующей версии .NET сборщик мусора станет более шустрым?
Re: Мучения сборщика мусора. Часть II
От: prVovik Россия  
Дата: 15.11.04 15:55
Оценка: 27 (2)
Здравствуйте, Сергей Губанов, Вы писали:

Че-то ты все одних коней в вакууме тестируешь...
Вот тебе пример более приближенный к реальности:

using System;

namespace Test
{
    class Test
    {
        int a = 0;
        int b = 1;
        int c = 2;
    }

    class Class1
    {
        static Test[] Allocate( int count )
        {
            Test[] res = new Test[count];
            for( int i = 0; i < count; ++i ) res[i] = new Test();
            return res;
        }

        [STAThread]
        static void Main(string[] args)
        {
            long t = Environment.TickCount;
            Test[] statObj = Allocate( 5000000 );
            for( int i = 0; i < 1000000; ++i )
            {
                Allocate(1000);
            }
            Console.WriteLine( Environment.TickCount - t );
            Console.ReadLine();
        }
    }
}


Выполняется чуть меньше минуты (58-59 сек). Celeron 2.64; 256 mb. Как оно будет на BlackBox?
... << RSDN@Home 1.1.4 @@subversion >>
лэт ми спик фром май харт
Re: Мучения сборщика мусора. Часть II
От: GlebZ Россия  
Дата: 15.11.04 16:04
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>

СГ>В данном конкретном тесте, .NET-товский сборщик мусора работал в 163/50 = 3.26 раза медленнее чем BlackBox-совский сборщик мусора. Если вспомнить про задачку с N^2 ссылками между N объектами, то там тоже .NET-товский сборщик мусора работал более чем в 3 раза медленнее чем BlackBox-совский сборщик мусора.
СГ>
СГ> N    кол.связей   один объект  вся структура   BlackBox   .NET        Отношение времен .NET/BlackBox
                                                                    
СГ>2000    4 млн         8 Kb        16 Mb          0.23 сек    0.83 сек    3.60 раз
СГ>3000    9 млн        12 Kb        36 Mb          0.55 сек    2.27 сек    4.13 раз
СГ>4000   16 млн        16 Kb        64 Mb          1.17 сек    3.99 сек    3.41 раз
СГ>5000   25 млн        20 Kb       100 Mb          1.70 сек    6.37 сек    3.75 раз
СГ>6000   36 млн        24 Kb       144 Mb          2.67 сек   10.03 сек    3.76 раз
СГ>7000   49 млн        28 Kb       196 Mb          4.17 сек   18.12 сек    4.35 раз
СГ>8000   64 млн        32 Kb       256 Mb          4.12 сек   22.22 сек    5.39 раз
СГ>

Чего то я не понял. Ты чего меряешь, сборщик мусора или скорость выделения памяти? Для первых несколько строк, сборщик мусора весьма возможно вообще не запускался. В основном были только операции выделения. В дальнейшем такое же поведение прослеживается и дальше. Кто сказал что выделение миллиона объектов занимает больше времени, чем один или несколько проходов сборщика мусора.
Кстати, в С# массивы начинаются с 0.

С уважением, Gleb.
Re[2]: Мучения сборщика мусора. Часть II
От: GlebZ Россия  
Дата: 15.11.04 16:13
Оценка:
Sorry, очепятка:
Кто сказал что выделение миллиона объектов занимает больше времени, чем один или несколько проходов сборщика мусора
читать как
Кто сказал что выделение миллиона объектов занимает меньше времени, чем один или несколько проходов сборщика мусора

GZ>С уважением, Gleb.
Re[2]: Мучения сборщика мусора. Часть II
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 15.11.04 19:46
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ> Чего то я не понял. Ты чего меряешь, сборщик мусора или скорость выделения памяти?


А я не могу отдельно измерить одно или другое, поэтому приходится тестировать сумму = "время создания" + "время разрушения".
Re: Мучения сборщика мусора. Часть II
От: alexeiz  
Дата: 15.11.04 21:29
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>И что же это такое получается? Вот уже на двух совершенно разных задачах .NET-товский сборщик мусора работает более чем в 3 раза медленнее чем BlackBox-совский сборщик мусора. Как это объяснить? Может быть в следующей версии .NET сборщик мусора станет более шустрым?


Интересно, что ты до сих пор так и не понял, как работает GC в BlackBox'е. Он не отдает память операционной системе. Никогда. Поэтому от такой "быстрый". Загони его один раз в swap, он там и останется, даже если последующее потребление памяти будет гораздо меньше.

Тем не менее .NET GC достаточно быстр. Советую тебе оценить скорость выделения памяти (MB/sec) .NET'овским GC и сравнить с максимальной (например, VirtualAlloc + ZeroMemory). Выйдет не такое уж плохое соотношение — 1/4. А потом, если учесть, что при выделении 100MB .NET GC совершает 20 Gen0 сборок и 2 Gen2, остается удивляться, как ему удается сделать это так быстро.

[Детали приводить не буду, сейчас времени нет. Тем, кому интересно, смогут сами провести нужные эксперименты.]
Re[2]: Мучения сборщика мусора. Часть II
От: hrg Россия  
Дата: 16.11.04 06:52
Оценка:
alexeiz -> "Re: Мучения сборщика мусора. Часть II"

a> Тем не менее .NET GC достаточно быстр. Советую тебе оценить скорость

a> выделения памяти (MB/sec) .NET'овским GC и сравнить с максимальной
a> (например, VirtualAlloc + ZeroMemory). Выйдет не такое уж плохое
a> соотношение — 1/4. А потом, если учесть, что при выделении 100MB
a> .NET GC совершает 20 Gen0 сборок и 2 Gen2, остается удивляться, как
a> ему удается сделать это так быстро.

a> [Детали приводить не буду, сейчас времени нет. Тем, кому интересно,

a> смогут сами провести нужные эксперименты.]

http://www.rsdn.ru/article/dotnet/GCnet.xml#XSLTPART145120120
Автор(ы): Игорь Ткачев
Дата: 06.12.2002
Алгоритм работы сборщика мусора (garbage collector, далее просто GC), являющегося частью CLR, подробно описан в книге Джефри Рихтера (Jeffrey Richter) «Applied Microsoft .NET Framework Programming». Мы не будем приводить здесь столь же подробное описание этого алгоритма, но обязательно остановимся на некоторых ключевых моментах.
— типа уже
люди сделали

Yury Kopyl aka hrg | Гордость мешает доходам!
Posted via RSDN NNTP Server 1.9 gamma
Re[2]: Эта программа "убивает" GC Блэкбокса
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 16.11.04 08:10
Оценка: :))) :)))
Здравствуйте, prVovik, Вы писали:

V>Че-то ты все одних коней в вакууме тестируешь...

V>Вот тебе пример более приближенный к реальности:
...
V>Выполняется чуть меньше минуты (58-59 сек). Celeron 2.64; 256 mb. Как оно будет на BlackBox?

На данном тесте BlackBox отстал от .NET в 2.5 раза.

Но это еще не самое страшное, что с ним может случиться...

Наверняка Вы создавая пять миллионов объектов вовсе не ставили своей целью их тотчас же уничтожить. Тем не менее, Ваша программа уничтожает эти самые пять миллионов объектов сразу же после их создания и цикл for выполняется уже без них. Это происходит потому, что значение присвоенное переменной statObj нигде не используется. Раз оно нигде не используется, то компилятор C# полагает, что эти пять миллионов объектов есть мусор. Это можно наблюдать собственными глазами запустив программу на выполнение и погладывая в Task Manager за количеством используемой памяти. При запуске, программа резво захватывает 100 мегабайтов необходимых для этих самых пяти миллионов объектов, а потом тот час же возвращает эти 100 мегабайтов обратно в Windows, и далее цикл for выполняется на 14 мегабайтах. Если чуть-чуть изменить Вашу программу, например, добавив в самом конце строчку:
...
      Test[] statObj = Allocate( 5000000 );
      for( int i = 0; i < 1000000; ++i )
      {
        Allocate(1000);
      }      
      Console.WriteLine( Environment.TickCount - t );
      Console.ReadLine();
      Console.WriteLine(statObj.Length); // <-- эта строчка добавлена для того чтобы GC не чистил statObj
    }
  }
}

для того чтобы GC не рассматривал созданные в начале работы программы пять миллионов объектов как мусор и сохранил их до самого конца, вот тогда, аналогичная программа написанная под BlackBox порвет блэкбоксовский сборщик мусора на куски! Блэкбоксовский сборщик мусора, на сколько я понял, не пользуется механизмом ранжирования объектов по поколениям (а если и пользуется, то криво), это означает, что в последующих запусках GC в цикле FOR, блэкбоксовский GC каждый раз будет снова и снова искать среди тех фоновых пяти миллионов объектов более не нужные. Я пробовал запускать цикл FOR не миллион раз, а меньше, а потом аппроксимировать, сколько же уйдет времени для миллиона. Цикл 10'000 выполнялся за 14 секунд, цикл 100'000 выполнялся 150 секунд, логично предположить, что миллионный цикл должен был бы выполняться что-то около 4 часов (явно проверять так ли это я не стал).



Вывод.
1) Если считать, что фоновые пять миллионов объектов есть мусор, то BlackBox отстает от .NET в 2.5 раза.
2) Если фоновые пять миллионов объектов оставить до конца работы программы, то BlackBox "умирает мучительной смертью", из-за того что либо не ранжирует объекты по поколениям, либо ранжирует, но криво.

Поздравляю Вас, Вы предложили программу реально "убивающую" Блэкбоксовский сборщик мусора!
Re[2]: Мучения сборщика мусора. Часть II
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 16.11.04 08:23
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Интересно, что ты до сих пор так и не понял, как работает GC в BlackBox'е. Он не отдает память операционной системе. Никогда.


Чего такого я не понял? Может быть, наоборот, это Вы не поняли того, что BlackBox сам является модульной расширяемой операционной системой, а Windows он рассматривает в качестве некой рантайм среды исполнения поверх которой он сам запущен. Естественно, что он ничего никогда виндосу назад не отдает.
Re[3]: Мучения сборщика мусора. Часть II
От: alexeiz  
Дата: 16.11.04 09:56
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, alexeiz, Вы писали:


A>>Интересно, что ты до сих пор так и не понял, как работает GC в BlackBox'е. Он не отдает память операционной системе. Никогда.


СГ>Чего такого я не понял? Может быть, наоборот, это Вы не поняли того, что BlackBox сам является модульной расширяемой операционной системой, а Windows он рассматривает в качестве некой рантайм среды исполнения поверх которой он сам запущен. Естественно, что он ничего никогда виндосу назад не отдает.


Много он на себя берет. Нечего прикидываться операционной системой, если не можешь. Да и сам GC там тупой. Он даже compact алгоритм не умеет выполнять. Вот тебе прямой пример, где BlackBox просто умирает, если вдруг случается временная нехватка памяти. В тоже время .NET продолжает нормально работать.

Oberon:
MODULE GCTest;

IMPORT StdLog, Services;

PROCEDURE Test( par, loopc : INTEGER );
TYPE
    Data = POINTER TO ARRAY OF BYTE;
    Object = POINTER TO
                RECORD
                    data: Data
                END;
    Objects = POINTER TO ARRAY OF Object;

VAR
    arr: Objects;
    x: Object;
    i: INTEGER;
    j: INTEGER;
    arr_size: INTEGER;
    data_size: INTEGER;

BEGIN
    arr_size := 1000 * par;
    data_size := 10 * par;
    NEW( arr, arr_size );

    FOR i := 0 TO loopc - 1 DO
        FOR j := 0 TO arr_size - 1 DO
            NEW( x );
            NEW( x.data, data_size );
            arr[ j ] := x;
        END;
    END;
END Test;

PROCEDURE Main*();
VAR
    i: INTEGER;
    par: INTEGER;
    time: LONGINT;

BEGIN
    FOR i := 100 TO 115 DO
        par := i;
        Test( 2 * par, 1 );

        time := Services.Ticks();
        Test( par, 4 );
        time := Services.Ticks() - time;

        StdLog.String( "size = " );
        StdLog.Int( 10000 * par * par DIV 1000000 );
        StdLog.String( " MB, time = " );
        StdLog.Int( time );
        StdLog.String( " msec" );
        StdLog.Ln();
    END;
END Main;

END GCTest.

C#:
using System;

class Obj
{
    public byte [] Data;
}

class MainCls
{
    static void test( int par, int loopc )
    {
        int arr_size = 1000 * par;
        int data_size = 10 * par;
        Obj [] arr = new Obj[ arr_size ];

        for ( int i = 0; i < loopc; ++i )
        {
            for ( int j = 0; j < arr_size; ++j )
            {
                Obj x = new Obj();
                x.Data = new byte[ data_size ];
                arr[ j ] = x;
            }
        }
    }

    static int get_mem( int par )
    {
        return 10000 * par * par;
    }
    
    static void Main()
    {
        for ( int i = 100; i < 116; ++i )
        {
            int par = i;
            MainCls.test( 2 * par, 1 );

            int time = Environment.TickCount;
            MainCls.test( par, 4 );
            time = Environment.TickCount - time;

            Console.WriteLine( "size = {0} MB, time = {1} sec", MainCls.get_mem( par ) / 1000000, time / 1000.0 );
        }
    }
}


Результаты на Win2K, 512MB RAM, .NET 1.1:
blackbox:
size = 100 MB, time = 1102 msec
size = 102 MB, time = 981 msec
size = 104 MB, time = 991 msec
size = 106 MB, time = 1001 msec
size = 108 MB, time = 1272 msec
size = 110 MB, time = 1102 msec
size = 112 MB, time = 1011 msec
size = 114 MB, time = 1021 msec
size = 116 MB, time = 981 msec
size = 118 MB, time = 190383 msec
size = 121 MB, time = 208730 msec
-- killed

.net:
size = 100 MB, time = 7.631 sec
size = 102 MB, time = 7.21 sec
size = 104 MB, time = 7.511 sec
size = 106 MB, time = 7.29 sec
size = 108 MB, time = 7.51 sec
size = 110 MB, time = 7.731 sec
size = 112 MB, time = 7.481 sec
size = 114 MB, time = 10.986 sec
size = 116 MB, time = 8.051 sec
size = 118 MB, time = 22.773 sec
size = 121 MB, time = 18.066 sec
size = 123 MB, time = 32.998 sec
size = 125 MB, time = 10.154 sec
size = 127 MB, time = 36.933 sec
size = 129 MB, time = 24.315 sec
size = 132 MB, time = 23.543 sec
Re[4]: Большое спасибо за приведенные результаты!
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 16.11.04 15:27
Оценка: :)))
Здравствуйте, alexeiz, Вы писали:

A>Много он на себя берет. Нечего прикидываться операционной системой, если не можешь. Да и сам GC там тупой. Он даже compact алгоритм не умеет выполнять. Вот тебе прямой пример, где BlackBox просто умирает, если вдруг случается временная нехватка памяти. В тоже время .NET продолжает нормально работать.


Так так, давайте поймем что происходит в приведенном Вами примере... BlackBox запрашивает у Windows память размером V1. Оперативной памяти в компьютере установлено V2 < V1. Windows отдает BlackBox-у столько сколько он просил, но куски этой памяти, естественно, находятся на жестком диске (оперативки-то нехватило!). Что происходит дальше. Несчастный блэкбокс, получив память начинает с ней работать, но так как память фрагментирована и фрагменты ее находятся не только в оперативке, но и на жестком диске, то, ну совершенно очевидно, что поскольку скорость обмена данными с жестким диском на несколько порядков медленнее чем с оперативкой, то блэкбокс "вешается" — жужжит жестким диском. Но виноват ли он в том что виндос подсунула ему память находящуюся на диске??? Ему-то почем знать, где физически находится та память? Что виндос ему дала с тем он и рабоатет! Так что Ваш пример нельзя засчитать за пример "вешания" сборщика мусора. С тем же успехом можно было бы привести гораздо-перегораздо более простой пример нежели Ваш, а причина торможения была бы тойже самой:
VAR p: POINTER TO ARRAY OF BYTE;
BEGIN
  NEW(p, 1000000000);
END

Что тут происходит? А очень просто. Блэкбокс запрашивает у виндозы 1 гиг и заполняет его нулями. Виноват ли блэкбокс в том, что бОльшая часть этого гигабайта физически расположена на жестком диске в разных его местах??? Я полагаю, что он в этом не виноват.

А вот за приведенные Вами результаты:

A>Результаты на Win2K, 512MB RAM, .NET 1.1:

A>
A>blackbox:
A>size = 100 MB, time = 1102 msec
A>size = 102 MB, time = 981 msec
A>size = 104 MB, time = 991 msec
A>size = 106 MB, time = 1001 msec
A>size = 108 MB, time = 1272 msec
A>size = 110 MB, time = 1102 msec
A>size = 112 MB, time = 1011 msec
A>size = 114 MB, time = 1021 msec
A>size = 116 MB, time = 981 msec

A>.net:
A>size = 100 MB, time = 7.631 sec
A>size = 102 MB, time = 7.21 sec
A>size = 104 MB, time = 7.511 sec
A>size = 106 MB, time = 7.29 sec
A>size = 108 MB, time = 7.51 sec
A>size = 110 MB, time = 7.731 sec
A>size = 112 MB, time = 7.481 sec
A>size = 114 MB, time = 10.986 sec
A>size = 116 MB, time = 8.051 sec
A>


говорю Вам большое спасибо. Ведь из них следует, что BlackBox в данном тесте работает от 7 до 10 раз быстрее чем .NET
Re[5]: Большое спасибо за приведенные результаты!
От: Sergey J. A. Беларусь  
Дата: 16.11.04 16:33
Оценка: 12 (2) :))) :))) :))) :)
Здравствуйте, Сергей Губанов, Вы писали:

Здорово. Я так понял, что Windows подсовывает BlackBox`у второсортную память... похуже. А вот для .Net — ничего не жалко — всё самое лучшее! Поэтому и разница....
Я — свихнувшееся сознание Джо.
Re[3]: Эта программа "убивает" GC Блэкбокса
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.11.04 21:28
Оценка: 1 (1) :))
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Поздравляю Вас, Вы предложили программу реально "убивающую" Блэкбоксовский сборщик мусора!


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

То что ты считашь, что чего-то не нужно или не важно ничего не значит, если есть сотни тысяч (а то и милллионы) программистов которым нужны эти фичи.

Пойми, что минималим — это убогость. Все что есть в Шарпе вымучино. Даже дженерики появились не случайно. По началу у разработчиков Явы и дотнета бытавало мнение, что дженерики — это все от лукавого (ну, точно как ты говорил только еще и аргументация была по солиднее), но в итоге они плюнули на свое мнение и сделали, так как хотят люди.

Поверь, что все до одного приемущества Оберона были реализованы в Шарпе.

Если ты дейсвительно хочешь срвнить, то попробуй назвать вещи которые есть в Обероне[2] и нет в Шаре. Или которые есть в Шарпе и они явно мешают эффективному созданию программ.

Вот это будет конструктивно и интересно. Только одна просба, если таковых вещей не найдется, то посторайся прекратить эту никчемную рекламную компанию и прйзнай, что Оберон сыграль свою роль в эволюции ООЯ и больше не нужен.
... << RSDN@Home 1.1.4 beta 3 rev. 207>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Большое спасибо за приведенные результаты!
От: Трурль  
Дата: 17.11.04 06:41
Оценка:
Здравствуйте, Sergey J. A., Вы писали:

SJA> Здорово. Я так понял, что Windows подсовывает BlackBox`у второсортную память... похуже. А вот для .Net — ничего не жалко — всё самое лучшее! Поэтому и разница....


Насколько я понял, вместо сферических коней предлагается использовать кубических.
У меня на 256M обе программы благополучно засыпали на непределенное время.
Re[4]: Вывод
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 17.11.04 09:30
Оценка: 30 (1) :)
Здравствуйте, VladD2, Вы писали:

VD> <....>


Странный вывод Вы сделали, однако...

Мы тут, понимаете ли, ни кого не трогаем, тихо мирно разные GC тестируем, завалить их пытаемся. Вот, например, оказалось, что при наличии большого количества "фоновых" объектов блэкбоксовский GC значительно отстает
Автор: Сергей Губанов
Дата: 16.11.04
от дотнетовского из-за того что не ранжирует объекты по поколениям. Однако, с другой стороны, выяснилось, что в случае отсутствия "фоновых" объектов блэкбоксовский GC, наоборот, как правило, опережает дотнетовский в несколько раз
Автор: Сергей Губанов
Дата: 15.11.04
(в основном получалось около 3 раз, хотя есть случаи десятикратного превосходства
Автор: Сергей Губанов
Дата: 16.11.04
).

Что касается конкретно языков программирования, так это, пожалуйста, давайте не в этой ветке форума.
Re[3]: Эта программа "убивает" GC Блэкбокса
От: Павел Кузнецов  
Дата: 18.11.04 05:26
Оценка: +1 :)
Сергей Губанов,

> Поздравляю Вас, Вы предложили программу реально "убивающую" Блэкбоксовский сборщик мусора!


Дотнетовский GC тоже, как выяснилось, тоже весьма несложно поставить в интересное положение: http://rsdn.ru/forum/?mid=903922
Автор: Дарней
Дата: 18.11.04


1:1

С интересом продолжаем наблюдать за битвами мусорщиков
Posted via RSDN NNTP Server 1.9 gamma
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: Большое спасибо за приведенные результаты!
От: alexeiz  
Дата: 18.11.04 09:30
Оценка: 37 (3) +1
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, alexeiz, Вы писали:


A>>Много он на себя берет. Нечего прикидываться операционной системой, если не можешь. Да и сам GC там тупой. Он даже compact алгоритм не умеет выполнять. Вот тебе прямой пример, где BlackBox просто умирает, если вдруг случается временная нехватка памяти. В тоже время .NET продолжает нормально работать.


СГ>Так так, давайте поймем что происходит в приведенном Вами примере...


Откровенно говоря, смешно даже читать было твое наивное объяснение.

> С тем же успехом можно было бы привести гораздо-перегораздо более простой пример нежели Ваш, а причина торможения была бы тойже самой:

СГ>
СГ>VAR p: POINTER TO ARRAY OF BYTE;
СГ>BEGIN
СГ>  NEW(p, 1000000000);
СГ>END
СГ>


Отнюдь. Если бы ты внимательно посмотрел на код программы, и/или выполнил бы её, у тебя было бы совсем другое мнение. Это явное утрирование показывает, что твоя лень (или нежелание докопаться до фактов, которые тебе будут неудобными) помешала тебе узнать что же все-таки происходит на самом деле.

СГ>Что тут происходит? А очень просто. Блэкбокс запрашивает у виндозы 1 гиг и заполняет его нулями. Виноват ли блэкбокс в том, что бОльшая часть этого гигабайта физически расположена на жестком диске в разных его местах??? Я полагаю, что он в этом не виноват.


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

Примерный алгоритм выглядит так:

Для размера X
  Выделить память размера 4*X -- имитация временной перегруженности системы
  Освободить память размера 4*X (потерять ссылки)

  Старт таймера
  Делать какую-либо работу с максимальным выделением памяти X
  Стоп таймера
  Вывести значение таймера


Далее просканировался X в промежутке [100,132] MB, что дает 4*X = [400,528] MB — довольно разумное значение если компьютер имеет 512MB RAM.

Время таймера не единственная характеристика в данном тесте. Гораздо интереснее поведенческие характеристики сборщиков мусора. .NET GC не имел недостатка в памяти до X=112MB. После этого выделение 4*X стало занимать больше и больше времени (т.к. понятно, что используется page file, но не очень сильно, в худшем случае десятки MB), что тем не менее не влияло на последующую работу программы, так как память освобождалась и необходимости в page file больше не возникало.

BlackBox GC прекрасно и очень быстро работает до X=116MB. До этого paging вообще не задействован. Тем не менее процесс BlackBox'а отнимает практически всю свободную память в системе. На следующем шаге для X=118MB задействуется максимум 8MB page file. BlackBox переживает всплеск в 4*X, после чего продолжает работать с максимальным размером в 118MB. Тем не менее у него начинаются серьезные проблемы. Таймер явно показывает, что происходит активный paging. Из этого следует, что BlackBox активно использует очень большое количество страниц, гораздо больше чем требуемые 118MB. Отсюда следует, что память, которой оперирует BlackBox очень сильно фрагментирована, что ему приходится пробегать ее всю, чтобы в очередной раз собрать мусор или выделить новый блок. Отсюда также следует, что про компактирование и поколения BlackBox GC не имеет ни малейшего понятия. В заключение замечу, что когда я наконец убил BlackBox, он отнимал 700MB виртуальной памяти. Можно только представить себе, как он носится по всей этой памяти в поисках свободных блоков или стараясь что-либо освободить, при этом запрашивая у OS все больше и больше, и больше, и больше...

СГ>А вот за приведенные Вами результаты:


A>>Результаты на Win2K, 512MB RAM, .NET 1.1:

A>>
A>>blackbox:
A>>size = 100 MB, time = 1102 msec
A>>size = 102 MB, time = 981 msec
A>>size = 104 MB, time = 991 msec
A>>size = 106 MB, time = 1001 msec
A>>size = 108 MB, time = 1272 msec
A>>size = 110 MB, time = 1102 msec
A>>size = 112 MB, time = 1011 msec
A>>size = 114 MB, time = 1021 msec
A>>size = 116 MB, time = 981 msec
size = 118 MB, time = 190383 msec
size = 121 MB, time = 208730 msec
-- killed

A>>.net:
A>>size = 100 MB, time = 7.631 sec
A>>size = 102 MB, time = 7.21 sec
A>>size = 104 MB, time = 7.511 sec
A>>size = 106 MB, time = 7.29 sec
A>>size = 108 MB, time = 7.51 sec
A>>size = 110 MB, time = 7.731 sec
A>>size = 112 MB, time = 7.481 sec
A>>size = 114 MB, time = 10.986 sec
A>>size = 116 MB, time = 8.051 sec
size = 118 MB, time = 22.773 sec
size = 121 MB, time = 18.066 sec
size = 123 MB, time = 32.998 sec
size = 125 MB, time = 10.154 sec
size = 127 MB, time = 36.933 sec
size = 129 MB, time = 24.315 sec
size = 132 MB, time = 23.543 sec
A>>


СГ>говорю Вам большое спасибо. Ведь из них следует, что BlackBox в данном тесте работает от 7 до 10 раз быстрее чем .NET


Из них следует, что ты закрываешь глаза на несостоятельнось BlackBox'а с технической точки зрения. Как можно сравнивать производительность .NET GC и BlackBox GC, когда последний не может обеспечить необходимой функциональности? BlackBox GC является примером упрощенного менеджера памяти, который приемлимо работает только на учебных задачах. Почему только учебные задачи? Потому что в реальных задачах память всегда ограниченна и всегда представляет собой ценный ресурс, и тот менеджер памяти, который считает нормальным выделить в десять раз больше необходимого, просто выходит за рамки разумного.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.