Git Product home page Git Product logo

Comments (13)

dlespiau avatar dlespiau commented on May 8, 2024 1

An interesting observation is the effect of disabling the GC, compiling kube-prometheus. Best of 3 runs:

$ time -J vendor -m manifests kube-prometheus.jsonnet
real	0m6.503s
user	0m8.852s
sys	0m0.352s

$ time GOGC=off jsonnet -J vendor -m manifests kube-prometheus.jsonnet
real	0m5.440s
user	0m4.488s
sys	0m0.952s

It's possible to play with SetGCPercent to tune the GC behaviour, jsonnet is a short lived program and very often doesn't need to garbage collect at all.

from go-jsonnet.

sbarzowski avatar sbarzowski commented on May 8, 2024 1

That's awesome!

  1. Actually I think it's best to keep the benchmarks completely implementation-agnostic, we shouldn't care if it's Go, Jsonnet or C++ - we want to compare the implementations. You can just create a Jsonnet file on which the performance improvement is visible here https://github.com/google/jsonnet/tree/master/benchmarks. Ideally we would have more benchmarks, including some realistic ones and a script which runs them all and prepares a nice looking report, allowing for easy comparison of performance across versions. But we don't have that yet, and frankly it's not critical, because there is still a lot of low hanging fruit performance-wise and the improvements tend to be obvious. So, don't worry too much about it, adding an example for which the improvement is clearly visible is enough for stuff like adding a builtin implementation of a stdlib function.
  2. All the builtins in the builtin table will override the ones defined in std.jsonnet. It's enough to define a new function implementing a builtin and add it to the table there. For reference the code which builds the std object and performs the overriding is here: https://github.com/google/go-jsonnet/blob/v0.14.0/interpreter.go#L1098.

If you have any questions or need help with anything, please let me know!

from go-jsonnet.

sbarzowski avatar sbarzowski commented on May 8, 2024

Perhaps a lot of time is stored resolving library functions. Every time a function value is called, the same values are computed, which do not depend on arguments. If there is std.something in a tight loop, every time std needs to get resolved (which by itself may mean a lot of map lookups), then something needs to be looked up in the object and then a function value needs to be created. Creating a local outside of the function for std.something can be used as a workaround.

It could be helped by keeping things like std.something as potentialValues inside function values, instead of always evaluating them from ast.

We would need to be careful not to store too much data, if we kept everything that doesn't depend on arguments, the memory usage could get out of hand pretty easily.

from go-jsonnet.

sbarzowski avatar sbarzowski commented on May 8, 2024

If we had resolved function values, we could go further and cache some call processing - the part which doesn't depend on actual argument values - checking if the number of arguments is correct, mapping positional/named arguments, etc. It could be a massive improvement for builtins.

from go-jsonnet.

redbaron avatar redbaron commented on May 8, 2024

if there is std.something in a tight loop, every time std needs to get resolved

is it same for $ objects?

from go-jsonnet.

sbarzowski avatar sbarzowski commented on May 8, 2024

Yep, $.something behaves similarly to std.something.

Note that by "resolved" I mean "looked up in the environment", just like any other variable.

from go-jsonnet.

sparkprime avatar sparkprime commented on May 8, 2024

It is a standard optimization to hoist invariant expressions out of functions, loops, etc.

from go-jsonnet.

sparkprime avatar sparkprime commented on May 8, 2024

I tried desugaring LiteralString to a special ast that embedded a pre-constructed stringValue object, to avoid having to create duplicate copies on the heap each time the string literal was executed. However this did not improve performance at all, in fact the profile indicated that makeStringValue was never being called, even though the code was full of string literals. I am not sure why.

from go-jsonnet.

sparkprime avatar sparkprime commented on May 8, 2024

This one generate unique numbers for variables statically and use that instead of names is going to give us the biggest bang for buck next I think.

I have a hunch that Go's maps are not as fast as the C++ std::map, which is responsible for some of the relative performance gap. We have to use maps for objects (in general) but there's no reason for environments.

from go-jsonnet.

abourget avatar abourget commented on May 8, 2024

I've been toying with this sonnet:

local k = import "k.libsonnet";

local deployment = k.apps.v1beta2.deployment;
local container = deployment.mixin.spec.template.spec.containersType;
local containerPort = container.portsType;

local myAppContainer = container.new("hello", "world");

local myAppDeployment = deployment.new("hello", 2, [myAppContainer], podLabels={"app": "myapp"});

k.core.v1.list.new(myAppDeployment)

It references these two files:

These are the results I get with 3 different implementations:

$ time jsonnet-cpp my.jsonnet
{...}
real	0m0.545s
user	0m0.477s
sys	0m0.047s
$ time jsonnet-go my.jsonnet
{...}
real	0m1.703s
user	0m2.082s
sys	0m0.193s
$ time ./sjsonnet.jar my.jsonnet 
{...}
real	0m1.833s
user	0m0.376s
sys	0m0.045s

and a second run of sjsonnet.jar, as it's calling into a background server (to avoid the JVM boot time):

$ time ./sjsonnet.jar my.jsonnet 
{...}
real	0m0.232s
user	0m0.327s
sys	0m0.029s

Seems the Scala version managed to get some interesting boost here.

My stack is in Go, so I'd love so much to have a speedy version here :)

As a side note, I'm interested in go-jsonnet as a real-time JSON stream reshaper.. disabling the garbage collecting in this situation isn't really practical.

from go-jsonnet.

sbarzowski avatar sbarzowski commented on May 8, 2024

It looks like in this case it's parsing performance that really matters in this case. I don't think garbage collection is a problem at all here.

EDIT:
I ran a quick experiment and just processing k8s.libsonnet takes pretty much the same amount of time as the provided example (the difference is well within random fluctuations).

from go-jsonnet.

ghostsquad avatar ghostsquad commented on May 8, 2024

I'd like to contribute to this effort. I had a couple questions though to help me get oriented.

  1. @sbarzowski requests that benchmarking is setup so that we can track performance changes over time. How would one write a benchmark test for a stdlib function that's written in jsonnet directly (instead of in Go)?
  2. How would someone "overwrite" a stdlib function that exists in the upstream stdlib jsonnet file (so that it runs native code instead of jsonnet interpreted)?

from go-jsonnet.

ghostsquad avatar ghostsquad commented on May 8, 2024

sjsonnet has some very good benchmarks because it caches values once they are evaluated as outlined here: https://github.com/databricks/sjsonnet#performance

Additionally, they moved all the native functions into Scala, which I think would also be very worthwhile. I started doing that to some of the more complex functions already.

from go-jsonnet.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.