Welcome Guest ( Log In | Register )


Important

The forums will be closing permanently the weekend of March 15th. Please see the notice in the announcements forum for details.

 
File Priority (for Os)
« Next Oldest | Next Newest » Track this topic | Email this topic | Print this topic
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
 
    Top
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).
 
    Top
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
 
    Top
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:
2 replies since Dec 14 2010, 06:50 PM Track this topic | Email this topic | Print this topic

<< Back to VirtualDub Development Forum