|
|
| dloneranger |
| Posted: Dec 14 2010, 06:50 PM |
 |
|
Moderator
  
Group: Moderators
Posts: 2366
Member No.: 22158
Joined: 26-September 07

|
From Vista and upwards, theres the concept of the file IO routines having a priority (similar to thread priority idle, lower than normal, normal)
Because the source code doesn't use these features I had a play with runtime checing/loading the required dll information and use it if available
[edit] Just for testing I put this function into the system unit file.cpp in the file open functions that open for writing Added -> SetFilePri( filehandle , true );
This sets the files's IO priority to lower-than-normal-priority after the file opens I left the non-write file alone as they'll throttle down to the speed of the writing file all by themself, and there's not much point in throttling dwon files that are just open in the gui
The results are quite nice, and improve system responsivness when the same hard drive is being used by virtualdub and anything else (Virtualdub will backoffs when the OS decides the drive is needed by a normal priority IO, but not a lot)
In practice the result is very much like setting a threads priority to lower than normal Large direct stream save-as's don't hog the hard drive, general system responsiveness feels smoother while processing batch jobs, etc
Here's the sources for it It's very basic, as a quick test version
IOPri.h
| CODE | // copy/pasted from winbase.h, apart from SetFilePri and pSetFileInformationByHandle #include "stdafx.h" #include <windows.h>
typedef enum _FILE_INFO_BY_HANDLE_CLASS { FileBasicInfo, FileStandardInfo, FileNameInfo, FileRenameInfo, FileDispositionInfo, FileAllocationInfo, FileEndOfFileInfo, FileStreamInfo, FileCompressionInfo, FileAttributeTagInfo, FileIdBothDirectoryInfo, FileIdBothDirectoryRestartInfo, FileIoPriorityHintInfo, MaximumFileInfoByHandleClass } FILE_INFO_BY_HANDLE_CLASS, *PFILE_INFO_BY_HANDLE_CLASS;
typedef struct _FILE_BASIC_INFO { LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; DWORD FileAttributes; } FILE_BASIC_INFO, *PFILE_BASIC_INFO;
typedef struct _FILE_STANDARD_INFO { LARGE_INTEGER AllocationSize; LARGE_INTEGER EndOfFile; DWORD NumberOfLinks; BOOLEAN DeletePending; BOOLEAN Directory; } FILE_STANDARD_INFO, *PFILE_STANDARD_INFO;
typedef struct _FILE_NAME_INFO { DWORD FileNameLength; WCHAR FileName[1]; } FILE_NAME_INFO, *PFILE_NAME_INFO;
typedef struct _FILE_RENAME_INFO { BOOLEAN ReplaceIfExists; HANDLE RootDirectory; DWORD FileNameLength; WCHAR FileName[1]; } FILE_RENAME_INFO, *PFILE_RENAME_INFO;
typedef struct _FILE_ALLOCATION_INFO { LARGE_INTEGER AllocationSize; } FILE_ALLOCATION_INFO, *PFILE_ALLOCATION_INFO;
typedef struct _FILE_END_OF_FILE_INFO { LARGE_INTEGER EndOfFile; } FILE_END_OF_FILE_INFO, *PFILE_END_OF_FILE_INFO;
typedef struct _FILE_STREAM_INFO { DWORD NextEntryOffset; DWORD StreamNameLength; LARGE_INTEGER StreamSize; LARGE_INTEGER StreamAllocationSize; WCHAR StreamName[1]; } FILE_STREAM_INFO, *PFILE_STREAM_INFO;
typedef struct _FILE_COMPRESSION_INFO { LARGE_INTEGER CompressedFileSize; WORD CompressionFormat; UCHAR CompressionUnitShift; UCHAR ChunkShift; UCHAR ClusterShift; UCHAR Reserved[3]; } FILE_COMPRESSION_INFO, *PFILE_COMPRESSION_INFO;
typedef struct _FILE_ATTRIBUTE_TAG_INFO { DWORD FileAttributes; DWORD ReparseTag; } FILE_ATTRIBUTE_TAG_INFO, *PFILE_ATTRIBUTE_TAG_INFO;
typedef struct _FILE_DISPOSITION_INFO { BOOLEAN DeleteFile; } FILE_DISPOSITION_INFO, *PFILE_DISPOSITION_INFO;
typedef struct _FILE_ID_BOTH_DIR_INFO { DWORD NextEntryOffset; DWORD FileIndex; LARGE_INTEGER CreationTime; LARGE_INTEGER LastAccessTime; LARGE_INTEGER LastWriteTime; LARGE_INTEGER ChangeTime; LARGE_INTEGER EndOfFile; LARGE_INTEGER AllocationSize; DWORD FileAttributes; DWORD FileNameLength; DWORD EaSize; CCHAR ShortNameLength; WCHAR ShortName[12]; LARGE_INTEGER FileId; WCHAR FileName[1]; } FILE_ID_BOTH_DIR_INFO, *PFILE_ID_BOTH_DIR_INFO;
typedef enum _PRIORITY_HINT { IoPriorityHintVeryLow = 0, IoPriorityHintLow, IoPriorityHintNormal, MaximumIoPriorityHintType } PRIORITY_HINT;
typedef struct _FILE_IO_PRIORITY_HINT_INFO { PRIORITY_HINT PriorityHint; } FILE_IO_PRIORITY_HINT_INFO, *PFILE_IO_PRIORITY_HINT_INFO;
BOOL WINAPI SetFileInformationByHandle( __in HANDLE hFile, __in FILE_INFO_BY_HANDLE_CLASS FileInformationClass, __in_bcount(dwBufferSize) LPVOID lpFileInformation, __in DWORD dwBufferSize );
typedef BOOL ( __stdcall *pSetFileInformationByHandle) ( __in HANDLE hFile, __in FILE_INFO_BY_HANDLE_CLASS FileInformationClass, __in_bcount(dwBufferSize) LPVOID lpFileInformation, __in DWORD dwBufferSize );
bool SetFilePri( HANDLE fhandle, bool lowpri ); |
IOPri.cpp
| CODE | #include "stdafx.h" #include <windows.h>
#include "IOPri.h"
bool Checked=false; bool Avail=false;
pSetFileInformationByHandle setpri;
bool SetFilePri( HANDLE fhandle, bool lowpri ) { bool DidSet=false; bool IsAtLeastVista = (sint32)(GetVersion() & 0x800000FF) >= 6; if (( !Checked )) { if (HINSTANCE hInst = LoadLibrary("Kernel32.dll")) { setpri = ( pSetFileInformationByHandle ) GetProcAddress( hInst,"SetFileInformationByHandle" );
if (setpri) { if (IsAtLeastVista) Avail=true; }; Checked=true; }; };
if (Avail) { FILE_IO_PRIORITY_HINT_INFO pp; if (lowpri) pp.PriorityHint = IoPriorityHintLow; else pp.PriorityHint = IoPriorityHintNormal; //not actually needed, default of file is normal
if ( setpri( fhandle,FileIoPriorityHintInfo,&pp,sizeof( FILE_IO_PRIORITY_HINT_INFO ) ) ) DidSet= true; }; return DidSet; };
|
This post has been edited by dloneranger on Dec 15 2010, 11:45 PM
-------------------- MultiAdjust JoinWav WavNormalize FFMPeg Input Plugin v1827 UnSharpMask Windows7/8 Codec Chooser All FccHandlers Stuff inc. Installers for acm codecs AAC, AC3, LameMp3 |
 |
