#free only part of an array

1 messages · Page 1 of 1 (latest)

wide iris
#

is there a way to free only the beginning of an array?

I am not that familiar with having to manually allocate memory, but I do know that allocations are slow.
So I found a way to do the calculation I am doing with only one allocation, but the problem is that the way I calculate how much space I need sometimes allocates a couple spaces too much so I end up with 0 to 2 extra spaces in the beginning of my list that are not needed and I cant just use a slice to remove them and return that

I need to something that is essentially this

const res = buf[extra..];
self.allocator.free(buf[0..extra]);
return res;

to free the unneeded bytes
I am unsure about the correct way to do this though

#

or should I not do this and just allocate a new array and memcopy the needed parts over?

obtuse plank
#

thats how fmt.allocPrint() works

wide iris
#

its for an encoding, I currently do one allocation with just more then enough or the exact needed amount of space then calculate through it backwards
I want the function to return the encoded data

eternal badge
#

You cannot free part of an allocated slice, you can either free it all or not at all.

obtuse plank
#

maybe write your encoding function to accept a writer: anytype and write to it. then you can use the fmt.count() strategy by passing an io.countingWriter(io.null_writer)

#

that would allow you to get the exact size you need from the counting_writer.bytes_written field

#

ofcourse that means you have to encode twice but this way you only have to allocate once.

#

does that make any sense?

wide iris
#

ya

obtuse plank
#

how does the signature of your encoding function look?

wide iris
#

rn its pub fn encode(self: Self, source: []const u8) baseTranslationError![]const u8 and self is a struct that stores an allocator it got in an init function

obtuse plank
#

sounds like it might work to accept a writer then if you want to go the double encoding route w/ countingWriter

#

io.Writer has lots of good methods for encoding

#

such as writeInt()

wide iris
#

I will look into it, thanks

obtuse plank
#

let me know if you have any questions. I may have been a little vague if you haven't done this before.

wide iris
#

its fine, im mostly just playing around trying to learn the language

obtuse plank
#

i definitely suggest learning how to use writers and readers in zig. they are very powerful and fundamental to the std lib

#

lots of things such as files, std.ArrayList(u8), io.fixedBufferStream() have reader() and writer() methods which return an io.Reader/Writer

#

heres a really simple example of how that might look

const std = @import("std");

fn encode(writer: anytype) !void {
    try writer.writeAll("MAGIC");
    const message = "hello world";
    try writer.writeInt(u32, message.len, .little);
    try writer.writeAll(message);
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const alloc = gpa.allocator();
    var cw = std.io.countingWriter(std.io.null_writer);
    try encode(cw.writer());
    const buf = try alloc.alloc(u8, cw.bytes_written);
    var fbs = std.io.fixedBufferStream(buf);
    try encode(fbs.writer());

    std.debug.print("{s}\n", .{buf});
}
wide iris
#

is there a way I can do benchmarks to test if its slower to do another allocation and a copy or to do another encoding?

#

not sure how benchmarking in zig works, apart from just getting the time before and after

obtuse plank
#

sure you can use std.time.Timer for benchmarking.

#

and std.fmt.fmtDuration() is an easy way to print out the ns to a readable format

#

or just time ./my_bench_exe isn't bad for a ballpark number

#

word or warning: heap.GeneralPurposeAllocator is quite slow. its not been well optimized yet and is mostly useful for reporting memory errors.

#

if you want to a a faster allocator, heap.c_allocator or an arena backed by heap.page_allocator are better

#

heres how you can use a zig timer

pub fn main() !void {
    var timer = try std.time.Timer.start();
    // ... code to benchmark
    std.debug.print("time: {}\n", .{std.fmt.fmtDuration(timer.lap())});
}
wide iris
#

thank you