authorgravatar for joad.nacer@gmail.comjoadnacer <joad.nacer@gmail.com> 2023-10-15 23:14:46+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-16 08:49:05-04:00
log7b9165b37576ed4c4962c0ad2afb62921524aa08
tree745976a8ed73184fcd587df96eec4ae12553075f
parent14efbf5ed1731058a616582d81223e23f43af128

std.mem: Improve writeIntSlice performance


1 files changed, 31 insertions(+), 22 deletions(-)

lib/std/mem.zig+31-22
...@@ -1911,7 +1911,7 @@ pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T...@@ -1911,7 +1911,7 @@ pub fn writePackedInt(comptime T: type, bytes: []u8, bit_offset: usize, value: T
1911/// Any extra bytes in buffer after writing the integer are set to zero. To1911/// Any extra bytes in buffer after writing the integer are set to zero. To
1912/// avoid the branch to check for extra buffer bytes, use writeIntLittle1912/// avoid the branch to check for extra buffer bytes, use writeIntLittle
1913/// instead.1913/// instead.
1914pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {1914fn writeIntSliceLittleNative(comptime T: type, buffer: []u8, value: T) void {
1915 assert(buffer.len >= @divExact(@typeInfo(T).Int.bits, 8));1915 assert(buffer.len >= @divExact(@typeInfo(T).Int.bits, 8));
19161916
1917 if (@typeInfo(T).Int.bits == 0) {1917 if (@typeInfo(T).Int.bits == 0) {
...@@ -1921,21 +1921,27 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {...@@ -1921,21 +1921,27 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
1921 buffer[0] = @as(u8, @bitCast(value));1921 buffer[0] = @as(u8, @bitCast(value));
1922 return;1922 return;
1923 }1923 }
1924 // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough1924
1925 const uint = std.meta.Int(.unsigned, @typeInfo(T).Int.bits);1925 const write_end = @divExact(@typeInfo(T).Int.bits, 8);
1926 var bits = @as(uint, @bitCast(value));1926 @as(*align(1) T, @ptrCast(buffer)).* = value;
1927 for (buffer) |*b| {1927 @memset(buffer[write_end..], 0);
1928 b.* = @as(u8, @truncate(bits));1928}
1929 bits >>= 8;1929
1930 }1930fn writeIntSliceLittleForeign(comptime T: type, buffer: []u8, value: T) void {
1931 return writeIntSliceLittleNative(T, buffer, @byteSwap(value));
1931}1932}
19321933
1934pub const writeIntSliceLittle = switch (native_endian) {
1935 .Little => writeIntSliceLittleNative,
1936 .Big => writeIntSliceLittleForeign,
1937};
1938
1933/// Writes a twos-complement big-endian integer to memory.1939/// Writes a twos-complement big-endian integer to memory.
1934/// Asserts that buffer.len >= @typeInfo(T).Int.bits / 8.1940/// Asserts that buffer.len >= @typeInfo(T).Int.bits / 8.
1935/// The bit count of T must be divisible by 8.1941/// The bit count of T must be divisible by 8.
1936/// Any extra bytes in buffer before writing the integer are set to zero. To1942/// Any extra bytes in buffer before writing the integer are set to zero. To
1937/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.1943/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
1938pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {1944fn writeIntSliceBigNative(comptime T: type, buffer: []u8, value: T) void {
1939 assert(buffer.len >= @divExact(@typeInfo(T).Int.bits, 8));1945 assert(buffer.len >= @divExact(@typeInfo(T).Int.bits, 8));
19401946
1941 if (@typeInfo(T).Int.bits == 0) {1947 if (@typeInfo(T).Int.bits == 0) {
...@@ -1946,25 +1952,28 @@ pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {...@@ -1946,25 +1952,28 @@ pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
1946 return;1952 return;
1947 }1953 }
19481954
1949 // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough1955 const write_start = buffer.len - @divExact(@typeInfo(T).Int.bits, 8);
1950 const uint = std.meta.Int(.unsigned, @typeInfo(T).Int.bits);1956 @memset(buffer[0..write_start], 0);
1951 var bits = @as(uint, @bitCast(value));1957 @as(*align(1) T, @ptrCast(buffer[write_start..])).* = value;
1952 var index: usize = buffer.len;1958}
1953 while (index != 0) {1959
1954 index -= 1;1960fn writeIntSliceBigForeign(comptime T: type, buffer: []u8, value: T) void {
1955 buffer[index] = @as(u8, @truncate(bits));1961 return writeIntSliceBigNative(T, buffer, @byteSwap(value));
1956 bits >>= 8;
1957 }
1958}1962}
19591963
1964pub const writeIntSliceBig = switch (native_endian) {
1965 .Little => writeIntSliceBigForeign,
1966 .Big => writeIntSliceBigNative,
1967};
1968
1960pub const writeIntSliceNative = switch (native_endian) {1969pub const writeIntSliceNative = switch (native_endian) {
1961 .Little => writeIntSliceLittle,1970 .Little => writeIntSliceLittleNative,
1962 .Big => writeIntSliceBig,1971 .Big => writeIntSliceBigNative,
1963};1972};
19641973
1965pub const writeIntSliceForeign = switch (native_endian) {1974pub const writeIntSliceForeign = switch (native_endian) {
1966 .Little => writeIntSliceBig,1975 .Little => writeIntSliceBigForeign,
1967 .Big => writeIntSliceLittle,1976 .Big => writeIntSliceLittleForeign,
1968};1977};
19691978
1970/// Writes a twos-complement integer to memory, with the specified endianness.1979/// Writes a twos-complement integer to memory, with the specified endianness.