Chkstk_darwin woes

I have a DSL library that I'm writing that looks something like this in use:

//  Client

struct MyDataFilter: Filter {

    @FilterBodyBuilder func body() -> some FilterBody {
        filter("dogs") {
            filter("pomeranians") {
                group("age") {
                    //  ...
                }
            }
        }
    }

}

Each filter() method returns a FilterNode<T> type that statically encodes what the filter tree looks like, which helps me know some things about the tree ahead of time. The closure that filter() accepts never escape the stack, and are always run immediately (or skipped.). Basically:

//  Library

//  Empty type, literally only used to encode static type information.

public struct FilterNode<T> {

    static func inspect() -> Inspection { }

}

extension Filter {

    public func filter<T: FilterBody>(_ filter: String, @FilterBodyBuilder body: () -> T) -> FilterNode<T> {
        withCurrentData {
            data

            if data.matches(filter) {
                body()
            }
        }

        return .init()
    }

}

My real code involves quite a bit more logic than this, but in essence, that body closure gets passed down a call chain of other with-style functions that decide if it gets executed or not.

Depending on the size of the data, the Filter.body method gets called a lot. Potentially millions of times. When profiling, I notice a fun little friend eating up much of the run time, even with very shallow (one-level Filter.body-ies): ___chkstk_darwin.

In my case — thanks to a suggestion from ChatGPT — I notice that sprinkling @inline(never) down the call stack reduces the time spent in ___chkstk_darwin, but doesn't eliminate it. Shortening filter to just immediately call the closure it's handed does eliminate it, but obviously that's not realistic.

Hopefully someone knowledgeable here can shed light on:

  • Exactly what ___chkstk_darwin is meant to do in this case,
  • Why Swift is choosing to emit it here — what are the thresholds?, and
  • How I can reduce (or eliminate) the amount of time my code is spending it
1 Like

Check this thread.

1 Like

Thanks. What's suggested in one of the replies there (adding -no-stack-check) works, but admittedly disabling stack checks entirely sounds... risky, so I'd also love to know exactly what is triggering this and if I can structure my logic a different way to avoid it.

1 Like