| phaeron |
| Posted: Dec 19 2010, 11:48 PM |
 |
|

Virtualdub Developer
  
Group: Administrator
Posts: 7773
Member No.: 61
Joined: 30-July 02

|
This seems like a good idea, but I wonder if it might be a better idea to call SetPriorityClass() and just change all threads to background mode -- might be a bit easier than hunting down all of the file handles, which would be particularly troublesome in plugins (input plugins would have to also call this function). |
 |
| dloneranger |
| Posted: Dec 20 2010, 12:00 AM |
 |
|
Moderator
  
Group: Moderators
Posts: 2366
Member No.: 22158
Joined: 26-September 07

|
Trouble with going to vista's background idle priority is it's really, really low - high disk activity can throttle it down to almost zero, and there's no middle ground
The nice thing about this I think, is that you just call it on a file handle and it's done, you don't need to do anything later on, or keep track that you've done it I've just added it at the end of the create async file routines, to set all writeable files to low priority That throttles back the output files, the input files self throttle on the output file, while editing in the gui is left alone as they're opened with read only privileges
That said, if input plugins are calling createfile themselves, that's skip the simple insert of code into the async file routines
-------------------- MultiAdjust JoinWav WavNormalize FFMPeg Input Plugin v1827 UnSharpMask Windows7/8 Codec Chooser All FccHandlers Stuff inc. Installers for acm codecs AAC, AC3, LameMp3 |
 |
|