1

I read the following blog: https://medium.com/@jerzy.chalupski/a-closer-look-at-the-okio-library-90336e37261

It is said that" the Sinks and Sources are often connected into a pipe. Smart folks at Square realized that there’s no need to copy the data between such pipe components like the java.io buffered streams do. All Sources and Sinks use Buffers under the hood, and Buffers keep the data in Segments, so quite often you can just take an entire Segment from one Buffer and move it to another."

I just dont understand where is the copy of data in java.io.

And in which case a Segment would be moved to another Buffer.

After i read source code of Okio. If writing strings to file by Okio like the following:

val sink = logFile.appendingSink().buffer()
sink.writeUtf8("xxxx")

there will be no "moving segment to another Buffer". Am i right?

唐子玄
  • 11
  • 2

1 Answers1

2

Java's BufferedReader is just a Reader that buffers data into a buffer – the buffer being a char[], or something like that – so that every time you need a bunch of bytes/chars from it, it doesn't need to read bytes from a file/network/whatever your byte source is (as long as it has buffered enough bytes). A BufferedWriter does the opposite operation: whenever you write a bunch of bytes to the BufferedWriter, it doesn't actually write bytes to a file/socket/whatever, but it "parks" them into a buffer, so that it can flush the buffer only once it's full. Overall, this minimises access to file/network/whatever, as it could be expensive.

When you pipe a BufferedReader to a BufferedWriter, you effectively have 2 buffers. How does Java move bytes from one buffer to the other? It copies them from the source to the sink using System.arraycopy (or something equivalent). Everything works well, except that copying a bunch of bytes requires an amount of time that grows linearly as the size of the buffer(s) grow. Hence, copying 1 MB will take roughly 1000 times more than copying 1 KB.

Okio, on the other hand, doesn't actually copy bytes. Oversimplifying the way it works, Okio has a single byte[] with the actual bytes, and the only thing that gets moved from the source to the sink is the pointer (or reference) to that byte[], which requires the same amount of time regardless of its size.

user2340612
  • 10,053
  • 4
  • 41
  • 66
  • May I ask that If Okio just get pointers from the source, how does it copy strings from a file to another? from what I know, you have to read strings from the source into a buffer and then get strings from the buffer and write into the dest file. How pointers write the actual strings into the dest files? – Chinese Cat Jun 15 '23 at 08:17
  • Okio internally uses Java's `InputStream` when it deals with files (see [here](https://github.com/square/okio/blob/master/okio/src/jvmMain/kotlin/okio/JvmOkio.kt#L182)). So the advantage is only after you crossed the bridge between Java and Okio – user2340612 Jun 15 '23 at 10:00