#Dynamic CallModifier for increased performance

1 messages · Page 1 of 1 (latest)

frosty sage
#

Hi,

Im currently working on a hobby project of implementing functional programming methods like map, filter, reduce e.t.c and one question I have is regard CallModifier. If we look at my current implementation for mapping over a slice

/// Map over slice of type `T` to new allocated slice using function `func` on each element of `slice`.
/// Additionally supply some arguments to `func`.
/// Consumer of function must make sure to free returned slice.
pub fn mapSlice(allocator: Allocator, comptime T: type, slice: []const T, comptime func: anytype, args: anytype) ![]@typeInfo(@TypeOf(func)).Fn.return_type.? {
    if (@typeInfo(@TypeOf(func)).Fn.params[0].type.? != T) {
        return FunctoolTypeError.InvalidParamType;
    }

    const ReturnType = @typeInfo(@TypeOf(func)).Fn.return_type orelse {
        return FunctoolTypeError.InvalidReturnType;
    };

    var mapped_slice = try allocator.alloc(ReturnType, slice.len);
    for (0..slice.len) |idx| {
        mapped_slice[idx] = @call(.always_inline, func, .{slice[idx]} ++ args);
    }

    return mapped_slice;
}

We can see that I pass .always_inline as my CallModifier to @call. Obviously you can't always inline every function and the documentation says as much, but I was wondering if there is any way to make it resort to .auto if inlining isn't possible. The reason I want to try .always_inline first is because it usually results in better performance than a "manual" implementation of whatever mapping you are doing when working on slices, at least according to my benchmarks.

tiny perch
#

Inlining in zig is a semantic inline (i.e. treating the function like a C macro) rather than an optimization hint. Given there's a single dispatch point, you could try just calling it normally and relying on the optimizer to inline it if it doesnt break register pressure elsewhere (mapSlice could probably be inlined by the optimizer too)

frosty sage
#

Another reason I am using @call instead of just calling the function normally is so I can easily spread the arguments using the ++ operator. Is there any way to achieve the same thing when calling the function normally, i.e spreading the args?

kind canopy
frosty sage
kind canopy
frosty sage
#

Debug, I'm gonna try release safe now

#

Oh, it seems like .auto does indeed end up inlining anyway when building in release safe so there is really no point in specifying .always_inline