Запрос БД .NET без выделения? - PullRequest
2 голосов
/ 11 апреля 2010

Мне было поручено переписать некоторые библиотеки, написанные на C #, чтобы после завершения запуска не было выделений.

Я только что попал в один проект, который каждые 30 секунд выполняет несколько запросов к БД через OdbcConnection. Я всегда просто использовал .ExecuteReader (), который создает OdbcDataReader. Существует ли какой-либо шаблон (например, шаблон сокета SocketAsyncEventArgs), который позволяет повторно использовать собственный OdbcDataReader? Или какой-то другой умный способ избежать выделения?

Я не удосужился изучить LINQ, поскольку все работающие базы данных основаны на Oracle, и, в последний раз, когда я проверял, не было официального поставщика Linq To Oracle. Но если есть способ сделать это в Linq, я мог бы использовать один из сторонних.

Обновление:

Я не думаю, что я четко указал причины требования no-alloc. У нас запущен один критический поток, и очень важно, чтобы он не зависал. Это приложение для торговли почти в реальном времени, и мы видим до 100 мс замораживания для некоторых коллекций второго поколения. (Я также слышал об играх, написанных таким же образом на C #). Существует один фоновый поток, который выполняет некоторую проверку соответствия и запускается каждые 30 секунд. Это делает запрос БД прямо сейчас. Запрос выполняется довольно медленно (около 500 мс для возврата со всеми данными), но это нормально, поскольку он не мешает критическому потоку. За исключением случаев, когда рабочий поток выделяет память, он вызывает GC, которые замораживают все потоки.

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

Теперь, очевидно, есть способы, которыми я мог бы вводить данные в этот процесс без выделения ресурсов. Я мог бы настроить другой процесс и подключить его к этому с помощью сокета. Новые сокеты .NET 3.5 были специально оптимизированы, чтобы вообще не выделяться, используя новый шаблон SocketAsyncEventArgs. (На самом деле, мы используем их для подключения к нескольким системам и никогда не видим из них GC.) Затем создайте предварительно выделенный байтовый массив, который читает данные из сокета и просматривает данные, не выделяя при этом никаких строк. (Я не знаком с другими формами IPC в .NET, поэтому я не уверен, выделяют ли отображаемые в памяти файлы и именованные каналы или нет).

Но если есть более быстрый способ выполнить этот запрос без выделения ресурсов без прохождения всех этих хлопот, я бы предпочел его.

Ответы [ 3 ]

3 голосов
/ 11 апреля 2010

Вы не можете повторно использовать IDataReader (или OdbcDataReader или SqlDataReader или любой другой эквивалентный класс). Они предназначены для использования только с одним запросом. Эти объекты инкапсулируют один набор записей, поэтому, как только вы получите и итерируете его, он больше не будет иметь смысла.

Создание программы чтения данных в любом случае является невероятно дешевой операцией, которая ничтожно мала по сравнению с затратами на фактическое выполнение запроса. Я не вижу логической причины для этого требования "без распределения".

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

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

2 голосов
/ 11 апреля 2010

Для такого требования вы уверены, что язык высокого уровня, такой как C #, является вашим выбором?
Вы не можете сказать, используют ли используемые вами функции библиотеки .NET внутреннюю память или нет. Стандарт не гарантирует этого, поэтому, если они не используют выделения в текущей версии .NET Framework, они могут начать делать это позже.

1 голос
/ 11 апреля 2010

Я предлагаю вам профилировать приложение, чтобы определить, на что тратится время и / или память. Не угадай - ты только угадаешь неправильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...