Skip to content

perf(core): daily incremental optimizations and safety harding#164

Open
repyh wants to merge 1 commit into
mainfrom
daily-optimization-patch-8474244443530169332
Open

perf(core): daily incremental optimizations and safety harding#164
repyh wants to merge 1 commit into
mainfrom
daily-optimization-patch-8474244443530169332

Conversation

@repyh
Copy link
Copy Markdown
Owner

@repyh repyh commented May 25, 2026

This daily optimization patch addresses multiple areas in the bridge/core and eventloop packages to improve execution speed, minimize memory allocations, and enhance runtime safety.

Key Changes:

  1. Reflection Opts (bindSlice & bindMap): Eliminated interface boxing and allocation overhead for standard numeric/byte slice mapping into Sobek.
  2. Cache Line Usage: Reordered struct fields in EventLoop to ensure hot path data avoids false sharing and operates within shared cache lines alongside their lock.
  3. Safety & Stability: Repaired panics caused by multiple Resolve/Reject calls on Sobek promises using Go sync.Once primitives. Prevented potential fatal errors when operating in JS environments lacking global Uint8Array variables.

Bench Recommendation:
To verify the impact of the reflection path improvements, run: go test -bench=. ./bridge/core


PR created automatically by Jules for task 8474244443530169332 started by @repyh

Summary by CodeRabbit

  • Bug Fixes

    • Improved console error message formatting to prevent output splitting
    • Enhanced promise settlement reliability to prevent runtime errors
    • Added fallback handling for ArrayBuffer creation when standard methods unavailable
  • Refactor

    • Optimized byte array binding performance and key formatting consistency

Review Change Stack

- Adds `[]byte` fast path to `bindSlice` with explicit slice copying for memory isolation.
- Converts `bindMap` to use `MapRange()` and `strconv` primitives, avoiding interface boxing and slice allocation.
- Rearranges `EventLoop` struct fields to maximize cache locality and group variables under their protecting mutex.
- Implements `sync.Once` in `CreatePromise` to prevent wait group panics from double-settling.
- Consolidates console logging to prevent double-locking `os.Stdout`.
- Implements safe fallback for `Uint8Array` constructor resolution in `MapSharedBuffer`.

Co-authored-by: repyh <63894915+repyh@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

📝 Walkthrough

Walkthrough

This PR introduces reliability and performance improvements across the Go-to-JavaScript bridge layer and event loop. Changes add fallback handling for missing ArrayBuffer constructors, optimize byte slice and map binding in reflection, fix console error output formatting, and ensure promise callbacks execute safely only once via synchronization primitives.

Changes

Bridge and EventLoop Enhancements

Layer / File(s) Summary
ArrayBuffer and typed array binding
bridge/core/arraybuffer.go, bridge/core/reflection.go
MapSharedBuffer guards against missing Uint8Array and falls back to direct ArrayBuffer registration. bindSlice adds a fast path for []byte that converts to ArrayBuffer via ToArrayBuffer with explicit data copying.
Map binding and numeric key formatting
bridge/core/reflection.go
bindMap switches to MapRange() iteration and uses strconv for efficient numeric key formatting (string keys via key.String(), integers via FormatInt/FormatUint, others via fmt.Sprint).
Console error output formatting
bridge/core/console.go
Console.Error now prepends "Error:" as the first argument in a single print call instead of splitting output across separate calls.
Promise callback safety and field organization
eventloop/eventloop.go
EventLoop struct fields reorganized to group mu with running. CreatePromise callbacks guarded by sync.Once to ensure wg.Done() executes exactly once, preventing panics on multiple invocations.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

A rabbit hops through bridge code neat,
With buffers safe and promises sweet,
Once-guarded callbacks dance with care,
Maps iterate with formatting flair,
Go and JavaScript now both play fair! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'perf(core): daily incremental optimizations and safety harding' accurately reflects the main changes across the PR—performance improvements in reflection/binding, eventloop optimizations, and safety fixes (Uint8Array fallback, sync.Once guards, console logging fixes).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch daily-optimization-patch-8474244443530169332

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
bridge/core/arraybuffer.go (1)

34-45: ⚡ Quick win

Document the new ArrayBuffer fallback behavior in MapSharedBuffer.

The implementation now conditionally exposes raw ArrayBuffer, but the function docs still state it is exposed as Uint8Array. Please update the docstring to reflect both outcomes.

Proposed doc update
 // The buffer is registered as a global variable with the given name, accessible
-// as a Uint8Array in JavaScript. This is commonly used for inter-worker
+// as a Uint8Array in JavaScript when available. In environments where
+// Uint8Array is unavailable, it falls back to exposing the ArrayBuffer directly.
+// This is commonly used for inter-worker
 // communication and zero-copy data sharing.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bridge/core/arraybuffer.go` around lines 34 - 45, The MapSharedBuffer
docstring still says the buffer is exposed as a Uint8Array but the
implementation (in MapSharedBuffer) falls back to exposing a raw ArrayBuffer
when Uint8Array is unavailable; update the function comment to describe both
outcomes: when the global Uint8Array exists MapSharedBuffer exposes a Uint8Array
view (using ctor/typedArray), and when it does not it exposes the raw
ArrayBuffer (vm.ToValue(buf)), including the conditions checked (ctor == nil ||
sobek.IsNull(ctor) || sobek.IsUndefined(ctor)) and the rationale for the
graceful fallback so callers know to handle either type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@bridge/core/arraybuffer.go`:
- Around line 34-45: The MapSharedBuffer docstring still says the buffer is
exposed as a Uint8Array but the implementation (in MapSharedBuffer) falls back
to exposing a raw ArrayBuffer when Uint8Array is unavailable; update the
function comment to describe both outcomes: when the global Uint8Array exists
MapSharedBuffer exposes a Uint8Array view (using ctor/typedArray), and when it
does not it exposes the raw ArrayBuffer (vm.ToValue(buf)), including the
conditions checked (ctor == nil || sobek.IsNull(ctor) ||
sobek.IsUndefined(ctor)) and the rationale for the graceful fallback so callers
know to handle either type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b548d0df-bca6-4af3-b617-952ce5234fed

📥 Commits

Reviewing files that changed from the base of the PR and between b85f440 and 37995ee.

📒 Files selected for processing (4)
  • bridge/core/arraybuffer.go
  • bridge/core/console.go
  • bridge/core/reflection.go
  • eventloop/eventloop.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant