Запретить своп приложения в виртуальную память

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Gasparini
Новичок
Новичок
 
Сообщения: 49
Зарегистрирован: 06.09.2012 (Чт) 14:42

Запретить своп приложения в виртуальную память

Сообщение Gasparini » 20.10.2012 (Сб) 12:36

Здравствуйте, уважаемые форумчане.

Мне необходимо реализовать процедуру, которая бы делала так, чтобы мое приложение при работе не свопилось на диск системой, а работало в физической памяти (100% гарантии никто не даст, но 100% мне не критично).

Реализую это так:

Код: Выделить всё
Public Const MBSize = 1048576 '1 MB

Public Sub SetProcessMemoryNoSwap()
    Dim lRes As Long
    MinMemory = 35 * MBSize '35 MB
    MaxMemory = 75 * MBSize '75 MB
        If SetProcessWorkingSetSize(GetCurrentProcess, MinMemory, MaxMemory) = 0 Then
            'SetProcessWorkingSetSize is failed           
            Debug.Print "WARNING: SetProcessWorkingSetSize Function is failed."
        Else
            'SetProcessWorkingSetSize is success
            'Allocate memory
            lMemoryAllocated = VirtualAlloc(ByVal 0&, MaxMemory - MinMemory, MEM_COMMIT, PAGE_READWRITE)
            'Try to LockMemory
            lRes = VirtualLock(lMemoryAllocated, MaxMemory - MinMemory)
            If lRes <> 0 Then
                'Memory Lock is success
                Debug.Print "Memory usage set is success."
            Else
                Debug.Print "Memory usage set is failed. Error #" & CStr(Err.LastDllError)
            End If
        End If
'   End If
End Sub


P.S. Само собой перед закрытием делаю VirtualUnlock и все освобождаю.

Если беру пару мегабайт, то код работает нормально, если больше 3-х например, то ошибка 998 "Invalid access to memory location".

Я так понял, что делаю всё неправильно, помогите понять, плз.
Мне видимо нужно получить адресное пространство памяти, в которой работает мое приложение и применить VirtualLock к ней, или нет?
Как это сделать?

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Запретить своп приложения в виртуальную память

Сообщение VBTerminator » 21.10.2012 (Вс) 7:53

По пунктам:
  1. К сожалению, выделить память из неподкачиваемого пула могут только драйвера. А зачем, кстати, это надо?
  2. VitrualAlloc ничего не гарантирует насчёт подкачки.
  3. "Invalid access to memory location" - ты пытаешься выделить память там, где у тебя недостаточно прав, например, в проекции ядра.
  4. Согласно Хабрахабру все функции *Lock и *Unlock являются всего лишь заглушками.

Gasparini
Новичок
Новичок
 
Сообщения: 49
Зарегистрирован: 06.09.2012 (Чт) 14:42

Re: Запретить своп приложения в виртуальную память

Сообщение Gasparini » 21.10.2012 (Вс) 9:23

VBTerminator писал(а):К сожалению, выделить память из неподкачиваемого пула могут только драйвера. А зачем, кстати, это надо?

Как это?
В MSDN же написано про функции VirtualLock и VirutalUnlock и обычные приложения.

Моё приложение по определенным причинам в системах Vista и Seven запускается из планировщика заданий. Связано с нюансами UAC, который не позволяет моему приложению грузится из автозагрузки несмотря на любые манифесты и цифровую подпись.

Один неопциональный нюанс Планировщика заданий Windows 2.0 в том, что все активные выполняемые задания постепенно скидываются в своп из физической памяти. В итоге интерфейс приложения долго думает и тупит из-за этого, оно становится тугодумным. Мне надо поставить запрет на скидывание в своп. В MSDN написано, что делается это связкой функций SetProcessWorkingSetSize и VirtualLock. Но я подозреваю, что делаю это неправильно.

VBTerminator писал(а):VitrualAlloc ничего не гарантирует насчёт подкачки.

Я знаю об этом. Я сразу написал, что мне не нужна 100% гарантия.
В подавляющем большинстве случаев это будет работать.

VBTerminator писал(а):"Invalid access to memory location" - ты пытаешься выделить память там, где у тебя недостаточно прав, например, в проекции ядра.

Мне VitrualAlloc возвращает место для работы с памятью, вроде, получается он возвращает место где у меня нет прав?
Я так понял, что делаю неправильно и мне надо найти и сделать VirutalLock пространству, в котором работает мое приложение, а не просто где-то место зарезирвировать.

