SCSI порт-драйвер и производительность
От: x64 Россия http://x64blog.name
Дата: 27.11.12 20:59
Оценка:
Привет.

Ситуация такая. Пишу полноценный SCSI порт-драйвер (не использующий ни ScsiPort, ни StorPort), работает всё замечательно на всех системах, но сильно проседает производительность на малых блоках (порядка 4 КБ). Архитектура вполне стандартная: есть драйвер виртуальной шины, на своей шине он обнаруживает опять же виртуальное дисковое устройство, которое сообщает о себе, как о GenDisk, в результате на него вешаются disk.sys, partmgr.sys и ещё classpnp.sys сбоку. Обрабатываю SCSI-команды плюс некоторые IOCTL, про PnP, Power и WMI и не говорю, это само собой. В качестве непосредственно хранилища данных у меня файл, память, сеть, в общем, всё, что угодно, только не реальная железка. Почему озаботился проблемой, потому что написанный мной же legacy виртуальный диск, который по уровню сидит примерно там же, где драйвер класса, выдаёт минимум в 2 раза большую производительность, на малых блоках в особенности, — хочется добиться того же, но с порт-драйвером, ну или хотя бы убедиться, что это нереально.

Теперь о том, что уже пробовал. Выставление полей MaximumPhysicalPages и MaximumTransferLength в структуре STORAGE_ADAPTER_DESCRIPTOR действительно влияет на производительность самым непосредственным образом, но, к сожалению, увеличение этих параметров имеет смысл только до определённого предела, во-вторых, это влияет только на ввод/вывод большими блоками. Реализация write-caching, когда запрос SCSIOP_WRITE завершается до того, как данные фактически записаны мною, даёт некоторый эффект только для записи и не всегда, мне же нужно и для чтения тоже. Реализация очереди pending-запросов вообще даёт обратный эффект, т.к. накладных расходов становится больше (об этом в следующем абзаце). Обработка mode sense/select с кодом caching никак не влияет на storage stack, по сути, это управление исключительно портом/железкой. Помимо прочего, пробовал работать с буфером pSrb -> DataBuffer напрямую, минуя MDL, это действительно даёт ещё некоторый прирост скорости, проблема в том, что в случае paging I/O этот буфер может быть не валиден, а вот корректно распознать paging I/O на этом уровне не всегда есть возможность, даже если использовать недокументированные флаги и кое-какую эвристику.

Отдельно про queueing пару слов. Поддержка command queueing или не реализована в Windows вообще, или я что-то делаю неправильно (а как правильно и возможно ли вообще на этом уровне — вопрос открытый), но так или иначе мне не удалось заставить этот механизм работать (ставлю CommandQueueing в TRUE в обоих дескрипторах в IOCTL). Смотрел исходники classpnp/disk в WDK, но то ли они не соответствуют действительности, то ли ещё что, но я не увидел там полноценной реализации этого механизма. Получается, что все запросы, которые драйвер класса шлёт (мини-)порту — они все untagged, что выливается в значениях QueueTag = 0, QueueSortKey = 0 и QueueAction = SRB_FLAGS_QUEUE_ACTION_ENABLE в структуре SRB (что означает, что queueing вообще-то включен и работает, но...), при этом тег всегда 0, во сколько бы потоков я не запускал стресс-тесты. Подозреваю, что эти значения не для порт-драйвера, а для кого-то ниже (железка?), но у меня нет никого ниже, шина чисто номинальная. Тут ещё такой момент (как раз про отложенную обработку) — по спецификации нельзя слать более одного untagged-запроса за раз, т.е. если ранее уже был послен untagged-запрос, то его необходимо дождаться, что драйвер класса и делает (вот тут он, зараза, следует спецификации по полной программе, где ж всё остальное-то), но проблема в том, что от него все запросы — untagged, поэтому он никогда не шлёт read/write-запросы пачками, всегда строго последовательно, например, если я вставлю задержку в 2 секунды в обработчик чтения, то и получать буду не более одного read-запроса в 2 секунды, что попахивает каким-то маразмом, по-моему.

Любые идеи приветствуются, включая грязнохаки, может где чего подкрутить можно, может я что-то очевидное упустил? Просьба не отсылать в поиск, в гугл и уж тем более на osronline.com, — это, кстати, отдельная песня, там этот вопрос обсасывался огромное кол-во раз, но никто из тамошних "гуру" так и не смог дать реально конкретный ответ на указанные выше вопросы. В гугле был и был много, информации крайне мало, что, в принципе, ожидаемо, т.к. порт-драйвера недокументированы, вместо них предлагается писать минипорты, которые мне в данный момент не подходят, да и совсем не факт, что они смогут обеспечить требуемую производительность. Исходники порт-драйверов в сети есть, видел пару, но там всё сильно упрощённо и авторы, похоже, о производительности не парились вообще.

Как-то так.
Заранее спасибо.
JID: x64j@jabber.ru
scsi порт-драйвер
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.