Skip to content

Commit

Permalink
Merge branch 'main' into instructionsdelete
Browse files Browse the repository at this point in the history
  • Loading branch information
phbnf authored Dec 9, 2024
2 parents 86831ea + cfc5fe2 commit 9471197
Show file tree
Hide file tree
Showing 36 changed files with 762 additions and 346 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/benchmark-go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Benchmark Go

on:
push:
branches:
- main

permissions:
# deployments permission to deploy GitHub pages website
deployments: write
# contents permission to update benchmark contents in gh-pages branch
contents: write
# allow posting comments to pull request
pull-requests: write

jobs:
benchmark:
name: Performance regression check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version-file: go.mod
- name: Run benchmark
run: set -o pipefail; go test ./... -benchmem -run=^$ -bench . | tee output.txt
- name: Store benchmark result
uses: benchmark-action/[email protected]
with:
tool: 'go'
output-file-path: output.txt
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
alert-threshold: "150%"
comment-on-alert: true
fail-on-alert: true
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,18 @@ When writing your Tessera personality, the biggest decision you need to make fir
* [POSIX](./storage/posix/)

Each of these implementations has a very similar API, but they have different characteristics.

The easiest implementations to operate and to scale are the cloud implementations: GCP and AWS.
These are the recommended choice for the majority of users.
These are the recommended choice for the majority of users running in production.

If you aren't using a cloud provider, then your options are MySQL and POSIX:
- POSIX is the simplest to get started with as it needs little in the way of extra infrastructure, and
if you already serve static files as part of your business/project this could be a good fit.
- Alternatively, if you are used to operating user-facing applications backed by a RDBMS, then MySQL could
be a natural fit.

If you aren't using a cloud provider, then your options are MySQL and POSIX.
POSIX is the more niche choice, intended to be lightweight and for logs that are infrequently updated.
If you already serve static files as part of your business this could be a good fit.
If you are more used to operating user-facing applications backed by a RDBMS, then MySQL will be a natural fit.
To get a sense of the rough performance you can expect from the different backends, take a look at
[docs/performance.md](/docs/performance.md).

#### Setup

Expand Down
8 changes: 4 additions & 4 deletions api/layout/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ func ExampleNodeCoordsToTileAddress() {
}

func ExampleTilePath() {
tilePath := layout.TilePath(0, 1234067, 315921160)
tilePath := layout.TilePath(0, 1234067, 8)
fmt.Printf("tile path: %s", tilePath)
// Output: tile path: tile/0/x001/x234/067.p/8
}

func ExampleEntriesPath() {
entriesPath := layout.EntriesPath(1234067, 315921160)
entriesPath := layout.EntriesPath(1234067, 8)
fmt.Printf("entries path: %s", entriesPath)
// Output: entries path: tile/entries/x001/x234/067.p/8
}

func ExampleParseTileLevelIndexWidth() {
level, index, width, _ := layout.ParseTileLevelIndexWidth("0", "x001/x234/067.p/8")
func ExampleParseTileLevelIndexPartial() {
level, index, width, _ := layout.ParseTileLevelIndexPartial("0", "x001/x234/067.p/8")
fmt.Printf("level: %d, index: %d, width: %d", level, index, width)
// Output: level: 0, index: 1234067, width: 8
}
34 changes: 18 additions & 16 deletions api/layout/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,28 @@ const (
// The logSize is required so that a partial qualifier can be appended to tiles that
// would contain fewer than 256 entries.
func EntriesPathForLogIndex(seq, logSize uint64) string {
return EntriesPath(seq/256, logSize)
return EntriesPath(seq/EntryBundleWidth, PartialTileSize(0, seq, logSize))
}

// NWithSuffix returns a tiles-spec "N" path, with a partial suffix if applicable.
func NWithSuffix(l, n, logSize uint64) string {
// NWithSuffix returns a tiles-spec "N" path, with a partial suffix if p > 0.
func NWithSuffix(l, n uint64, p uint8) string {
suffix := ""
if p := partialTileSize(l, n, logSize); p > 0 {
if p > 0 {
suffix = fmt.Sprintf(".p/%d", p)
}
return fmt.Sprintf("%s%s", fmtN(n), suffix)
}

// EntriesPath returns the local path for the nth entry bundle. p denotes the partial
// tile size, or 0 if the tile is complete.
func EntriesPath(n, logSize uint64) string {
return fmt.Sprintf("tile/entries/%s", NWithSuffix(0, n, logSize))
func EntriesPath(n uint64, p uint8) string {
return fmt.Sprintf("tile/entries/%s", NWithSuffix(0, n, p))
}

// TilePath builds the path to the subtree tile with the given level and index in tile space.
func TilePath(tileLevel, tileIndex, logSize uint64) string {
return fmt.Sprintf("tile/%d/%s", tileLevel, NWithSuffix(tileLevel, tileIndex, logSize))
// If p > 0 the path represents a partial tile.
func TilePath(tileLevel, tileIndex uint64, p uint8) string {
return fmt.Sprintf("tile/%d/%s", tileLevel, NWithSuffix(tileLevel, tileIndex, p))
}

// fmtN returns the "N" part of a Tiles-spec path.
Expand All @@ -83,13 +84,13 @@ func fmtN(N uint64) string {
// Examples:
// "/tile/0/x001/x234/067" means level 0 and index 1234067 of a full tile.
// "/tile/0/x001/x234/067.p/8" means level 0, index 1234067 and width 8 of a partial tile.
func ParseTileLevelIndexWidth(level, index string) (uint64, uint64, uint64, error) {
func ParseTileLevelIndexPartial(level, index string) (uint64, uint64, uint8, error) {
l, err := ParseTileLevel(level)
if err != nil {
return 0, 0, 0, err
}

i, w, err := ParseTileIndexWidth(index)
i, w, err := ParseTileIndexPartial(index)
if err != nil {
return 0, 0, 0, err
}
Expand All @@ -107,17 +108,18 @@ func ParseTileLevel(level string) (uint64, error) {
return l, err
}

// ParseTileIndexWidth takes index in string, validates and returns the index and width in uint64.
func ParseTileIndexWidth(index string) (uint64, uint64, error) {
w := uint64(256)
// ParseTileIndexPartial takes index in string, validates and returns the index and width in uint64.
func ParseTileIndexPartial(index string) (uint64, uint8, error) {
w := uint8(0)
indexPaths := strings.Split(index, "/")

if strings.Contains(index, ".p") {
var err error
w, err = strconv.ParseUint(indexPaths[len(indexPaths)-1], 10, 64)
if err != nil || w < 1 || w > 255 {
return 0, 0, fmt.Errorf("failed to parse tile index")
w64, err := strconv.ParseUint(indexPaths[len(indexPaths)-1], 10, 64)
if err != nil || w64 < 1 || w64 >= TileWidth {
return 0, 0, fmt.Errorf("failed to parse tile width")
}
w = uint8(w64)
indexPaths[len(indexPaths)-2] = strings.TrimSuffix(indexPaths[len(indexPaths)-2], ".p")
indexPaths = indexPaths[:len(indexPaths)-1]
}
Expand Down
Loading

0 comments on commit 9471197

Please sign in to comment.