Так или я туплю?
VBTerminator писал(а):Согласно Хабрахабру все функции *Lock и *Unlock являются всего лишь заглушками.

Там речь идет про древние GlobalLock и GlobalUnlock вроде. Эти да - давно заглушки, всегда True будут возвращать.

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Запретить своп приложения в виртуальную память

Сообщение VBTerminator » 21.10.2012 (Вс) 9:49

Gasparini писал(а):В MSDN же написано про функции VirtualLock и VirutalUnlock и обычные приложения.

Ах, да:
Locking pages into memory may degrade the performance of the system by reducing the available RAM and forcing the system to swap out other critical pages to the paging file.


Gasparini писал(а):Я знаю об этом. Я сразу написал, что мне не нужна 100% гарантия.
В подавляющем большинстве случаев это будет работать.

Эмм... А разве VirtualLock не забирает пространство именно виртуальной памяти, не работая со свопом вообще?

Gasparini писал(а):Мне VitrualAlloc возвращает место для работы с памятью, вроде, получается он возвращает место где у меня нет прав?

Получается, что да.

Gasparini писал(а):... мне надо найти и сделать VirutalLock пространству, в котором работает мое приложение, а не просто где-то место зарезирвировать?

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

Gasparini писал(а):Там речь идет про древние GlobalLock и GlobalUnlock вроде. Эти да - давно заглушки, всегда True будут возвращать.

Извиняюсь, перепутал.

А так, надо ждать Хакера.

Gasparini
Новичок
Новичок
 
Сообщения: 49
Зарегистрирован: 06.09.2012 (Чт) 14:42

Re: Запретить своп приложения в виртуальную память

Сообщение Gasparini » 21.10.2012 (Вс) 10:24

VBTerminator писал(а):Locking pages into memory may degrade the performance of the system by reducing the available RAM and forcing the system to swap out other critical pages to the paging file.

Думаю, это было написано когда объем оперативной памяти был в диапозонах 128-512 Мб и всегда был критичен.

Я понимаю, что это эгоизм и неправильно, но не думаю, что с текущими объемами оперативной памяти на борту компьютеров, зарезирвировав ~50 Мб физической ОЗУ другим не достанется места.

Дело в том, что другой выход в моем случае сложно найти.
Если бы моё приложение просто запускалось из автозагрузки со включенным UAC, я бы и рад был обойтись без этих сложностей.

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

VBTerminator
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 415
Зарегистрирован: 19.11.2008 (Ср) 20:10

Re: Запретить своп приложения в виртуальную память

Сообщение VBTerminator » 21.10.2012 (Вс) 10:44

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

Если ты делаешь программу только для себя, тогда проще вообще выключить в настройках Windows подкачку.

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

Выделение неподкачиваемой памяти создавалось исключительно для поддержки драйверами DMA-устройств (использующих оперативную память в качестве буфера), не дружащих с подкачкой.

Gasparini
Новичок
Новичок
 
Сообщения: 49
Зарегистрирован: 06.09.2012 (Чт) 14:42

Re: Запретить своп приложения в виртуальную память

Сообщение Gasparini » 21.10.2012 (Вс) 12:07

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

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

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

VBTerminator писал(а):Если ты делаешь программу только для себя, тогда проще вообще выключить в настройках Windows подкачку.

Эххх, да если бы делал только для себя, то не покупал тогда цифровую подпись и не занимался длительным сексом с манфиестами...всё для упрямого UAC, который так и не запускает программу из автозагрузки. Всё испробовал - безрезультатно.
Планировщик был заюзан как единственный выход из создавшегося положения.

Может конечно кто-нибудь предложит вариант, как обойтись без планировщика и подружится с UAC, то я с радостью избавлюсь от столь замороченного способа.

NashRus
Постоялец
Постоялец
 
Сообщения: 388
Зарегистрирован: 18.03.2006 (Сб) 1:16

Re: Запретить своп приложения в виртуальную память

Сообщение NashRus » 21.10.2012 (Вс) 15:47

Сервис напиши.

И что-то не так во всей этой истории с дегродацией производительности.
Либо в архитектуре проблемы, либо в реализации.

Gasparini
Новичок
Новичок
 
Сообщения: 49
Зарегистрирован: 06.09.2012 (Чт) 14:42

