Performance: FillRect has redundant bounds checking per pixel
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 1
- Forks
- 2
- PR merge metrics
- No merged PRs in 30d
Description
## Description
`FillRect()` calls `SetPixel()` for each pixel, which performs bounds checking on every call.
## Location
- `render/render.go:116-122` - `FillRect()`
- `render/render.go:108-111` - `SetPixel()`
## Problem
```go
func (c *Canvas) FillRect(x, y, width, height int, col color.RGBA) {
for dy := 0; dy < height; dy++ {
for dx := 0; dx < width; dx++ {
c.SetPixel(x+dx, y+dy, col) // Bounds check every iteration
}
}
}
func (c *Canvas) SetPixel(x, y int, col color.RGBA) {
if x >= 0 && x < c.Width && y >= 0 && y < c.Height { // Redundant
c.Pixels[y*c.Width+x] = col
}
}
```
For a 100x100 rectangle, this performs 10,000 redundant bounds checks.
## Suggested Improvements
1. **Clip rectangle bounds once** before the loop, then write directly to `c.Pixels`
2. **Use row-based filling** - Clip Y bounds once, fill entire rows with direct slice operations
3. **Consider `copy()` for horizontal fills** - Pre-fill a row template and copy it
Example optimized version:
```go
func (c *Canvas) FillRect(x, y, width, height int, col color.RGBA) {
// Clip bounds once
x1, y1 := max(0, x), max(0, y)
x2, y2 := min(c.Width, x+width), min(c.Height, y+height)
for py := y1; py < y2; py++ {
offset := py * c.Width
for px := x1; px < x2; px++ {
c.Pixels[offset+px] = col
}
}
}
```
## Impact
FillRect is called for every background, border, and many drawing operations. This optimization would benefit the entire rendering pipeline.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with render/render.go:116-122 and compare FillRect with SetPixel at lines 108-111. Clip the rectangle once and write rows directly to c.Pixels, preserving behavior for rectangles that extend beyond the canvas. Done means FillRect no longer calls SetPixel for every pixel while producing the same clipped result.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- computer-graphics, performance
- Issue type
- Refactor
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100