Apollo-ios: Increased compile times for generated code

Created on 13 Sep 2017  路  9Comments  路  Source: apollographql/apollo-ios

Since the new structure for query data structures with the backing dictionaries, we've experienced a huge increase in the lines of code generated for our API. Upgrading from Apollo iOS 0.5 to 0.6 we've gone from 9213 LOC to 55k lines of generated code, all of which now takes several seconds to compile.

This can be remedied by wrapping the generated code in another layer of frameworks, but it creates more hassle setting up. Are the plans to stick to this dictionary-backed approach in future releases?

codegen enhancement

All 9 comments

I'm not too happy with the backing dictionaries, but I'm not sure alternatives are any better. The reason for adding these was because I wanted to allow mutation of properties. And because the same result object can be represented by different structs (such as As<Type> or fragments), we needed a way to have the changed values be reflected in the whole chain. So if you set a value with hero.fragments.heroDetails.asDroid?.primaryFuntion = "Astromech", the change should also be reflected in hero.

Definitely interested in discussing this further and seeing how we can improve this.

One alternative would be to make the getters and setters smarter, so they actually convert individual properties, but that's also a lot of code and runtime overhead. An added benefit of the backing dictionaries might be that we avoid unnecessary retain/release of individual properties.

Thanks for explaining the rationale. I haven't looked into the generated code enough to see how/if it could be improved, but at least wanted to open an issue in case more people are seeing it as a problem.

One idea would be to offer a read-only flag into generate and not stamp out the set {}?

Mutable:

public var __typename: String {
    get {
        return snapshot["__typename"]! as! String
    }
    set {
        snapshot.updateValue(newValue, forKey: "__typename")
    }
}

Immutable:

public var __typename: String {
    return snapshot["__typename"]! as! String
}

@rjchatfield The point of the backing dictionaries is to provide consistent mutability across representations. Without mutability, we could go back to plain structs.

@martijnwalraven I'm wondering, is that consistency in mutability really worth it? From GraphQL's standpoint, you're getting the server state back, and use mutation requests to change it. Any local mutations to data isn't really in the realm of GraphQL? Another alternative could be to let fragments be protocols, that might solve the consistency issue, or have you perhaps explored that already?

@MrAlek: Local mutations are important if you want to be able to change results in the store manually, either to update dependent data or for optimistic updates. This hasn't really been documented yet, but you can use store.withinReadWriteTransaction to write/update fragments or queries. This is similar to the read/write API in Apollo Client JS.

I'd love for fragments to be protocols, but what is blocking that is a limitation of the Swift compiler which means implemented properties/methods have to be invariant. There is an unfinished open pull request for this on the Swift repository, but unfortunately I haven't been able to contribute to it.

@MrAlek we're now facing the same issue... compile times have sky rocketed. Could you elaborate on the idea on how to wrap this in a framework?

@attheodo If you wrap all the generated code in a framework which you add precompiled to your project, you'll only have to rebuild it when you change your queries or update your schema.

For example: you could create a framework called YourAPIKit, which in turn uses Apollo and then integrate that framework with your app project using Carthage. You get rid of the recompiling times but the drawback is that it's a bit more hassle to play around with queries.

I think there are some ways to set this up without being quite as much of a pain in the ass with SPM/Xcode 11. Going to look into it.

Awesome! Super glad you're onboard the project @designatednerd 馃憦 As for my end, I'm no longer using Apollo in case any follow-up questions arise but the original issue is probably still valid.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ashiemke picture ashiemke  路  5Comments

jeromeDms picture jeromeDms  路  5Comments

farice picture farice  路  4Comments

ermik picture ermik  路  4Comments

MrAlek picture MrAlek  路  3Comments