Re: Запретить своп приложения в виртуальную память

Сообщение Gasparini » 21.10.2012 (Вс) 18:02

NashRus писал(а):Сервис напиши.

Смотрел в этом направлении.

1) Помню, что когда просматривал реализации сервисов на VB, то увидел, что они достаточно неудобные и мягко говоря нетривиально реализованы (не до такой конечно степени как мой путь с планировщиком заданий :) ).
Хотя может мне такие исходники попадались.

2) Если делать сервис, то придется делать по уму, отдельно сервис - отдельно оболочку с интерфейсом, сейчас приложение монолитное, всё завязано друг на друге, всё взаимосвязано, обьем же кода охрененно огромный.

Вобщем это самый сложный и нежелаемый выход в моем случае.
NashRus писал(а):И что-то не так во всей этой истории с дегродацией производительности.
Либо в архитектуре проблемы, либо в реализации.

Как раз производительность приложения-то нормальная.
Интерфейс реагирует ужасно, видно что всё постепенно подгружается, подтормаживает всё когда взаимодействуешь с интерфейсом.

В диспетчере задач процесс занимает ~16 Мб памяти вместо положенных 50 Мб.
Кликаешь по иконке в трее, окно появляется секунд через 5.
Если полазить какое-то время по интерфейсу, то всё реагиурует нормально, но стоит скрыть приложение и подождать какое-то время, как приложение снова свопится и тормоза с интерфейсом повторяются.

Если приложение запустить вручную, то эти проблемы не наблюдаются.

NashRus
Постоялец
Постоялец
 
Сообщения: 388
Зарегистрирован: 18.03.2006 (Сб) 1:16

Re: Запретить своп приложения в виртуальную память

Сообщение NashRus » 21.10.2012 (Вс) 18:35

Если кода много и всё сложно, значит по любому надо разбивать приложение.
Например, на функциональную часть и на часть управления: GUI, объектная модель, командная строка или что-то другое.

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

PS: но вот что точно не надо делать, так это вот пытаться даже думать в сторону сабжа этого топика.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Запретить своп приложения в виртуальную память

Сообщение Хакер » 21.10.2012 (Вс) 19:07

Gasparini писал(а):Если беру пару мегабайт, то код работает нормально, если больше 3-х например, то ошибка 998 "Invalid access to memory location".

При вызове VirtualLock? Это логично, потому что это защита от дурака: это сделано для того, чтобы никакой процесс не мог (пойдя в разнос) залочить себе половину физ. памяти и не мог таким образом вызвать чудовищное падение общесистемной производительности.

В общем, есть лимит для процессса, ограничивающий кол-во памяти, которое можно залочить VirtualLock-ом.

Если полазить какое-то время по интерфейсу, то всё реагиурует нормально, но стоит скрыть приложение и подождать какое-то время, как приложение снова свопится и тормоза с интерфейсом повторяются.

Есть такое дело. Я думал, это проблема только XP (когда-то давно tyomitch жаловался при переходе с Win2K на WinXP на этот косяк, особенно при переключении между сеансами, который, по его словам, был только в XP). Если его не поправили даже в Win7, то я вообще не смысла переходить на эти ужасные системы.

В общем, мысль такая: а как ты собрался бороться с этим, применяя VirtualLock? Какие именно страницы АП процесса ты хочешь лочить, чтобы описываемая беда с интерфейсом прошла?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Gasparini
Новичок
Новичок
 
Сообщения: 49
Зарегистрирован: 06.09.2012 (Чт) 14:42

Re: Запретить своп приложения в виртуальную память

Сообщение Gasparini » 22.10.2012 (Пн) 12:09

Слава богу, почитав интернет, нашел нормальное решение проблемы.

Планировщик заданий всегда ставит всем заданиям MemoryPriority = 3 и IO Priority = 1, это мягко говоря ниже среднего, почти минимум.
Кстати Windows 8 ставит MemoryPriority еще ниже.
От этого и все тормоза связанные с интерфейсом моего приложения, а судя по IO Priority еще видимо и с дисковыми операциями.

Поскольку моё приложение требует админских прав для работы, то при запуске я без проблем устанавливаю своему процессу MemoryPrority = 5 и IO Priority = 2, что является значениями по-умолчанию.
Это полностью разрешило проблему без прибегания к манипуляции с памятью.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 26

    TopList