TUN-4356: Set AUTOMAXPROCS to the CPU limit when running in a Linux container
This commit is contained in:
		
							parent
							
								
									209091da39
								
							
						
					
					
						commit
						07af2a33b7
					
				| 
						 | 
				
			
			@ -10,6 +10,7 @@ import (
 | 
			
		|||
	homedir "github.com/mitchellh/go-homedir"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"github.com/urfave/cli/v2"
 | 
			
		||||
	_ "go.uber.org/automaxprocs"
 | 
			
		||||
 | 
			
		||||
	"github.com/cloudflare/cloudflared/cmd/cloudflared/access"
 | 
			
		||||
	"github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										1
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -43,6 +43,7 @@ require (
 | 
			
		|||
	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 | 
			
		||||
	github.com/stretchr/testify v1.6.0
 | 
			
		||||
	github.com/urfave/cli/v2 v2.2.0
 | 
			
		||||
	go.uber.org/automaxprocs v1.4.0
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
 | 
			
		||||
	golang.org/x/net v0.0.0-20200904194848-62affa334b73
 | 
			
		||||
	golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										2
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -609,6 +609,8 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 | 
			
		|||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 | 
			
		||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 | 
			
		||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 | 
			
		||||
go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0=
 | 
			
		||||
go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
 | 
			
		||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 | 
			
		||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
 | 
			
		||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
coverage:
 | 
			
		||||
  range: 80..100
 | 
			
		||||
  round: down
 | 
			
		||||
  precision: 2
 | 
			
		||||
 | 
			
		||||
  status:
 | 
			
		||||
    project:                   # measuring the overall project coverage
 | 
			
		||||
      default:                 # context, you can create multiple ones with custom titles
 | 
			
		||||
        enabled: yes           # must be yes|true to enable this status
 | 
			
		||||
        target: 90%            # specify the target coverage for each commit status
 | 
			
		||||
                               #   option: "auto" (must increase from parent commit or pull request base)
 | 
			
		||||
                               #   option: "X%" a static target percentage to hit
 | 
			
		||||
        if_not_found: success  # if parent is not found report status as success, error, or failure
 | 
			
		||||
        if_ci_failed: error    # if ci fails report status as success, error, or failure
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
 | 
			
		||||
*.o
 | 
			
		||||
*.a
 | 
			
		||||
*.so
 | 
			
		||||
 | 
			
		||||
# Folders
 | 
			
		||||
_obj
 | 
			
		||||
_test
 | 
			
		||||
vendor
 | 
			
		||||
 | 
			
		||||
# Architecture specific extensions/prefixes
 | 
			
		||||
*.[568vq]
 | 
			
		||||
[568vq].out
 | 
			
		||||
 | 
			
		||||
*.cgo1.go
 | 
			
		||||
*.cgo2.c
 | 
			
		||||
_cgo_defun.c
 | 
			
		||||
_cgo_gotypes.go
 | 
			
		||||
_cgo_export.*
 | 
			
		||||
 | 
			
		||||
_testmain.go
 | 
			
		||||
 | 
			
		||||
*.exe
 | 
			
		||||
*.test
 | 
			
		||||
*.prof
 | 
			
		||||
*.pprof
 | 
			
		||||
*.out
 | 
			
		||||
*.log
 | 
			
		||||
coverage.txt
 | 
			
		||||
 | 
			
		||||
/bin
 | 
			
		||||
cover.out
 | 
			
		||||
cover.html
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
language: go
 | 
			
		||||
sudo: false
 | 
			
		||||
go_import_path: go.uber.org/automaxprocs
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  global:
 | 
			
		||||
    - GO111MODULE=on
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
  include:
 | 
			
		||||
    - go: oldstable
 | 
			
		||||
    - go: stable
 | 
			
		||||
      env: LINT=1
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - make install
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - test -z "$LINT" || make lint
 | 
			
		||||
  - make test
 | 
			
		||||
 | 
			
		||||
after_success:
 | 
			
		||||
  - make cover
 | 
			
		||||
  - bash <(curl -s https://codecov.io/bash)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
# Changelog
 | 
			
		||||
 | 
			
		||||
## v1.4.0 (2021-02-01)
 | 
			
		||||
 | 
			
		||||
- Support colons in cgroup names.
 | 
			
		||||
- Remove linters from runtime dependencies.
 | 
			
		||||
 | 
			
		||||
## v1.3.0 (2020-01-23)
 | 
			
		||||
 | 
			
		||||
- Migrate to Go modules.
 | 
			
		||||
 | 
			
		||||
## v1.2.0 (2018-02-22)
 | 
			
		||||
 | 
			
		||||
- Fixed quota clamping to always round down rather than up; Rather than
 | 
			
		||||
  guaranteeing constant throttling at saturation, instead assume that the
 | 
			
		||||
  fractional CPU was added as a hedge for factors outside of Go's scheduler.
 | 
			
		||||
 | 
			
		||||
## v1.1.0 (2017-11-10)
 | 
			
		||||
 | 
			
		||||
- Log the new value of `GOMAXPROCS` rather than the current value.
 | 
			
		||||
- Make logs more explicit about whether `GOMAXPROCS` was modified or not.
 | 
			
		||||
- Allow customization of the minimum `GOMAXPROCS`, and modify default from 2 to 1.
 | 
			
		||||
 | 
			
		||||
## v1.0.0 (2017-08-09)
 | 
			
		||||
 | 
			
		||||
- Initial release.
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
# Contributor Covenant Code of Conduct
 | 
			
		||||
 | 
			
		||||
## Our Pledge
 | 
			
		||||
 | 
			
		||||
In the interest of fostering an open and welcoming environment, we as
 | 
			
		||||
contributors and maintainers pledge to making participation in our project and
 | 
			
		||||
our community a harassment-free experience for everyone, regardless of age,
 | 
			
		||||
body size, disability, ethnicity, gender identity and expression, level of
 | 
			
		||||
experience, nationality, personal appearance, race, religion, or sexual
 | 
			
		||||
identity and orientation.
 | 
			
		||||
 | 
			
		||||
## Our Standards
 | 
			
		||||
 | 
			
		||||
Examples of behavior that contributes to creating a positive environment
 | 
			
		||||
include:
 | 
			
		||||
 | 
			
		||||
* Using welcoming and inclusive language
 | 
			
		||||
* Being respectful of differing viewpoints and experiences
 | 
			
		||||
* Gracefully accepting constructive criticism
 | 
			
		||||
* Focusing on what is best for the community
 | 
			
		||||
* Showing empathy towards other community members
 | 
			
		||||
 | 
			
		||||
Examples of unacceptable behavior by participants include:
 | 
			
		||||
 | 
			
		||||
* The use of sexualized language or imagery and unwelcome sexual attention or
 | 
			
		||||
  advances
 | 
			
		||||
* Trolling, insulting/derogatory comments, and personal or political attacks
 | 
			
		||||
* Public or private harassment
 | 
			
		||||
* Publishing others' private information, such as a physical or electronic
 | 
			
		||||
  address, without explicit permission
 | 
			
		||||
* Other conduct which could reasonably be considered inappropriate in a
 | 
			
		||||
  professional setting
 | 
			
		||||
 | 
			
		||||
## Our Responsibilities
 | 
			
		||||
 | 
			
		||||
Project maintainers are responsible for clarifying the standards of acceptable
 | 
			
		||||
behavior and are expected to take appropriate and fair corrective action in
 | 
			
		||||
response to any instances of unacceptable behavior.
 | 
			
		||||
 | 
			
		||||
Project maintainers have the right and responsibility to remove, edit, or
 | 
			
		||||
reject comments, commits, code, wiki edits, issues, and other contributions
 | 
			
		||||
that are not aligned to this Code of Conduct, or to ban temporarily or
 | 
			
		||||
permanently any contributor for other behaviors that they deem inappropriate,
 | 
			
		||||
threatening, offensive, or harmful.
 | 
			
		||||
 | 
			
		||||
## Scope
 | 
			
		||||
 | 
			
		||||
This Code of Conduct applies both within project spaces and in public spaces
 | 
			
		||||
when an individual is representing the project or its community. Examples of
 | 
			
		||||
representing a project or community include using an official project e-mail
 | 
			
		||||
address, posting via an official social media account, or acting as an
 | 
			
		||||
appointed representative at an online or offline event. Representation of a
 | 
			
		||||
project may be further defined and clarified by project maintainers.
 | 
			
		||||
 | 
			
		||||
## Enforcement
 | 
			
		||||
 | 
			
		||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
 | 
			
		||||
reported by contacting the project team at oss-conduct@uber.com. The project
 | 
			
		||||
team will review and investigate all complaints, and will respond in a way
 | 
			
		||||
that it deems appropriate to the circumstances. The project team is obligated
 | 
			
		||||
to maintain confidentiality with regard to the reporter of an incident.
 | 
			
		||||
Further details of specific enforcement policies may be posted separately.
 | 
			
		||||
 | 
			
		||||
Project maintainers who do not follow or enforce the Code of Conduct in good
 | 
			
		||||
faith may face temporary or permanent repercussions as determined by other
 | 
			
		||||
members of the project's leadership.
 | 
			
		||||
 | 
			
		||||
## Attribution
 | 
			
		||||
 | 
			
		||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
 | 
			
		||||
version 1.4, available at
 | 
			
		||||
[http://contributor-covenant.org/version/1/4][version].
 | 
			
		||||
 | 
			
		||||
[homepage]: http://contributor-covenant.org
 | 
			
		||||
[version]: http://contributor-covenant.org/version/1/4/
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
# Contributing
 | 
			
		||||
 | 
			
		||||
We'd love your help improving this package!
 | 
			
		||||
 | 
			
		||||
If you'd like to add new exported APIs, please [open an issue][open-issue]
 | 
			
		||||
describing your proposal — discussing API changes ahead of time makes
 | 
			
		||||
pull request review much smoother. In your issue, pull request, and any other
 | 
			
		||||
communications, please remember to treat your fellow contributors with
 | 
			
		||||
respect! We take our [code of conduct](CODE_OF_CONDUCT.md) seriously.
 | 
			
		||||
 | 
			
		||||
Note that you'll need to sign [Uber's Contributor License Agreement][cla]
 | 
			
		||||
before we can accept any of your contributions. If necessary, a bot will remind
 | 
			
		||||
you to accept the CLA when you open your pull request.
 | 
			
		||||
 | 
			
		||||
## Setup
 | 
			
		||||
 | 
			
		||||
[Fork][fork], then clone the repository:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
mkdir -p $GOPATH/src/go.uber.org
 | 
			
		||||
cd $GOPATH/src/go.uber.org
 | 
			
		||||
git clone git@github.com:your_github_username/automaxprocs.git
 | 
			
		||||
cd automaxprocs
 | 
			
		||||
git remote add upstream https://github.com/uber-go/automaxprocs.git
 | 
			
		||||
git fetch upstream
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Install the test dependencies:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
make dependencies
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Make sure that the tests and the linters pass:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
make test
 | 
			
		||||
make lint
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If you're not using the minor version of Go specified in the Makefile's
 | 
			
		||||
`LINTABLE_MINOR_VERSIONS` variable, `make lint` doesn't do anything. This is
 | 
			
		||||
fine, but it means that you'll only discover lint failures after you open your
 | 
			
		||||
pull request.
 | 
			
		||||
 | 
			
		||||
## Making Changes
 | 
			
		||||
 | 
			
		||||
Start by creating a new branch for your changes:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
cd $GOPATH/src/go.uber.org/automaxprocs
 | 
			
		||||
git checkout master
 | 
			
		||||
git fetch upstream
 | 
			
		||||
git rebase upstream/master
 | 
			
		||||
git checkout -b cool_new_feature
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Make your changes, then ensure that `make lint` and `make test` still pass. If
 | 
			
		||||
you're satisfied with your changes, push them to your fork.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git push origin cool_new_feature
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then use the GitHub UI to open a pull request.
 | 
			
		||||
 | 
			
		||||
At this point, you're waiting on us to review your changes. We *try* to respond
 | 
			
		||||
to issues and pull requests within a few business days, and we may suggest some
 | 
			
		||||
improvements or alternatives. Once your changes are approved, one of the
 | 
			
		||||
project maintainers will merge them.
 | 
			
		||||
 | 
			
		||||
We're much more likely to approve your changes if you:
 | 
			
		||||
 | 
			
		||||
* Add tests for new functionality.
 | 
			
		||||
* Write a [good commit message][commit-message].
 | 
			
		||||
* Maintain backward compatibility.
 | 
			
		||||
 | 
			
		||||
[fork]: https://github.com/uber-go/automaxprocs/fork
 | 
			
		||||
[open-issue]: https://github.com/uber-go/automaxprocs/issues/new
 | 
			
		||||
[cla]: https://cla-assistant.io/uber-go/automaxprocs
 | 
			
		||||
[commit-message]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
export GOBIN ?= $(shell pwd)/bin
 | 
			
		||||
 | 
			
		||||
GO_FILES := $(shell \
 | 
			
		||||
	find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
 | 
			
		||||
	-o -name '*.go' -print | cut -b3-)
 | 
			
		||||
 | 
			
		||||
GOLINT = $(GOBIN)/golint
 | 
			
		||||
STATICCHECK = $(GOBIN)/staticcheck
 | 
			
		||||
 | 
			
		||||
.PHONY: build
 | 
			
		||||
build:
 | 
			
		||||
	go build ./...
 | 
			
		||||
 | 
			
		||||
.PHONY: install
 | 
			
		||||
install:
 | 
			
		||||
	go mod download
 | 
			
		||||
 | 
			
		||||
.PHONY: test
 | 
			
		||||
test:
 | 
			
		||||
	go test -race ./...
 | 
			
		||||
 | 
			
		||||
.PHONY: cover
 | 
			
		||||
cover:
 | 
			
		||||
	go test -coverprofile=cover.out -covermode=atomic -coverpkg=./... ./...
 | 
			
		||||
	go tool cover -html=cover.out -o cover.html
 | 
			
		||||
 | 
			
		||||
$(GOLINT): tools/go.mod
 | 
			
		||||
	cd tools && go install golang.org/x/lint/golint
 | 
			
		||||
 | 
			
		||||
$(STATICCHECK): tools/go.mod
 | 
			
		||||
	cd tools && go install honnef.co/go/tools/cmd/staticcheck
 | 
			
		||||
 | 
			
		||||
.PHONY: lint
 | 
			
		||||
lint: $(GOLINT) $(STATICCHECK)
 | 
			
		||||
	@rm -rf lint.log
 | 
			
		||||
	@echo "Checking gofmt"
 | 
			
		||||
	@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
 | 
			
		||||
	@echo "Checking go vet"
 | 
			
		||||
	@go vet ./... 2>&1 | tee -a lint.log
 | 
			
		||||
	@echo "Checking golint"
 | 
			
		||||
	@$(GOLINT) ./... | tee -a lint.log
 | 
			
		||||
	@echo "Checking staticcheck"
 | 
			
		||||
	@$(STATICCHECK) ./... 2>&1 |  tee -a lint.log
 | 
			
		||||
	@echo "Checking for license headers..."
 | 
			
		||||
	@./.build/check_license.sh | tee -a lint.log
 | 
			
		||||
	@[ ! -s lint.log ]
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
# automaxprocs [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
 | 
			
		||||
 | 
			
		||||
Automatically set `GOMAXPROCS` to match Linux container CPU quota.
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
`go get -u go.uber.org/automaxprocs`
 | 
			
		||||
 | 
			
		||||
## Quick Start
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import _ "go.uber.org/automaxprocs"
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
  // Your application logic here.
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Development Status: Stable
 | 
			
		||||
 | 
			
		||||
All APIs are finalized, and no breaking changes will be made in the 1.x series
 | 
			
		||||
of releases. Users of semver-aware dependency management systems should pin
 | 
			
		||||
automaxprocs to `^1`.
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
We encourage and support an active, healthy community of contributors —
 | 
			
		||||
including you! Details are in the [contribution guide](CONTRIBUTING.md) and
 | 
			
		||||
the [code of conduct](CODE_OF_CONDUCT.md). The automaxprocs maintainers keep
 | 
			
		||||
an eye on issues and pull requests, but you can also report any negative
 | 
			
		||||
conduct to oss-conduct@uber.com. That email list is a private, safe space;
 | 
			
		||||
even the automaxprocs maintainers don't have access, so don't hesitate to hold
 | 
			
		||||
us to a high standard.
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
Released under the [MIT License](LICENSE).
 | 
			
		||||
 | 
			
		||||
[doc-img]: https://godoc.org/go.uber.org/automaxprocs?status.svg
 | 
			
		||||
[doc]: https://godoc.org/go.uber.org/automaxprocs
 | 
			
		||||
[ci-img]: https://travis-ci.com/uber-go/automaxprocs.svg?branch=master
 | 
			
		||||
[ci]: https://travis-ci.com/uber-go/automaxprocs
 | 
			
		||||
[cov-img]: https://codecov.io/gh/uber-go/automaxprocs/branch/master/graph/badge.svg
 | 
			
		||||
[cov]: https://codecov.io/gh/uber-go/automaxprocs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// Package automaxprocs automatically sets GOMAXPROCS to match the Linux
 | 
			
		||||
// container CPU quota, if any.
 | 
			
		||||
package automaxprocs // import "go.uber.org/automaxprocs"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	"go.uber.org/automaxprocs/maxprocs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	maxprocs.Set(maxprocs.Logger(log.Printf))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
package: go.uber.org/automaxprocs
 | 
			
		||||
import: []
 | 
			
		||||
testImport:
 | 
			
		||||
- package: github.com/stretchr/testify
 | 
			
		||||
  version: ^1.1.4
 | 
			
		||||
  subpackages:
 | 
			
		||||
  - assert
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
module go.uber.org/automaxprocs
 | 
			
		||||
 | 
			
		||||
go 1.13
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/kr/pretty v0.1.0 // indirect
 | 
			
		||||
	github.com/stretchr/testify v1.4.0
 | 
			
		||||
	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 | 
			
		||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 | 
			
		||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
			
		||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 | 
			
		||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 | 
			
		||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
package cgroups
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CGroup represents the data structure for a Linux control group.
 | 
			
		||||
type CGroup struct {
 | 
			
		||||
	path string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCGroup returns a new *CGroup from a given path.
 | 
			
		||||
func NewCGroup(path string) *CGroup {
 | 
			
		||||
	return &CGroup{path: path}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Path returns the path of the CGroup*.
 | 
			
		||||
func (cg *CGroup) Path() string {
 | 
			
		||||
	return cg.path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParamPath returns the path of the given cgroup param under itself.
 | 
			
		||||
func (cg *CGroup) ParamPath(param string) string {
 | 
			
		||||
	return filepath.Join(cg.path, param)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readFirstLine reads the first line from a cgroup param file.
 | 
			
		||||
func (cg *CGroup) readFirstLine(param string) (string, error) {
 | 
			
		||||
	paramFile, err := os.Open(cg.ParamPath(param))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	defer paramFile.Close()
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(paramFile)
 | 
			
		||||
	if scanner.Scan() {
 | 
			
		||||
		return scanner.Text(), nil
 | 
			
		||||
	}
 | 
			
		||||
	if err := scanner.Err(); err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return "", io.ErrUnexpectedEOF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// readInt parses the first line from a cgroup param file as int.
 | 
			
		||||
func (cg *CGroup) readInt(param string) (int, error) {
 | 
			
		||||
	text, err := cg.readFirstLine(param)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return strconv.Atoi(text)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
package cgroups
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// _cgroupFSType is the Linux CGroup file system type used in
 | 
			
		||||
	// `/proc/$PID/mountinfo`.
 | 
			
		||||
	_cgroupFSType = "cgroup"
 | 
			
		||||
	// _cgroupSubsysCPU is the CPU CGroup subsystem.
 | 
			
		||||
	_cgroupSubsysCPU = "cpu"
 | 
			
		||||
	// _cgroupSubsysCPUAcct is the CPU accounting CGroup subsystem.
 | 
			
		||||
	_cgroupSubsysCPUAcct = "cpuacct"
 | 
			
		||||
	// _cgroupSubsysCPUSet is the CPUSet CGroup subsystem.
 | 
			
		||||
	_cgroupSubsysCPUSet = "cpuset"
 | 
			
		||||
	// _cgroupSubsysMemory is the Memory CGroup subsystem.
 | 
			
		||||
	_cgroupSubsysMemory = "memory"
 | 
			
		||||
 | 
			
		||||
	// _cgroupCPUCFSQuotaUsParam is the file name for the CGroup CFS quota
 | 
			
		||||
	// parameter.
 | 
			
		||||
	_cgroupCPUCFSQuotaUsParam = "cpu.cfs_quota_us"
 | 
			
		||||
	// _cgroupCPUCFSPeriodUsParam is the file name for the CGroup CFS period
 | 
			
		||||
	// parameter.
 | 
			
		||||
	_cgroupCPUCFSPeriodUsParam = "cpu.cfs_period_us"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_procPathCGroup    = "/proc/self/cgroup"
 | 
			
		||||
	_procPathMountInfo = "/proc/self/mountinfo"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CGroups is a map that associates each CGroup with its subsystem name.
 | 
			
		||||
type CGroups map[string]*CGroup
 | 
			
		||||
 | 
			
		||||
// NewCGroups returns a new *CGroups from given `mountinfo` and `cgroup` files
 | 
			
		||||
// under for some process under `/proc` file system (see also proc(5) for more
 | 
			
		||||
// information).
 | 
			
		||||
func NewCGroups(procPathMountInfo, procPathCGroup string) (CGroups, error) {
 | 
			
		||||
	cgroupSubsystems, err := parseCGroupSubsystems(procPathCGroup)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cgroups := make(CGroups)
 | 
			
		||||
	newMountPoint := func(mp *MountPoint) error {
 | 
			
		||||
		if mp.FSType != _cgroupFSType {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, opt := range mp.SuperOptions {
 | 
			
		||||
			subsys, exists := cgroupSubsystems[opt]
 | 
			
		||||
			if !exists {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cgroupPath, err := mp.Translate(subsys.Name)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			cgroups[opt] = NewCGroup(cgroupPath)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := parseMountInfo(procPathMountInfo, newMountPoint); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return cgroups, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCGroupsForCurrentProcess returns a new *CGroups instance for the current
 | 
			
		||||
// process.
 | 
			
		||||
func NewCGroupsForCurrentProcess() (CGroups, error) {
 | 
			
		||||
	return NewCGroups(_procPathMountInfo, _procPathCGroup)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CPUQuota returns the CPU quota applied with the CPU cgroup controller.
 | 
			
		||||
// It is a result of `cpu.cfs_quota_us / cpu.cfs_period_us`. If the value of
 | 
			
		||||
// `cpu.cfs_quota_us` was not set (-1), the method returns `(-1, nil)`.
 | 
			
		||||
func (cg CGroups) CPUQuota() (float64, bool, error) {
 | 
			
		||||
	cpuCGroup, exists := cg[_cgroupSubsysCPU]
 | 
			
		||||
	if !exists {
 | 
			
		||||
		return -1, false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cfsQuotaUs, err := cpuCGroup.readInt(_cgroupCPUCFSQuotaUsParam)
 | 
			
		||||
	if defined := cfsQuotaUs > 0; err != nil || !defined {
 | 
			
		||||
		return -1, defined, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cfsPeriodUs, err := cpuCGroup.readInt(_cgroupCPUCFSPeriodUsParam)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, false, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return float64(cfsQuotaUs) / float64(cfsPeriodUs), true, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// Package cgroups provides utilities to access Linux control group (CGroups)
 | 
			
		||||
// parameters (CPU quota, for example) for a given process.
 | 
			
		||||
package cgroups
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,51 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
package cgroups
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
type cgroupSubsysFormatInvalidError struct {
 | 
			
		||||
	line string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type mountPointFormatInvalidError struct {
 | 
			
		||||
	line string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type pathNotExposedFromMountPointError struct {
 | 
			
		||||
	mountPoint string
 | 
			
		||||
	root       string
 | 
			
		||||
	path       string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err cgroupSubsysFormatInvalidError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("invalid format for CGroupSubsys: %q", err.line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err mountPointFormatInvalidError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("invalid format for MountPoint: %q", err.line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err pathNotExposedFromMountPointError) Error() string {
 | 
			
		||||
	return fmt.Sprintf("path %q is not a descendant of mount point root %q and cannot be exposed from %q", err.path, err.root, err.mountPoint)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,166 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
package cgroups
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_mountInfoSep               = " "
 | 
			
		||||
	_mountInfoOptsSep           = ","
 | 
			
		||||
	_mountInfoOptionalFieldsSep = "-"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_miFieldIDMountID = iota
 | 
			
		||||
	_miFieldIDParentID
 | 
			
		||||
	_miFieldIDDeviceID
 | 
			
		||||
	_miFieldIDRoot
 | 
			
		||||
	_miFieldIDMountPoint
 | 
			
		||||
	_miFieldIDOptions
 | 
			
		||||
	_miFieldIDOptionalFields
 | 
			
		||||
 | 
			
		||||
	_miFieldCountFirstHalf
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_miFieldOffsetFSType = iota
 | 
			
		||||
	_miFieldOffsetMountSource
 | 
			
		||||
	_miFieldOffsetSuperOptions
 | 
			
		||||
 | 
			
		||||
	_miFieldCountSecondHalf
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const _miFieldCountMin = _miFieldCountFirstHalf + _miFieldCountSecondHalf
 | 
			
		||||
 | 
			
		||||
// MountPoint is the data structure for the mount points in
 | 
			
		||||
// `/proc/$PID/mountinfo`. See also proc(5) for more information.
 | 
			
		||||
type MountPoint struct {
 | 
			
		||||
	MountID        int
 | 
			
		||||
	ParentID       int
 | 
			
		||||
	DeviceID       string
 | 
			
		||||
	Root           string
 | 
			
		||||
	MountPoint     string
 | 
			
		||||
	Options        []string
 | 
			
		||||
	OptionalFields []string
 | 
			
		||||
	FSType         string
 | 
			
		||||
	MountSource    string
 | 
			
		||||
	SuperOptions   []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewMountPointFromLine parses a line read from `/proc/$PID/mountinfo` and
 | 
			
		||||
// returns a new *MountPoint.
 | 
			
		||||
func NewMountPointFromLine(line string) (*MountPoint, error) {
 | 
			
		||||
	fields := strings.Split(line, _mountInfoSep)
 | 
			
		||||
 | 
			
		||||
	if len(fields) < _miFieldCountMin {
 | 
			
		||||
		return nil, mountPointFormatInvalidError{line}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mountID, err := strconv.Atoi(fields[_miFieldIDMountID])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parentID, err := strconv.Atoi(fields[_miFieldIDParentID])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, field := range fields[_miFieldIDOptionalFields:] {
 | 
			
		||||
		if field == _mountInfoOptionalFieldsSep {
 | 
			
		||||
			fsTypeStart := _miFieldIDOptionalFields + i + 1
 | 
			
		||||
 | 
			
		||||
			if len(fields) != fsTypeStart+_miFieldCountSecondHalf {
 | 
			
		||||
				return nil, mountPointFormatInvalidError{line}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			miFieldIDFSType := _miFieldOffsetFSType + fsTypeStart
 | 
			
		||||
			miFieldIDMountSource := _miFieldOffsetMountSource + fsTypeStart
 | 
			
		||||
			miFieldIDSuperOptions := _miFieldOffsetSuperOptions + fsTypeStart
 | 
			
		||||
 | 
			
		||||
			return &MountPoint{
 | 
			
		||||
				MountID:        mountID,
 | 
			
		||||
				ParentID:       parentID,
 | 
			
		||||
				DeviceID:       fields[_miFieldIDDeviceID],
 | 
			
		||||
				Root:           fields[_miFieldIDRoot],
 | 
			
		||||
				MountPoint:     fields[_miFieldIDMountPoint],
 | 
			
		||||
				Options:        strings.Split(fields[_miFieldIDOptions], _mountInfoOptsSep),
 | 
			
		||||
				OptionalFields: fields[_miFieldIDOptionalFields:(fsTypeStart - 1)],
 | 
			
		||||
				FSType:         fields[miFieldIDFSType],
 | 
			
		||||
				MountSource:    fields[miFieldIDMountSource],
 | 
			
		||||
				SuperOptions:   strings.Split(fields[miFieldIDSuperOptions], _mountInfoOptsSep),
 | 
			
		||||
			}, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, mountPointFormatInvalidError{line}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Translate converts an absolute path inside the *MountPoint's file system to
 | 
			
		||||
// the host file system path in the mount namespace the *MountPoint belongs to.
 | 
			
		||||
func (mp *MountPoint) Translate(absPath string) (string, error) {
 | 
			
		||||
	relPath, err := filepath.Rel(mp.Root, absPath)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	if relPath == ".." || strings.HasPrefix(relPath, "../") {
 | 
			
		||||
		return "", pathNotExposedFromMountPointError{
 | 
			
		||||
			mountPoint: mp.MountPoint,
 | 
			
		||||
			root:       mp.Root,
 | 
			
		||||
			path:       absPath,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return filepath.Join(mp.MountPoint, relPath), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseMountInfo parses procPathMountInfo (usually at `/proc/$PID/mountinfo`)
 | 
			
		||||
// and yields parsed *MountPoint into newMountPoint.
 | 
			
		||||
func parseMountInfo(procPathMountInfo string, newMountPoint func(*MountPoint) error) error {
 | 
			
		||||
	mountInfoFile, err := os.Open(procPathMountInfo)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer mountInfoFile.Close()
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(mountInfoFile)
 | 
			
		||||
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		mountPoint, err := NewMountPointFromLine(scanner.Text())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if err := newMountPoint(mountPoint); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return scanner.Err()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,102 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
package cgroups
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_cgroupSep       = ":"
 | 
			
		||||
	_cgroupSubsysSep = ","
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	_csFieldIDID = iota
 | 
			
		||||
	_csFieldIDSubsystems
 | 
			
		||||
	_csFieldIDName
 | 
			
		||||
	_csFieldCount
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CGroupSubsys represents the data structure for entities in
 | 
			
		||||
// `/proc/$PID/cgroup`. See also proc(5) for more information.
 | 
			
		||||
type CGroupSubsys struct {
 | 
			
		||||
	ID         int
 | 
			
		||||
	Subsystems []string
 | 
			
		||||
	Name       string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCGroupSubsysFromLine returns a new *CGroupSubsys by parsing a string in
 | 
			
		||||
// the format of `/proc/$PID/cgroup`
 | 
			
		||||
func NewCGroupSubsysFromLine(line string) (*CGroupSubsys, error) {
 | 
			
		||||
	fields := strings.SplitN(line, _cgroupSep, _csFieldCount)
 | 
			
		||||
 | 
			
		||||
	if len(fields) != _csFieldCount {
 | 
			
		||||
		return nil, cgroupSubsysFormatInvalidError{line}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	id, err := strconv.Atoi(fields[_csFieldIDID])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cgroup := &CGroupSubsys{
 | 
			
		||||
		ID:         id,
 | 
			
		||||
		Subsystems: strings.Split(fields[_csFieldIDSubsystems], _cgroupSubsysSep),
 | 
			
		||||
		Name:       fields[_csFieldIDName],
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cgroup, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseCGroupSubsystems parses procPathCGroup (usually at `/proc/$PID/cgroup`)
 | 
			
		||||
// and returns a new map[string]*CGroupSubsys.
 | 
			
		||||
func parseCGroupSubsystems(procPathCGroup string) (map[string]*CGroupSubsys, error) {
 | 
			
		||||
	cgroupFile, err := os.Open(procPathCGroup)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer cgroupFile.Close()
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(cgroupFile)
 | 
			
		||||
	subsystems := make(map[string]*CGroupSubsys)
 | 
			
		||||
 | 
			
		||||
	for scanner.Scan() {
 | 
			
		||||
		cgroup, err := NewCGroupSubsysFromLine(scanner.Text())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		for _, subsys := range cgroup.Subsystems {
 | 
			
		||||
			subsystems[subsys] = cgroup
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := scanner.Err(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return subsystems, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_linux.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										49
									
								
								vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_linux.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
package runtime
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"math"
 | 
			
		||||
 | 
			
		||||
	cg "go.uber.org/automaxprocs/internal/cgroups"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CPUQuotaToGOMAXPROCS converts the CPU quota applied to the calling process
 | 
			
		||||
// to a valid GOMAXPROCS value.
 | 
			
		||||
func CPUQuotaToGOMAXPROCS(minValue int) (int, CPUQuotaStatus, error) {
 | 
			
		||||
	cgroups, err := cg.NewCGroupsForCurrentProcess()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return -1, CPUQuotaUndefined, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	quota, defined, err := cgroups.CPUQuota()
 | 
			
		||||
	if !defined || err != nil {
 | 
			
		||||
		return -1, CPUQuotaUndefined, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	maxProcs := int(math.Floor(quota))
 | 
			
		||||
	if minValue > 0 && maxProcs < minValue {
 | 
			
		||||
		return minValue, CPUQuotaMinUsed, nil
 | 
			
		||||
	}
 | 
			
		||||
	return maxProcs, CPUQuotaUsed, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_unsupported.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							
							
						
						
									
										30
									
								
								vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_unsupported.go
								
								
									generated
								
								
									vendored
								
								
									Normal file
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// +build !linux
 | 
			
		||||
 | 
			
		||||
package runtime
 | 
			
		||||
 | 
			
		||||
// CPUQuotaToGOMAXPROCS converts the CPU quota applied to the calling process
 | 
			
		||||
// to a valid GOMAXPROCS value. This is Linux-specific and not supported in the
 | 
			
		||||
// current OS.
 | 
			
		||||
func CPUQuotaToGOMAXPROCS(_ int) (int, CPUQuotaStatus, error) {
 | 
			
		||||
	return -1, CPUQuotaUndefined, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
package runtime
 | 
			
		||||
 | 
			
		||||
// CPUQuotaStatus presents the status of how CPU quota is used
 | 
			
		||||
type CPUQuotaStatus int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// CPUQuotaUndefined is returned when CPU quota is undefined
 | 
			
		||||
	CPUQuotaUndefined CPUQuotaStatus = iota
 | 
			
		||||
	// CPUQuotaUsed is returned when a valid CPU quota can be used
 | 
			
		||||
	CPUQuotaUsed
 | 
			
		||||
	// CPUQuotaMinUsed is return when CPU quota is smaller than the min value
 | 
			
		||||
	CPUQuotaMinUsed
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,130 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
// Package maxprocs lets Go programs easily configure runtime.GOMAXPROCS to
 | 
			
		||||
// match the configured Linux CPU quota. Unlike the top-level automaxprocs
 | 
			
		||||
// package, it lets the caller configure logging and handle errors.
 | 
			
		||||
package maxprocs // import "go.uber.org/automaxprocs/maxprocs"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
 | 
			
		||||
	iruntime "go.uber.org/automaxprocs/internal/runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const _maxProcsKey = "GOMAXPROCS"
 | 
			
		||||
 | 
			
		||||
func currentMaxProcs() int {
 | 
			
		||||
	return runtime.GOMAXPROCS(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type config struct {
 | 
			
		||||
	printf        func(string, ...interface{})
 | 
			
		||||
	procs         func(int) (int, iruntime.CPUQuotaStatus, error)
 | 
			
		||||
	minGOMAXPROCS int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *config) log(fmt string, args ...interface{}) {
 | 
			
		||||
	if c.printf != nil {
 | 
			
		||||
		c.printf(fmt, args...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// An Option alters the behavior of Set.
 | 
			
		||||
type Option interface {
 | 
			
		||||
	apply(*config)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Logger uses the supplied printf implementation for log output. By default,
 | 
			
		||||
// Set doesn't log anything.
 | 
			
		||||
func Logger(printf func(string, ...interface{})) Option {
 | 
			
		||||
	return optionFunc(func(cfg *config) {
 | 
			
		||||
		cfg.printf = printf
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Min sets the minimum GOMAXPROCS value that will be used.
 | 
			
		||||
// Any value below 1 is ignored.
 | 
			
		||||
func Min(n int) Option {
 | 
			
		||||
	return optionFunc(func(cfg *config) {
 | 
			
		||||
		if n >= 1 {
 | 
			
		||||
			cfg.minGOMAXPROCS = n
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type optionFunc func(*config)
 | 
			
		||||
 | 
			
		||||
func (of optionFunc) apply(cfg *config) { of(cfg) }
 | 
			
		||||
 | 
			
		||||
// Set GOMAXPROCS to match the Linux container CPU quota (if any), returning
 | 
			
		||||
// any error encountered and an undo function.
 | 
			
		||||
//
 | 
			
		||||
// Set is a no-op on non-Linux systems and in Linux environments without a
 | 
			
		||||
// configured CPU quota.
 | 
			
		||||
func Set(opts ...Option) (func(), error) {
 | 
			
		||||
	cfg := &config{
 | 
			
		||||
		procs:         iruntime.CPUQuotaToGOMAXPROCS,
 | 
			
		||||
		minGOMAXPROCS: 1,
 | 
			
		||||
	}
 | 
			
		||||
	for _, o := range opts {
 | 
			
		||||
		o.apply(cfg)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	undoNoop := func() {
 | 
			
		||||
		cfg.log("maxprocs: No GOMAXPROCS change to reset")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Honor the GOMAXPROCS environment variable if present. Otherwise, amend
 | 
			
		||||
	// `runtime.GOMAXPROCS()` with the current process' CPU quota if the OS is
 | 
			
		||||
	// Linux, and guarantee a minimum value of 1. The minimum guaranteed value
 | 
			
		||||
	// can be overriden using `maxprocs.Min()`.
 | 
			
		||||
	if max, exists := os.LookupEnv(_maxProcsKey); exists {
 | 
			
		||||
		cfg.log("maxprocs: Honoring GOMAXPROCS=%q as set in environment", max)
 | 
			
		||||
		return undoNoop, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	maxProcs, status, err := cfg.procs(cfg.minGOMAXPROCS)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return undoNoop, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if status == iruntime.CPUQuotaUndefined {
 | 
			
		||||
		cfg.log("maxprocs: Leaving GOMAXPROCS=%v: CPU quota undefined", currentMaxProcs())
 | 
			
		||||
		return undoNoop, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prev := currentMaxProcs()
 | 
			
		||||
	undo := func() {
 | 
			
		||||
		cfg.log("maxprocs: Resetting GOMAXPROCS to %v", prev)
 | 
			
		||||
		runtime.GOMAXPROCS(prev)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch status {
 | 
			
		||||
	case iruntime.CPUQuotaMinUsed:
 | 
			
		||||
		cfg.log("maxprocs: Updating GOMAXPROCS=%v: using minimum allowed GOMAXPROCS", maxProcs)
 | 
			
		||||
	case iruntime.CPUQuotaUsed:
 | 
			
		||||
		cfg.log("maxprocs: Updating GOMAXPROCS=%v: determined from CPU quota", maxProcs)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	runtime.GOMAXPROCS(maxProcs)
 | 
			
		||||
	return undo, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
// Copyright (c) 2017 Uber Technologies, Inc.
 | 
			
		||||
//
 | 
			
		||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
// of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
// in the Software without restriction, including without limitation the rights
 | 
			
		||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
// copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
// furnished to do so, subject to the following conditions:
 | 
			
		||||
//
 | 
			
		||||
// The above copyright notice and this permission notice shall be included in
 | 
			
		||||
// all copies or substantial portions of the Software.
 | 
			
		||||
//
 | 
			
		||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
// THE SOFTWARE.
 | 
			
		||||
 | 
			
		||||
package maxprocs
 | 
			
		||||
 | 
			
		||||
// Version is the current package version.
 | 
			
		||||
const Version = "1.4.0"
 | 
			
		||||
| 
						 | 
				
			
			@ -250,6 +250,12 @@ github.com/stretchr/testify/require
 | 
			
		|||
## explicit
 | 
			
		||||
github.com/urfave/cli/v2
 | 
			
		||||
github.com/urfave/cli/v2/altsrc
 | 
			
		||||
# go.uber.org/automaxprocs v1.4.0
 | 
			
		||||
## explicit
 | 
			
		||||
go.uber.org/automaxprocs
 | 
			
		||||
go.uber.org/automaxprocs/internal/cgroups
 | 
			
		||||
go.uber.org/automaxprocs/internal/runtime
 | 
			
		||||
go.uber.org/automaxprocs/maxprocs
 | 
			
		||||
# golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
 | 
			
		||||
## explicit
 | 
			
		||||
golang.org/x/crypto/blake2b
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue