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

Writing multiple files on OS X #3623

Closed
speg opened this issue Nov 1, 2015 · 6 comments
Closed

Writing multiple files on OS X #3623

speg opened this issue Nov 1, 2015 · 6 comments
Labels
fs Issues and PRs related to the fs subsystem / file system. macos Issues and PRs related to the macOS platform / OSX.

Comments

@speg
Copy link

speg commented Nov 1, 2015

I was trying to experiment with my understanding of node and wanted to test a simple assumption:

Node can write to two files at the same time.

fs = require('fs')

var bufferA = new Buffer(1e+8)
bufferA.fill(0)

var bufferB = new Buffer(1e+0)
bufferB.fill(0)

var fileA = fs.openSync('fileA', 'w')
var fileB = fs.openSync('fileB', 'w')

console.time('A')
fs.write(fileA, bufferA, 0, bufferA.length, function(err) { console.timeEnd('A')})
console.time('B')
fs.write(fileB, bufferB, 0, bufferB.length, function(err) { console.timeEnd('B')})

Two buffers, filled with zeros. A is very large, B is very small. B should finish first?

On Linux I get:

B: 4ms
A: 306ms

But on OS X (10.11.1) I get:

A: 314.564ms
B: 315.864ms

A commentor on StackOverflow confirms my Linux results on his Windows machine.
I tried with node 5.0, 4.1, and 0.12 on OS X. All similar results. It looks like fs.write is waiting for fileA to complete until fileB can write.

Is there a known issue with fs.write on OS X?

@mscdex
Copy link
Contributor

mscdex commented Nov 1, 2015

Did you try confirming that it's actually blocking by adding an interval timer that logs to the screen or something?

@mscdex mscdex added fs Issues and PRs related to the fs subsystem / file system. macos Issues and PRs related to the macOS platform / OSX. labels Nov 1, 2015
@speg
Copy link
Author

speg commented Nov 1, 2015

@mscdex maybe blocking was the wrong word. My JS thread continues to run. It appears that fileB waits for fileA to finish though, when I expected both to be written concurrently, as it appears to be doing on the other platforms. Maybe OS X has a limit in the I/O thread pool? This level is a bit above my knowledge so I'm just guessing at this point.

@mscdex
Copy link
Contributor

mscdex commented Nov 1, 2015

You could set the UV_THREADPOOL_SIZE environment variable to something higher than the default of 4 to rule something like that out. However I wouldn't expect that to be the cause.

@bnoordhuis
Copy link
Member

Libuv serializes disk writes on OS X due to a nasty quirk documented here. It's possible newer OS X releases fare better but that hasn't been tested.

@speg
Copy link
Author

speg commented Nov 1, 2015

Thank you @bnoordhuis 🙇

@speg speg closed this as completed Nov 1, 2015
@bnoordhuis
Copy link
Member

@speg I see you've commented on reddit. To clarify: the nasty quirk is inside the OS X kernel, not libuv - libuv merely works around the kernel bug. You can find more background here.

Maybe calling it "kernel bug" is not quite right - POSIX allows for how OS X behaves, it doesn't say much about the concurrency model w.r.t. positional writes - but it's quality of implementation issue that doesn't affect other Unices and with good reason: it results in rather heinous data corruption.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system. macos Issues and PRs related to the macOS platform / OSX.
Projects
None yet
Development

No branches or pull requests

3 participants