17
17
18
18
package org .apache .spark .util .collection .unsafe .sort ;
19
19
20
- import java .io .*;
20
+ import java .io .File ;
21
+ import java .io .IOException ;
21
22
22
23
import scala .Tuple2 ;
23
24
31
32
32
33
final class UnsafeSorterSpillWriter {
33
34
34
- private static final int SER_BUFFER_SIZE = 1024 * 1024 ; // TODO: tune this
35
+ static final int DISK_WRITE_BUFFER_SIZE = 1024 * 1024 ;
35
36
static final int EOF_MARKER = -1 ;
36
37
37
- private byte [] arr = new byte [SER_BUFFER_SIZE ];
38
+ // Small writes to DiskBlockObjectWriter will be fairly inefficient. Since there doesn't seem to
39
+ // be an API to directly transfer bytes from managed memory to the disk writer, we buffer
40
+ // data through a byte array. This array does not need to be large enough to hold a single
41
+ // record;
42
+ private byte [] writeBuffer = new byte [DISK_WRITE_BUFFER_SIZE ];
38
43
39
44
private final File file ;
40
45
private final BlockId blockId ;
41
46
private BlockObjectWriter writer ;
42
- private DataOutputStream dos ;
43
47
44
48
public UnsafeSorterSpillWriter (
45
49
BlockManager blockManager ,
@@ -55,32 +59,60 @@ public UnsafeSorterSpillWriter(
55
59
// around this, we pass a dummy no-op serializer.
56
60
writer = blockManager .getDiskWriter (
57
61
blockId , file , DummySerializerInstance .INSTANCE , fileBufferSize , writeMetrics );
58
- dos = new DataOutputStream (writer );
62
+ }
63
+
64
+ // Based on DataOutputStream.writeLong.
65
+ private void writeLongToBuffer (long v , int offset ) throws IOException {
66
+ writeBuffer [offset + 0 ] = (byte )(v >>> 56 );
67
+ writeBuffer [offset + 1 ] = (byte )(v >>> 48 );
68
+ writeBuffer [offset + 2 ] = (byte )(v >>> 40 );
69
+ writeBuffer [offset + 3 ] = (byte )(v >>> 32 );
70
+ writeBuffer [offset + 4 ] = (byte )(v >>> 24 );
71
+ writeBuffer [offset + 5 ] = (byte )(v >>> 16 );
72
+ writeBuffer [offset + 6 ] = (byte )(v >>> 8 );
73
+ writeBuffer [offset + 7 ] = (byte )(v >>> 0 );
74
+ }
75
+
76
+ // Based on DataOutputStream.writeInt.
77
+ private void writeIntToBuffer (int v , int offset ) throws IOException {
78
+ writeBuffer [offset + 0 ] = (byte )(v >>> 24 );
79
+ writeBuffer [offset + 1 ] = (byte )(v >>> 16 );
80
+ writeBuffer [offset + 2 ] = (byte )(v >>> 8 );
81
+ writeBuffer [offset + 3 ] = (byte )(v >>> 0 );
59
82
}
60
83
61
84
public void write (
62
85
Object baseObject ,
63
86
long baseOffset ,
64
87
int recordLength ,
65
88
long keyPrefix ) throws IOException {
66
- dos .writeInt (recordLength );
67
- dos .writeLong (keyPrefix );
68
- PlatformDependent .copyMemory (
69
- baseObject ,
70
- baseOffset + 4 ,
71
- arr ,
72
- PlatformDependent .BYTE_ARRAY_OFFSET ,
73
- recordLength );
74
- writer .write (arr , 0 , recordLength );
89
+ writeIntToBuffer (recordLength , 0 );
90
+ writeLongToBuffer (keyPrefix , 4 );
91
+ int dataRemaining = recordLength ;
92
+ int freeSpaceInWriteBuffer = DISK_WRITE_BUFFER_SIZE - 4 - 8 ;
93
+ long recordReadPosition = baseOffset + 4 ; // skip over record length
94
+ while (dataRemaining > 0 ) {
95
+ final int toTransfer = Math .min (freeSpaceInWriteBuffer , dataRemaining );
96
+ PlatformDependent .copyMemory (
97
+ baseObject ,
98
+ recordReadPosition ,
99
+ writeBuffer ,
100
+ PlatformDependent .BYTE_ARRAY_OFFSET + (DISK_WRITE_BUFFER_SIZE - freeSpaceInWriteBuffer ),
101
+ toTransfer );
102
+ writer .write (writeBuffer , 0 , (DISK_WRITE_BUFFER_SIZE - freeSpaceInWriteBuffer ) + toTransfer );
103
+ recordReadPosition += toTransfer ;
104
+ dataRemaining -= toTransfer ;
105
+ freeSpaceInWriteBuffer = DISK_WRITE_BUFFER_SIZE ;
106
+ }
75
107
writer .recordWritten ();
76
108
}
77
109
78
110
public void close () throws IOException {
79
- dos .writeInt (EOF_MARKER );
111
+ writeIntToBuffer (EOF_MARKER , 0 );
112
+ writer .write (writeBuffer , 0 , 4 );
80
113
writer .commitAndClose ();
81
114
writer = null ;
82
- dos = null ;
83
- arr = null ;
115
+ writeBuffer = null ;
84
116
}
85
117
86
118
public long numberOfSpilledBytes () {
0 commit comments