Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preallocate files during creation/extraction when sensible #26

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

WulfyStylez
Copy link

Using writes to successively allocate files thrashes disks in a lot of situations. This is due to filesystem meta being updated each time a write is issued, incurring extra seeks.
This alleviates the issue without adding extra overhead for smaller files which wouldn't benefit from preallocation.
Extraction tests on a 5400RPM 360 disk saw speeds increase from ~11MiB/s to the max write speed of the disk. This should make nearly every use case for both creation and extraction faster, however.

@@ -1627,6 +1627,14 @@ int extract_file( int in_xiso, dir_node *in_file, modes in_mode , char* path) {

if ( ! err && lseek( in_xiso, (xoff_t) in_file->start_sector * XISO_SECTOR_SIZE + s_xbox_disc_lseek, SEEK_SET ) == -1 ) seek_err();

// preallocate this file if it's not tiny
if(in_file->file_size >= (READWRITE_BUFFER_SIZE * 2))
Copy link
Member

@JayFoxRox JayFoxRox Jun 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should happen before the seek in the XISO, so we can possibly group it into a open_preallocated(in_file->filename, WRITEFLAGS, 0644, in_file->file_size)

Edit: I see this won't be possible due to the use in write_file - should still be moved upwards in my opinion.

if ( lseek( out, (xoff_t) in_file->file_size-1, SEEK_SET ) == -1 ) seek_err();
if ( write( out, "\0", 1 ) != (int) 1 ) write_err();
if ( lseek( out, (xoff_t) 0, SEEK_SET ) == -1 ) seek_err();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this scope will depend on !err for open.

{
if ( lseek( in_context->xiso, (xoff_t) (in_avl->start_sector * XISO_SECTOR_SIZE) + in_avl->file_size - 1, SEEK_SET ) == -1 ) seek_err();
if ( write( in_context->xiso, "\0", 1 ) != (int) 1 ) write_err();
}
Copy link
Member

@JayFoxRox JayFoxRox Jun 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be moved into a function like preallocate_file or something.

Edit: This will unfortunately include the dangerous case where it's used to overwrite existing data with a zero-byte; maybe https://linux.die.net/man/3/posix_fallocate ?

@JayFoxRox
Copy link
Member

JayFoxRox commented Jun 4, 2019

This is due to filesystem meta being updated each time a write is issued, incurring extra seeks.
[...]
Extraction tests on a 5400RPM 360 disk saw speeds increase from ~11MiB/s to the max write speed of the disk. This should make nearly every use case for both creation and extraction faster, however.

I'm surprised by this. What OS, what filesystem and what's the maximum write speed?
I'd imagine that the OS or FS layer will cache these changes.

Note: we will obviously support any ordinary harddisk (like Xbox 360 harddisks); but I'd imagine that we will probably focus on original Xbox and stop supporting Xbox 360 DVDs in the future (see #28 ).


nit: We use prefix-style commit messages now [prefix: Short description] (as for most XboxDev projects). Edit: We discussed this internally (on XboxDev Discord), and we don't care about commit message style for this repository - we are fine with inconsistency.

However, I'm open to accepting this as-is (including what I mentioned in review comments) because the old code-quality is horrible anyway (so my expectations aren't too high either).

if(in_file->file_size >= (READWRITE_BUFFER_SIZE * 2))
{
if ( lseek( out, (xoff_t) in_file->file_size-1, SEEK_SET ) == -1 ) seek_err();
if ( write( out, "\0", 1 ) != (int) 1 ) write_err();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "\x00"

(Personal preference)

@GXTX
Copy link
Contributor

GXTX commented Apr 7, 2020

Hey @WulfyStylez, any status on this or abandoned?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants