В C#/. Сеть. Динамический тип занимает меньше места, чем объект?

StackOverflow https://stackoverflow.com/questions/4823213

Вопрос

У меня есть консольное приложение, которое позволяет пользователям указать переменные для обработки. Эти переменные бывают трех вкусов: струна, двойной и длинной (с двойным и длинным, безусловно, наиболее часто используемыми типами). Пользователь может указать любые переменные, которые им нравятся, и в любом порядке, поэтому моя система должна иметь возможность справиться с этим. С этой целью в моем заявлении я хранил их как объект, а затем набрал/раскрыл их по мере необходимости. Например:

public class UnitResponse
{
    public object Value { get; set; }
}

Насколько я понимаю, в штучной упаковке объекты занимают немного больше памяти (около 12 байтов), чем стандартный тип значения.

Мой вопрос: будет ли более эффективным использовать динамическое ключевое слово для хранения этих значений? Это может обойти проблему бокса/распаковки, и если это более эффективно, как это повлияет на производительность?

РЕДАКТИРОВАТЬ

Чтобы обеспечить некоторый контекст и предотвратить «Вы уверены, что используете достаточно оперативной памяти, чтобы беспокоиться об этом» в моем худшем случае, у меня есть 420 000 000 данных, о которых нужно беспокоиться (60 переменных * 7 000 000 записей). Это в дополнение к группе других данных, которые я храню о каждой переменной (включая несколько булеев и т. Д.). Таким образом, уменьшение памяти оказывает огромное влияние.

Это было полезно?

Решение

Хорошо, так что настоящий Вопрос здесь: «У меня есть огромный набор данных, который я храню в памяти, как оптимизировать его производительность как во времени, так и в пространстве памяти?»

Несколько мыслей:

  • Вы абсолютно правы ненавидеть и бояться бокса. Бокс имеет большие затраты. Во -первых, да, в штучной упаковке объекты занимают дополнительную память. Во -вторых, в штучных объектах хранятся на куче, а не на стеке или в регистрах. В -третьих, они собирают мусор; Каждый из этих объектов должен быть допрошен во время GC, чтобы увидеть, содержит ли он ссылку на другой объект, который он никогда не будет, и это много времени в потоке GC. Вам почти наверняка нужно что -то сделать, чтобы избежать бокса.

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

Это грубо, но вы можете рассмотреть возможность использования структуры, чей макет разделяет память между различными областями - например, союз в C. Действительно действительно грубо а также совсем не безопасно Но это может помочь в таких ситуациях. Сделайте веб -поиск "structlayoutattribute"; Вы найдете учебники.

  • Длинный, двойной или струнный, правда? Нельзя быть Int, Float или String? Данные действительно ли либо превышают несколько миллиардов величины, либо точные до 15 десятичных знаков? Разве Int and Float не выполнит работу по 99% случаев? Они вдвое меньше.

Обычно я не рекомендую использовать Float вдвое больше, потому что это ложная экономика; Люди часто экономиют так, когда у них есть одно число, например, сбережения четырех байтов будут иметь значение. Разница между 42 миллионами поплавков и 42 миллиона удвоений является значительной.

  • Есть ли регулярность в данных, которые вы можете использовать? Например, предположим, что из ваших 42 миллионов записей, существует только 100000 фактических значений для, скажем, каждого длинного, 100000 значений для каждого двойного и 100000 значений для каждой строки. В этом случае вы делаете индексированное хранилище для долгосрочных, удвоенных и струн, а затем каждая запись получает целое число, где низкие биты являются индексом, а два лучших бита указывают, из какого хранилища его вытащить. Теперь у вас есть 42 миллиона записей, каждый из которых содержит Int, а значения хранятся в какой -то хорошо компактной форме где -то еще.

  • Хранить логические в качестве кусочков в байте; Напишите свойства, чтобы сделать переключение бита, чтобы вытащить их. Сохраните себя несколькими байтами таким образом.

  • Помните, что память на самом деле является дисковым пространством; ОЗУ - это просто удобный кеш на вершине. Если набор данных будет слишком большим, чтобы держать в оперативной памяти, тогда что-нибудь Собирается обратно его обратно на диск и прочитать его позже; Это может быть вы, или это может быть операционная система. Вполне возможно, что вы знаете больше о своей местности данных, чем операционная система. Вы можете написать свои данные на диск в какой-то удобно продуманной форме (например, B-дереве) и быть более эффективными в том, чтобы сохранить вещи на диске и привести их в память только тогда, когда вам это нужно.

Другие советы

Я думаю, что вы можете смотреть на неправильную вещь здесь. Помните, что делает динамика. Это Запускает компилятор снова, в процессе, во время выполнения. Анкет Он загружает сотни тысяч байтов кода для компилятора, а затем на каждом участке вызовов он выделяет кэши, которые содержат результаты свежеприготовленного IL для каждой динамической операции. Вы тратите несколько сотен тысяч байтов, чтобы сэкономить восемь. Это кажется плохой идеей.

И, конечно, вы ничего не спасли. «Динамика» - это просто «объект» с причудливой шляпой. «Динамические» объекты по -прежнему остаются в штучной упаковке.

Нет. dynamic связан с Как выполняются операции на объекте, не то, как хранится сам объект. В этом конкретном контексте типы значений все еще будут в штучной упаковке.

Кроме того, действительно ли все эти усилия стоит 12 байтов на объект? Конечно, есть лучшее использование для вашего времени, чем сэкономить несколько килобитов (если это) RAM? Вы доказали, что использование RAM по вашей программе на самом деле является проблемой?

Нет. Dynamic будет просто хранить его как объект.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top