(x = something, y = something_else) for constructing NamedTuples has been around since 1.0. The novelties since then were (; x, y) for constructing a NamedTuple from variables in scope (instead of having to write (x=x, y=y)) in 1.5, and then applying that to destructuring, i.e. (; x, y) = something where something is an object that has fieldnames x and y in Julia 1.7.

julia> abc = (a=1, b="hello", c = 3.14)
(a = 1, b = "hello", c = 3.14)
julia> ac = NamedTuple{(:a, :c)}(abc)
(a = 1, c = 3.14)

"""
keepkeys(nt::NamedTuple, syms::Tuple{Vararg{Symbol}})
Construct a subset of `nt` using only the keys in `syms`.
""" keepkeys
julia> keepkeys(nt::NamedTuple, ks=NTuple{N,Symbol} where {N}) =
NamedTuple{ks}(nt)
julia> b = keepkeys(abc, (:b,))
(b = "hello",)
julia> bc = keepkeys(abc, (:b, :c))
(b = "hello", c = 3.14)
julia> keepkeys(abc, (:z,))
ERROR: type NamedTuple has no field z

"""
omitkeys(nt::NamedTuple, syms::Tuple{Vararg{Symbol}})
Construct a subset of `nt` omitting the keys in `syms`.
""" omitkeys
julia> omitkeys(nt::NamedTuple, ks=NTuple{N,Symbol} where {N}) =
keepkeys(nt, Tuple(setdiff(keys(nt), ks)))
julia> bc = omitkeys(abc, (:a,))
(b = "hello", c = 3.14)
julia> b = omitkeys(abc, (:a, :c))
(b = "hello",)
julia> abc2 = omitkeys(abc, (:z,))
(a = 1, b = "hello", c = 3.14)

There should be no difference, or at most a negligible difference.

Recall that to compute times, either use @time and execute the function at least twice (the first run is always polluted by compilation time). But to do serious benchmarks, use the package BenchmarkTools and @btime. This computes multiple times the calculation to provide a more accurate benchmark.

That doesn’t sound right. You might mean that Iterators.reverse knows how to reverse eachline iterators in recent Julia versions. reverse from Base has never known how to do that.