структуры/классы c# складывают/помещают управление в "кучу"?

таким образом в C++ это очень легко. Вы хотите, чтобы любой класс/структура был выделен на "куче", использовал новый. если Вы хотите это на стеке, не используйте новый.

в C# мы всегда используем новое ключевое слово, и в зависимости от того, является ли это структурой или классом, который это выделило или на стеке или на "куче" (структуры переходят к стеку, классам к "куче") - и в некоторых приложениях может быть ОГРОМНОЕ различие в производительности при изменении дизайна, таким образом, что только те объекты переходят к "куче", которые действительно принадлежат там.

То, что интересно, - там прямой способ управлять, где объект выделяется независимый от того, объявляется ли он как структура или класс? я знаю, что (структуры) типов значения могут быть упакованы для движения в "кучу" (но упаковка/распаковывание происходит в стоимость производительности). существует ли способ выделить классы на стеке?

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

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

Любые приветствующиеся подсказки/подсказки:)

править: пример производительности:

struct Foo1
{
    public int i;
    public float f;
    public double d;
}

struct Foo2
{
   public Foo1[] bar;

   public void Init(){
        bar = new Foo1[100];
        for (int i = 0; i < 100; i++)
            bar[i] = new Foo1();
    }
}

class Program
{
    static void Main(string[] args)
    {
        DateTime time = DateTime.Now;
        Foo2[] arr = new Foo2[1000000];
        for (int i = 0; i < 1000000; i++)
        {
            arr[i] = new Foo2();
            arr[i].Init();
        }

        Console.WriteLine((DateTime.Now - time).TotalMilliseconds);
    }
}

Это занимает 1,8 секунды на моей машине для выполнения (обратите внимание, что существует на самом деле только продолжение выделения - никакая передача параметров),

если Foo1 изменяется от структуры до класса, выполнение занимает 8,9 секунд! это в пять раз медленнее

13
задан Mat 8 January 2010 в 23:54
поделиться

5 ответов

[

] Хотя в общем случае это правда, что объекты всегда выделяются на куче, C# позволяет опуститься до уровня указателя для тяжелого интернопа или для очень высокопроизводительного критического кода. [

] [

]В блоках []опасном[] можно использовать []stackalloc[] для выделения объектов на стеке и использования их в качестве указателей.[

] [

]Чтобы процитировать их пример:[

] [
// cs_keyword_stackalloc.cs
// compile with: /unsafe
using System; 

class Test
{
   public static unsafe void Main() 
   {
      int* fib = stackalloc int[100];
      int* p = fib;
      *p++ = *p++ = 1;
      for (int i=2; i<100; ++i, ++p)
         *p = p[-1] + p[-2];
      for (int i=0; i<10; ++i)
         Console.WriteLine (fib[i]);
   }
}
] [

]Обратите внимание, что не обязательно объявлять весь метод опасным, можно просто использовать для этого []опасный {...}[] блок.[

].
9
ответ дан 1 December 2019 в 23:15
поделиться
[

] Не беспокойтесь об этом - вы все еще находитесь в мире c / c++, где это может иметь большое значение, куда вещи идут. В команде CLR есть куча действительно умных людей, которые весь день беспокоятся о том, чтобы сделать это волшебным образом быстро. [

] [

]В c# есть несколько ловушек, и использование памяти, как правило, сопровождается созданием множества крошечных объектов случайно (делать строку = строка + другая строка в цикле - это классика)[

] [

]Существует memprofiler, который покажет вам, что происходит, если вы действительно думаете, что у вас есть проблемы с памятью, вызванные управлением[

] [

]Я написал много кода с высокой производительностью (клиенты рендеринга графики, сетевые серверы) на c# и никогда не беспокоился ни о чем из этого[

].
1
ответ дан 1 December 2019 в 23:15
поделиться

Не дайте себя обмануть ключевым словом new , оно необязательно для структур.

В C # есть управляемый мир, в котором вы пользуетесь сборщиком мусора и безопасностью типов и не беспокоитесь (не должны) о многих деталях памяти. Разница в стеке и куче не имеет значения, дело в семантике копирования.

Для тех редких случаев, когда вам нужен контроль, есть небезопасная (неуправляемая) часть C # с реальными указателями и всем остальным.

Но стоимость вещей в C # отличается от стоимости в C ++, поэтому не охотьтесь на призраков, неуправляемые, недолговечные объекты очень дешевы. И компилятор может размещать небольшие массивы в стеке в качестве оптимизации, вы не сможете сказать, и вам это тоже не нужно.

2
ответ дан 1 December 2019 в 23:15
поделиться

Это неправильный способ просмотра структур и классов в C #. В C # разница между структурой и классом заключается не в том, где она размещена, а в семантике копирования. Структура имеет семантику значения, а класс - семантику ссылки. Программисты на C ++ склонны больше читать об этом, поскольку они привыкли к объектам в стеке, имеющим семантику значений, и объектам в куче, имеющим ссылочную семантику.

Как распределяется эта память, является деталью реализации среды выполнения. Среда выполнения может использовать стеки, кучи или любую другую схему гибридного распределения, которая ей нравится. Хотя верно, что обычно структуры будут размещаться в чем-то вроде стека, а классы будут размещаться в какой-то куче, это не требуется. Например, вместо этого класс, выделенный в функции и не переданный за пределы функции, может быть легко размещен в стеке.

1
ответ дан 1 December 2019 в 23:15
поделиться

Ваше объяснение того, куда идут типы значений и типы ссылок (stack v. heap), неверно.

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

Следует прочитать http://www.yoda.arachsys.com/csharp/memory.html , чтобы лучше понять, где фактически распределяются различные типы.

В отдельном примечании, в .Net, вам действительно не должно быть важно, где типы выделены - как Эрик Липперт пишет: стек является детализацией реализации . Лучше понимать семантику передачи типов (по значению, быть ссылкой и т.д.).

Кроме того, создается впечатление, что выделение объекта в куче дороже, чем в стеке. На самом деле, я бы утверждал, что стоимость производительности копирования типов значений перевешивает выгоду от любой экономии в несколько более быстром распределении на стеке. Самое большое различие между стеком и кучой заключается в том, что на большинстве архитектур ЦП стек с большей вероятностью будет храниться в кэш-памяти ЦП, что позволит избежать промахов кэш-памяти.

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

6
ответ дан 1 December 2019 в 23:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: