Skip to content

Cache plugin configs - #3656

Open
peterebden wants to merge 5 commits into
thought-machine:masterfrom
peterebden:plugin-config-cache
Open

peterebden wants to merge 5 commits into
thought-machine:masterfrom
peterebden:plugin-config-cache

Conversation

@peterebden

Copy link
Copy Markdown
Collaborator

Turns out we spend a lot of time rebuilding config objects for every plugin / package combination, which really adds up time-wise. This implements caching for those config objects, which are usually identical.

On this machine, with a test repo generated from the perf tooling, this saves about 10% of wall clock time, 20% of user CPU and 27% of peak memory allocation, so it's pretty significant.

Comment thread src/parse/asp/builtins.go
case *pyRange:
return name == "range"
case pyList:
case pyList, pyFrozenList:

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not strictly related but a bit of a drive-by while I was here; isinstance should treat a frozen list as being a list

Comment thread src/parse/asp/objects.go
panic("unknown dict key: " + s.String())
case Union:
d2, ok := operand.(pyDict)
d2, ok := asDict(operand)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another drive-by about using a union operator of a dict and a frozen dict

Comment thread src/please.go
}
defer f.Close()
defer pprof.WriteHeapProfile(f)
defer runtime.GC()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here; we only get up-to-date stats for the heap profile once a GC cycle has completed, without this that might have been ages ago

Comment thread src/parse/asp/builtins.go
case pyList, pyFrozenList:
return name == "list"
case pyDict:
case pyDict, pyFrozenDict:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran a quick check against my repo and noticed differences in output, I suspect a change in behaviour; top-level variables in a sub included .build_defs file are frozen once it has loaded, so isinstance(x, dict) and isinstance(x, list) now return True where they used to return False.

This changed output (ran a plz query print comparison with plz-before and plz-after), it's probably worth noting the slight change in behaviour (which probably makes more sense).

08:47:24.702 WARNING: BUILD: describe()=plain value, isinstance(_DEFAULT_TAGS, list)=False
vs
08:47:32.650 WARNING: BUILD: describe()=per-env dict, isinstance(_DEFAULT_TAGS, list)=True

on

$ cat /tmp/isinstance-test0/defs/defs.build_defs 
_UNSET = {"unset": True}  # sentinel default
_DEFAULT_TAGS = ["base"]

def describe(setting = _UNSET):
    if isinstance(setting, dict):
        return "per-env dict"
    return "plain value"

def tags_is_list():
    return isinstance(_DEFAULT_TAGS, list)

would it make sense to check val != _UNSET before the isinstance call?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes exactly; there are some fixes in #3657 which I'll land in the same release as this and I've landed a fix internally to deal with that _UNSET thing so we should be fine before and after the upgrade.

Thanks for looking into it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants