-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
slow (or even hanging) dhall-kubernetes based generation #1960
Comments
Many thanks for the report, @uwedeportivo! :) Here's a diff of the two files: diff --git a/generate-plain.dhall b/generate-uwe.dhall
index 16c26f6..22ee9ff 100644
--- a/generate-plain.dhall
+++ b/generate-uwe.dhall
@@ -1,5 +1,34 @@
-let Generate = ./src/base/generate.dhall
+let Generate =
+ ./src/base/generate.dhall sha256:1438389a0f50298789f5deb1adee571accb5aefc552df89aa3ed68cf45180702
-let Configuration/global = ./src/configuration/global.dhall
+let Configuration/global =
+ ./src/configuration/global.dhall sha256:78ac8cb500fe1399ed094b01eff2bc6ed42ba93f1bde2ca4c3fc2958d18d7157
-in Generate Configuration/global::{=}
+let c =
+ Configuration/global::{=}
+ with GithubProxy.Deployment.Containers.GithubProxy.image = Some
+ "index.docker.io/sourcegraph/github-proxy:insiders@sha256:9bc0fab1ef7cddd6a09d45d47fe81314be60a7a42ca5b48b4fd3c33b45527dda"
+ with Prometheus.Deployment.Containers.Prometheus.resources.limits.memory = Some
+ "2G"
+ with Prometheus.Deployment.Containers.Prometheus.resources.requests.memory = Some
+ "500M"
+ with Prometheus.Deployment.Containers.Prometheus.image = Some
+ "index.docker.io/sourcegraph/prometheus:insiders@sha256:8906de7028ec7ecfcfecb63335dc47fe70dbf50d8741699eaaa17ea2ddfa857e"
+ with Prometheus.Deployment.Containers.Prometheus.resources.requests.ephemeralStorage = Some
+ "1Gi"
+ with Prometheus.Deployment.Containers.Prometheus.resources.limits.ephemeralStorage = Some
+ "1Gi"
+ with Gitserver.StatefulSet.persistentVolumeSize = Some "4Ti"
+ with Gitserver.StatefulSet.sshSecretName = Some "gitserver-ssh"
+ with Grafana.StatefulSet.Containers.Grafana.image = Some
+ "index.docker.io/sourcegraph/grafana:insiders@sha256:3a9f472109f9ab1ab992574e5e55b067a34537a38a0872db093cd877823ac42e"
+ with Grafana.StatefulSet.Containers.Grafana.resources.limits.memory = Some
+ "100Mi"
+ with Grafana.StatefulSet.Containers.Grafana.resources.requests.memory = Some
+ "100Mi"
+ with Grafana.StatefulSet.Containers.Grafana.resources.limits.ephemeralStorage = Some
+ "1Gi"
+ with Grafana.StatefulSet.Containers.Grafana.resources.requests.ephemeralStorage = Some
+ "1Gi"
+
+in Generate c It would be useful to reduce the differences between the files so it becomes clearer what the root of the performance issue is.
|
@sjakobi The execution time grows dramatically when we add more |
I've done some quick timings with
My current suspicion is that dhall-haskell/dhall/src/Dhall/Syntax.hs Lines 1173 to 1186 in 97ff185
|
i've pushed three files to that repo
with gradually more i also took out the sha256 (that was my bad, playing and misunderstanding freeze) |
i will try to test it tomorrow without the |
Yeah, I'm fairly certain that the extended use of This is one of the things that came up in the discussion for dhall-lang/dhall-lang#923 There is one change we could potentially make to the standard to make this sort of chained x with a.b.c = e = let _ = x in _ // { a = _.a // { b = _.a.b // { c = e } } } That would prevent the exponential blowup. |
An additional --- a/generate-uwe-50sec.dhall
+++ b/generate-uwe-50sec.dhall
@@ -2,8 +2,10 @@ let Generate = ./src/base/generate.dhall
let Configuration/global = ./src/configuration/global.dhall
-let c =
+let b =
Configuration/global::{=}
+
+let c = b
with GithubProxy.Deployment.Containers.GithubProxy.image = Some
"index.docker.io/sourcegraph/github-proxy:insiders@sha256:9bc0fab1ef7cddd6a09d45d47fe81314be60a7a42ca5b48b4fd3c33b45527dda"
with Prometheus.Deployment.Containers.Prometheus.resources.limits.memory = Some This shortens IIUC the reason for this speedup is that it avoids type-checking 8s is still pretty slow though. The |
@sjakobi: Right, this is why it requires language support. It needs to desugar to one |
Ah, good point! With one
Which is hardly slower than |
thanks for looking into this.
since i have your attention i would like some advice on how to set things up. let me briefly describe what we are doing and trying to accomplish: kubernetes customizationswe have a set of base manifests (https://github.com/sourcegraph/deploy-sourcegraph/tree/master/base) that define what a normal sourcegraph installation needs to run in a k8s cluster. our customers use these manifests to install sourcegraph on-prem in their own cluster. this naturally leads to customizations that the customers want to specify on top of this base (for things like replica count and specific resources like memory all the way to custom namespaces, storageclassnames, image registries etc., see https://github.com/sourcegraph/sourcegraph/issues/12000 for a more complete list). there are various ways one can support this and the kubernetes community has come up with various solutions from which we tried a couple over the years. we were not too happy with what we tried so far. they all have their drawbacks and customers struggle to keep up-to-date with our base changes while maintaining their customizations (RFC 141 is slightly outdated but gives you an idea: https://docs.google.com/document/d/1tsksAlqe77NmdPLw7oyy2u0-1rYDQeVpPeDo1T0Xt50/edit?usp=sharing). current stateour current state is: we encourage customers to keep base clean (no mods, so it's easy to merge upstream changes from our deploy-sourcegraph repo). as far as customizations we include some examples and machinery to let them define overlays using kustomize (https://kustomize.io/). we provide common overlays in the repo. you can get a picture of that from https://github.com/sourcegraph/deploy-sourcegraph/tree/master/overlays dhallwe are trying to be better than that and have been evaluating dhall for this (among other technologies). the repo https://github.com/sourcegraph/deploy-sourcegraph-dhall has our current approach with dhall. we are trying for now to get to a point where we can define customizations for one of our dogfood clusters and then use dhall to generate the manifests for it. here's a gist with some needed customizations for this dogfood cluster: https://gist.github.com/uwedeportivo/a4298942f75496a3de6ab24da65fc3aa (this is with the shell command variant and json jq, jy etc cmds mentioned in the RFC 141). our goal is to provide an ergonomic way for customers to specify these. they shouldn't need to know more than some minimal subset of dhall. the minimal syntax they would use will be obvious from example customizations. we see three ways to approach this:
each have their pluses and minuses. number one is complete but overwhelming and exposes too much configuration API that we might want to change later. this would break customers. it also might require too much dhall knowledge from our customers. number 2 suffers from lack of discoverability of the allowed paths into those records. it also feels repetitive especially with the my question: do you have any advice on how we should set it up. what's a nice dhall-ergonomic way to do something like this. thanks in advance :-) |
That sounds reasonable to me, at least once this perf issue is fixed. I'm not very familiar with using Dhall in practice though, so I my opinion on this is unlikely to be of much value. I think you might get more feedback on this if you'd pose your question at https://discourse.dhall-lang.org/ (and that might also help keep this issue about the perf problem). @Gabriel439: Improving the desugaring in this way seems like a good way forward to me. I wonder whether a standard change would be necessary or even helpful for this though. AFAIK the additional |
@sjakobi: The standard change is necessary because otherwise we'd fail this test: Also, although the standard does specify one way to normalize More importantly, even if we didn't mind the slight deviation from the standard (we've deviated in other small ways), I wouldn't want other implementations to have to rediscover this problem and independently reinvent the same solution. That would discourage them and also put them at a disadvantage to the Haskell implementation. |
That said, I plan to have a branch ready with the Haskell-side changes in parallel so that at least @uwedeportivo and @ggilmore will have something to try while waiting on the standardization change. |
@uwedeportivo: I would go with (2). If discoverability is the only issue, that can be fixed by language server support to auto-complete |
@uwedeportivo: I have a pull request up that you can use in the interim while I standardize this change: #1964 |
wow, thank you very much. will try it out |
@uwedeportivo: You're welcome! 🙂 |
The motivation for this change is: dhall-lang/dhall-haskell#1960 … where a deeply nested and chained `with` expression caused a blow-up in the size of the desugared syntax tree. This alternative desugaring was actually an idea we contemplated in the original change that standardized `with`: #923 … but at the time we elected to go with the simpler desugaring, reasoning that users could work around performance issues with explicit `let` binding: #923 (comment) However, for chained `with` expressions that work-around is not ergonomic, as illustrated in dhall-lang/dhall-haskell#1960. Instead, this adds language support for the `let` work-around. The change to the `WithMultiple` test demonstrates that this leads to a more compact desugared expression. Before this change the expression `{ a.b = 1, c.d = 2 } with a.b = 3 with c.e = 4` would desugar to: ```dhall { a.b = 1, c.d = 2 } ⫽ { a = { a.b = 1, c.d = 2 }.a ⫽ { b = 3 } } ⫽ { c = ({ a.b = 1, c.d = 2 } ⫽ { a = { a.b = 1, c.d = 2 }.a ⫽ { b = 3 } }).c ⫽ { e = 4 } } ``` … and now the same expression desugars to: ```dhall let _ = let _ = { a.b = 1, c.d = 2 } in _ ⫽ { a = _.a ⫽ { b = 3 } } in _ ⫽ { c = _.c ⫽ { e = 4 } } ```
@uwedeportivo let me know if LSP works for you. The last time I have tried it it was pretty bad (see #1817) |
Food for thought - our current approach to Kubernetes extensibility among dhall-unfamiliar users is as follows:
It takes a couple minutes for the generation process to finish, which is a little slow, but still workable for our current purposes. In exchange, we get: |
@Gabriel439, I wasn't aware of these recommendations for |
@ari-becker thanks for that. that is valuable input for us. and sorry everyone that i hijacked a little this issue to discuss something not quite relevant to it :-). |
@uwedeportivo @ggilmore @uwedeportivo @PierreR @ari-becker: I created a Discourse thread for the Kubernetes roadmap here: https://discourse.dhall-lang.org/t/roadmap-for-improved-kubernetes-support/313 |
@Gabriel439 i used your branch to build new binaries and ran it over the generate-uwe-40min.dhall and it is finishing in 1.7s and uses no more mem than plain. thank you very much. that fixes it. |
@uwedeportivo: You're welcome! Keep in mind it might be a week or two before that change gets merged into |
@sjakobi: When I wrote that, I was thinking of this part from the β-normalization section:
However, open reading that more closely it doesn't actually mention that it also applies to keywords like |
The motivation for this change is: dhall-lang/dhall-haskell#1960 This change to the standard gives implementations greater freedom in how they desugar a `with` expression, in order to permit more efficient implementations. The standard now also suggests a more efficient implementation to help implementation authors. This is technically a breaking change to the binary encoding of a non-normalized `with` expression, but semantic integrity checks are unaffected by this change.
The motivation for this change is: dhall-lang/dhall-haskell#1960 This change to the standard gives implementations greater freedom in how they desugar a `with` expression, in order to permit more efficient implementations. The standard now also suggests a more efficient implementation to help implementation authors. This is technically a breaking change to the binary encoding of a non-normalized `with` expression, but most semantic integrity checks are unaffected by this change. The exception are those where an imported expression contains a `with` expression with an abstract left-hand side (see the `WithDesugar` test for an example of code that would have a new integrity check after this change)
This was fixed by #1993 |
setup and steps to reproduce
https://github.com/sourcegraph/deploy-sourcegraph-dhall
at branchthe_rest_generate
dhall --file ./generate-uwe.dhall
in the root of the repodhall --file ./generate-plain.dhall
in the root of the repothe repo is in concept similar to a helm setup, where in generate-uwe.dhall you have defined customizations that should override records in src/base. generate-plain.dhall is the same only no overrides (empty customizations). each subdir in src/base corresponds to one service with deployment/statefulset and everything else it needs (volume claims, config maps, rbac roles etc). each such subdir defines a configuration.dhall which is used in a generate.dhall for generating the appropriate dhall-kubernetes record. those in turn get used for generating the actual yaml files when we want to deploy to k8s.
what to observe
by contrast generate-plain.dhall takes 1 sec to finish.
we would love feedback and advice on our setup and how we can address this problem. also how we can help debug this and help improve the performance.
The text was updated successfully, but these errors were encountered: