Skip to content
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

Refactor for easier deploys of new versions. Adds jemalloc 5.0.1 #18

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## 5.0.0

* Update to jemalloc 5
* LD_PRELOAD now works differently. Previously, you could point it directly to the jemalloc shared library (/app/vendor/jemalloc/lib/libjemalloc.so.1). Now, it's better to let jemalloc do it for you, as noted in the README. You must change this environment variable when upgrading and it is not backwards compatible. If you are not using LD_PRELOAD and instead use jemalloc.sh, no action is required.
11 changes: 0 additions & 11 deletions Dockerfile

This file was deleted.

38 changes: 25 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
default: dist/jemalloc-4.2.1-1.tar.gz
default: heroku-16 cedar-14

dist/jemalloc-4.2.1-1.tar.gz: jemalloc-cedar
docker cp $<:/tmp/jemalloc-cedar.tar.gz .
mkdir -p $$(dirname $@)
mv jemalloc-cedar.tar.gz $@
VERSION := 5.0.1
ROOT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))

clean:
rm -rf src/ dist/
-docker rm jemalloc-cedar

src/jemalloc.tar.bz2:
# Download missing source archives to ./src/
src/jemalloc-%.tar.bz2:
mkdir -p $$(dirname $@)
curl -sL https://github.com/jemalloc/jemalloc/releases/download/4.2.1/jemalloc-4.2.1.tar.bz2 -o $@
curl -fsL https://github.com/jemalloc/jemalloc/releases/download/$*/jemalloc-$*.tar.bz2 -o $@

.PHONY: cedar-14 heroku-16

# Build for cedar-14 stack
cedar-14: src/jemalloc-$(VERSION).tar.bz2
docker run -it --volume="$(ROOT_DIR):/wrk" \
heroku/cedar:14 /wrk/build.sh $(VERSION) cedar-14

.PHONY: jemalloc-cedar
# Build for heroku-16 stack
heroku-16: src/jemalloc-$(VERSION).tar.bz2
docker run -it --volume="$(ROOT_DIR):/wrk" \
heroku/heroku:16-build /wrk/build.sh $(VERSION) heroku-16

jemalloc-cedar: src/jemalloc.tar.bz2
docker build --rm -t mojodna/$@ .
-docker rm $@
docker run --name $@ mojodna/$@ /bin/echo $@
# Build recent releases for all supported stacks
all:
$(MAKE) cedar-14 VERSION=3.6.0
$(MAKE) cedar-14 VERSION=4.5.0
$(MAKE) cedar-14 VERSION=5.0.1
$(MAKE) heroku-16 VERSION=3.6.0
$(MAKE) heroku-16 VERSION=4.5.0
$(MAKE) heroku-16 VERSION=5.0.1
88 changes: 67 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,93 @@
# heroku-buildpack-jemalloc

I am a Heroku buildpack that installs
[jemalloc](http://www.canonware.com/jemalloc/) into a dyno slug.
I am a Heroku buildpack that installs [jemalloc](http://jemalloc.net/) into a
dyno slug.

## Using
## Install

To use jemalloc with your app, either prefix commands with `jemalloc.sh <cmd>`
or set `LD_PRELOAD=/app/vendor/jemalloc/lib/libjemalloc.so.1` in your
environment (it will then apply to all commands run).
[Heroku supports using multiple buildpacks for an app](https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app).

Example, in your Procfile:
```console
heroku buildpacks:add --index 1 https://github.com/mojodna/heroku-buildpack-jemalloc.git
git push heroku master
```

## Usage

### Recommended

Set the JEMALLOC_ENABLED config option to true and jemalloc will be used for
all commands run inside of your dynos.

```console
heroku config:set JEMALLOC_ENABLED=true
```

### Per dyno

To control when jemalloc is configured on a per dyno basis use
`jemalloc.sh <cmd>` and ensure that JEMALLOC_ENABLED is unset.

Example Procfile:
```yaml
web: jemalloc.sh bundle exec puma -C config/puma.rb
```

Setting LD_PRELOAD can sometimes mess with the building of an app - if you're seeing errors during slug compilation, try removing LD_PRELOAD and just using `jemalloc.sh`.
## Configuration

### Composed
### JEMALLOC_ENABLED

[Heroku now supports using multiple buildpacks for an app](https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app).
Set this to true to automatically enable jemalloc.

```bash
heroku buildpacks:add --index 1 https://github.com/mojodna/heroku-buildpack-jemalloc.git
git push heroku master
```console
heroku config:set JEMALLOC_ENABLED=true
```

If you're not seeing great results from Jemalloc 4.x, you can try Jemalloc 3.6 instead:
To disable jemalloc set the option to false. This will cause the application to
restart disabling jemalloc.

```bash
heroku buildpacks:add --index 1 https://github.com/mojodna/heroku-buildpack-jemalloc.git#v3.6.0
git push heroku master
```console
heroku config:set JEMALLOC_ENABLED=false
```

Note that you can also use this syntax to lock your buildpack to a specific release.
### JEMALLOC_VERSION

Set this to select or pin to a specific version of jemalloc. The default is to
use the latest stable version if this is not set. You will receive an error
mentioning tar if the version does not exist.

A full list of supported versions and stacks is available on the
[releases page.](https://github.com/mojodna/heroku-buildpack-jemalloc/releases)

**note:** This setting is only used during slug compilation. Changing it will
require a code change to be deployed in order to take affect.

```console
heroku config:set JEMALLOC_VERSION=5.0.1
```

## Building

This uses Docker to build against Heroku
[stack-image](https://github.com/heroku/stack-images)-like images.

```bash
make
```console
make VERSION=5.0.1
```

Artifacts will be dropped in `dist/`. See `Dockerfile`s for build options.
Artifacts will be dropped in `dist/` based on Heroku stack and jemalloc version.

### Deploying New Versions

- `make VERSION=X.Y.Z`
- `open dist`
- Go to [releases](https://github.com/mojodna/heroku-buildpack-jemalloc/releases)
- Edit the release corresponding to each heroku Stack
- Drag and drop the new build to attach

### Creating a New Stack
- Go to [releases](https://github.com/mojodna/heroku-buildpack-jemalloc/releases)
- Click "Draft a new release"
- Tag is the name of the Stack (e.g. `heroku-18`)
- Target is `release-master`
- Title is `Builds for the [stack] stack`
81 changes: 29 additions & 52 deletions bin/compile
Original file line number Diff line number Diff line change
@@ -1,61 +1,38 @@
#!/usr/bin/env bash
# bin/compile <build-dir> <cache-dir>
# bin/compile <build-dir> <cache-dir> <env-dir>
set -e

set -e # fail fast

# parse params
# Parse params
BUILD_DIR=$1
CACHE_DIR=$2
BUILDPACK_NAME=jemalloc

function indent() {
c='s/^/ /'
case $(uname) in
Darwin) sed -l "$c";;
*) sed -u "$c";;
esac
}

function vendor() {
binary="$1"
path="$2"

echo "Fetching $binary" | indent
mkdir -p $path
curl -sL $binary -s -o - | tar xz -C $path -f -

[ -d "$path/bin" ] && export PATH=$path/bin:$PATH
export CPPPATH="$path/include:$CPPPATH"
export CPATH="$path/include:$CPATH"
export LIBRARY_PATH="$path/lib:$LIBRARY_PATH"
export LD_LIBRARY_PATH="$path/lib:$LD_LIBRARY_PATH"
[ -d "$path/lib/pkgconfig" ] && export PKG_CONFIG_PATH="$path/lib/pkgconfig:$PKG_CONFIG_PATH"

true
}

echo "-----> Vendoring binaries"
vendor "https://github.com/mojodna/heroku-buildpack-jemalloc/releases/download/4.2.1/jemalloc-4.2.1-1.tar.gz" "$BUILD_DIR/vendor/jemalloc"

echo "-----> Configuring build environment"

cat <<EOF > export
export PATH="$PATH:\$PATH"
export LD_LIBRARY_PATH="\$LD_LIBRARY_PATH:$LD_LIBRARY_PATH"
export LIBRARY_PATH="\$LIBRARY_PATH:$LIBRARY_PATH"
export PKG_CONFIG_PATH="\$PKG_CONFIG_PATH:$PKG_CONFIG_PATH"
export CPPPATH="\$CPPPATH:$CPPPATH"
export CPATH="\$CPATH:$CPATH"
EOF
ENV_DIR=$3

# Default version
version="5.0.1"

# Read version from configured JEMALLOC_VERSION
if [ -f $ENV_DIR/JEMALLOC_VERSION ]; then
version=$(cat $ENV_DIR/JEMALLOC_VERSION)
fi

url="https://github.com/mojodna/heroku-buildpack-jemalloc/releases/download/$STACK/jemalloc-$version.tar.bz2"
dest="$BUILD_DIR/vendor/jemalloc"

echo "-----> Vendoring jemalloc"
echo " Fetching $url"

mkdir -p $dest
curl -sL $url | tar -C $dest -xj

echo "-----> Building runtime environment"
mkdir -p $BUILD_DIR/.profile.d

cat <<EOF > $BUILD_DIR/.profile.d/$BUILDPACK_NAME.sh
export PATH="${PATH//$BUILD_DIR//app}:\$PATH"
export LD_LIBRARY_PATH="\$LD_LIBRARY_PATH:${LD_LIBRARY_PATH//$BUILD_DIR//app}"
export LIBRARY_PATH="\$LIBRARY_PATH:${LIBRARY_PATH//$BUILD_DIR//app}"
export PKG_CONFIG_PATH="\$PKG_CONFIG_PATH:${PKG_CONFIG_PATH//$BUILD_DIR//app}"
export CPPPATH="\$CPPPATH:${CPPPATH//$BUILD_DIR//app}"
export CPATH="\$CPATH:${CPATH//$BUILD_DIR//app}"
cat <<'EOF' > $BUILD_DIR/.profile.d/jemalloc.sh
export PATH="$PATH:/app/vendor/jemalloc/bin"

# Configure LD_PRELOAD when JEMALLOC_ENABLED is set to "true". Setting this can
# be tricky for people and it occasionally changes with new versions.
if [ $JEMALLOC_ENABLED = 'true' ]; then
export LD_PRELOAD="/app/vendor/jemalloc/lib/libjemalloc.so $LD_PRELOAD"
fi
EOF
17 changes: 17 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
# usage: build [version] [stack]
set -e

version=$1
stack=$2
build=`mktemp -d`

tar -C $build --strip-components=1 -xj -f /wrk/src/jemalloc-$version.tar.bz2

cd $build
./configure --prefix=/app/vendor/jemalloc
make install_bin install_include install_lib_shared install_lib_static

# Bundle and compress the compiled library
mkdir -p /wrk/dist/$stack
tar -C /app/vendor/jemalloc -jc -f /wrk/dist/$stack/jemalloc-$version.tar.bz2 .