Skip to content

use mmap syscall instead of open to reduce baseline memory footprint on startup#14

Open
af-emp-0271 wants to merge 1 commit intomasterfrom
proxydb-memory-optimization
Open

use mmap syscall instead of open to reduce baseline memory footprint on startup#14
af-emp-0271 wants to merge 1 commit intomasterfrom
proxydb-memory-optimization

Conversation

@af-emp-0271
Copy link
Copy Markdown
Contributor

@af-emp-0271 af-emp-0271 commented Apr 7, 2026

Summary by CodeRabbit

  • Refactor
    • Optimized proxy database file handling by implementing memory-mapped file access, enhancing resource efficiency and runtime performance during database initialization and operations.

@af-emp-0271 af-emp-0271 requested a review from at-emp-4 April 7, 2026 07:47
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 7, 2026

📝 Walkthrough

Walkthrough

The Client struct adds a mmapData []byte field to store memory-mapped file data. The Open() method is refactored to use syscall.Mmap for read-only memory mapping of the database file instead of the prior direct file opening approach, with a new openMmap helper function handling mmap initialization and error cleanup via syscall.Munmap.

Changes

Cohort / File(s) Summary
Memory-Mapped File I/O Implementation
proxydb/proxydb.go
Added mmapData []byte field to Client struct. Modified Open() method to use openMmap helper that opens DB file, memory-maps it read-only with syscall.Mmap, initializes DB via ip2proxy.FromBytes(), and cleans up mapped region with syscall.Munmap on parse failure.

Sequence Diagram

sequenceDiagram
    participant Client
    participant openMmap as openMmap Helper
    participant FileSystem as File System
    participant Syscall
    participant ip2proxy as ip2proxy Library

    Client->>openMmap: Call openMmap(c)
    openMmap->>FileSystem: os.Open(c.dbpath)
    FileSystem-->>openMmap: File Handle
    openMmap->>Syscall: syscall.Mmap(MAP_SHARED, read-only)
    Syscall-->>openMmap: mmapData []byte
    openMmap->>ip2proxy: ip2proxy.FromBytes(mmapData)
    alt Parse Success
        ip2proxy-->>openMmap: DB initialized
        openMmap-->>Client: error = nil
    else Parse Failure
        ip2proxy-->>openMmap: error
        openMmap->>Syscall: syscall.Munmap(mmapData)
        openMmap-->>Client: error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A Rabbit's Ode to Memory Mapping

Through syscall's burrow, the data flows fast,
Mapped to memory, no disk seeks at last,
A clever optimization, swift and so lean,
Where bytes and the file system beautifully convene! 🗺️

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically describes the main change: replacing file open with memory-mapped syscall to optimize baseline memory usage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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 proxydb-memory-optimization

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.

Actionable comments posted: 3

🧹 Nitpick comments (1)
proxydb/proxydb.go (1)

62-72: Remove commented-out code and simplify the method.

The commented-out old implementation should be removed. Additionally, the method can be simplified to a single return statement.

Proposed simplification
 func (c *Client) Open() error {
-	err := openMmap(c)
-	return err
-	// var err error
-	// c.DB, err = ip2proxy.Open(c.dbpath)
-	// if err != nil {
-	// 	c.DB = nil
-	// 	return err
-	// }
-	// return nil
+	return openMmap(c)
 }
-
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@proxydb/proxydb.go` around lines 62 - 72, Remove the commented-out legacy
ip2proxy code inside the Client.Open method and simplify the implementation to a
single return of the mmap helper; specifically, edit the Client.Open function
(which currently calls openMmap(c)) to remove the commented block referencing
ip2proxy.Open and change the body to just "return openMmap(c)" so it is concise
and has no commented dead code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@proxydb/proxydb.go`:
- Line 44: int(stat.Size()) can overflow on 32-bit systems because stat.Size()
is int64; update the code to avoid truncation by either (a) changing the
receiving variable/types to int64 and use stat.Size() directly, or (b) if an int
is required, validate the size before casting: import math, check if stat.Size()
> int64(math.MaxInt) and return an error when too large, otherwise safely cast
with int(stat.Size()); refer to the call using stat.Size() and the current
int(...) cast to locate the change.
- Around line 11-15: Add a Close method on the Client type that unmaps mmapData
and clears the reference; specifically implement func (c *Client) Close() error
that checks if c.mmapData != nil, calls syscall.Munmap(c.mmapData), handles and
returns any error, and then sets c.mmapData = nil (and optionally c.DB = nil) so
resources are released; ensure callers of the client (where Client is created)
call Client.Close() when done.
- Around line 5-6: The code currently calls syscall.Mmap and syscall.Munmap (in
proxydb.go) which are Unix-only and break Windows builds; replace these direct
syscall usages with a cross-platform mmap abstraction (e.g.,
golang.org/x/exp/mmap or github.com/edsrzf/mmap-go) or split platform-specific
implementations using build tags. Concretely, remove calls to
syscall.Mmap/syscall.Munmap in the function(s) that perform file memory mapping,
introduce an interface or helper (e.g., MapFile/UnmapFile) backed by the chosen
portable package (or by separate _unix.go and _windows.go files with build
constraints), and update callers to use that abstraction so the package compiles
and runs on Windows as well as Unix.

---

Nitpick comments:
In `@proxydb/proxydb.go`:
- Around line 62-72: Remove the commented-out legacy ip2proxy code inside the
Client.Open method and simplify the implementation to a single return of the
mmap helper; specifically, edit the Client.Open function (which currently calls
openMmap(c)) to remove the commented block referencing ip2proxy.Open and change
the body to just "return openMmap(c)" so it is concise and has no commented dead
code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4ec7d0d-6c4a-4ee7-a3e7-729739a6858b

📥 Commits

Reviewing files that changed from the base of the PR and between d173386 and dec2682.

📒 Files selected for processing (1)
  • proxydb/proxydb.go

Comment on lines +5 to +6
"os"
"syscall"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if there's any build constraint or platform-specific handling in the repo
rg -n "//go:build|// \+build" --type go
# Check go.mod for target platforms or existing mmap libraries
cat go.mod 2>/dev/null || echo "go.mod not found"

Repository: CloudStuffTech/go-utils

Length of output: 3814


🏁 Script executed:

#!/bin/bash
# Find and read proxydb.go
find . -name "proxydb.go" -type f

Repository: CloudStuffTech/go-utils

Length of output: 87


🏁 Script executed:

#!/bin/bash
# First check the beginning of the file to see build constraints and imports
head -60 proxydb/proxydb.go

Repository: CloudStuffTech/go-utils

Length of output: 1091


🏁 Script executed:

#!/bin/bash
# Search for actual usage of Mmap in the file
rg -n "Mmap|Munmap" proxydb/proxydb.go

Repository: CloudStuffTech/go-utils

Length of output: 193


🏁 Script executed:

#!/bin/bash
# Check first 10 lines specifically for build constraints
head -10 proxydb/proxydb.go

Repository: CloudStuffTech/go-utils

Length of output: 151


🏁 Script executed:

#!/bin/bash
# Check if there's a proxydb_unix.go or similar platform-specific variant
find proxydb -name "*.go" | head -20

Repository: CloudStuffTech/go-utils

Length of output: 85


Platform portability: syscall.Mmap and syscall.Munmap are Unix-specific and will fail on Windows.

The code directly uses syscall.Mmap and syscall.Munmap (lines 41 and 55) without any build constraints or platform-specific handling. These functions are unavailable on Windows and will cause compilation failures. If cross-platform support is required, use golang.org/x/exp/mmap or github.com/edsrzf/mmap-go to provide a portable abstraction.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@proxydb/proxydb.go` around lines 5 - 6, The code currently calls syscall.Mmap
and syscall.Munmap (in proxydb.go) which are Unix-only and break Windows builds;
replace these direct syscall usages with a cross-platform mmap abstraction
(e.g., golang.org/x/exp/mmap or github.com/edsrzf/mmap-go) or split
platform-specific implementations using build tags. Concretely, remove calls to
syscall.Mmap/syscall.Munmap in the function(s) that perform file memory mapping,
introduce an interface or helper (e.g., MapFile/UnmapFile) backed by the chosen
portable package (or by separate _unix.go and _windows.go files with build
constraints), and update callers to use that abstraction so the package compiles
and runs on Windows as well as Unix.

Comment on lines 11 to 15
type Client struct {
dbpath string
DB *ip2proxy.DB
dbpath string
DB *ip2proxy.DB
mmapData []byte
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Missing Close() method to release mmap resources.

The Client now holds mmapData which is memory-mapped via syscall.Mmap, but there's no corresponding Close() method to call syscall.Munmap. This will leak the memory-mapped region for the lifetime of the process.

Proposed fix: Add a Close method
+func (c *Client) Close() error {
+	if c.mmapData != nil {
+		err := syscall.Munmap(c.mmapData)
+		c.mmapData = nil
+		c.DB = nil
+		return err
+	}
+	return nil
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type Client struct {
dbpath string
DB *ip2proxy.DB
dbpath string
DB *ip2proxy.DB
mmapData []byte
}
func (c *Client) Close() error {
if c.mmapData != nil {
err := syscall.Munmap(c.mmapData)
c.mmapData = nil
c.DB = nil
return err
}
return nil
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@proxydb/proxydb.go` around lines 11 - 15, Add a Close method on the Client
type that unmaps mmapData and clears the reference; specifically implement func
(c *Client) Close() error that checks if c.mmapData != nil, calls
syscall.Munmap(c.mmapData), handles and returns any error, and then sets
c.mmapData = nil (and optionally c.DB = nil) so resources are released; ensure
callers of the client (where Client is created) call Client.Close() when done.

c.mmapData, err = syscall.Mmap(
int(file.Fd()),
0,
int(stat.Size()),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential integer overflow on 32-bit systems.

int(stat.Size()) truncates the file size on 32-bit systems where int is 32 bits, but stat.Size() returns int64. Files larger than 2GB would cause incorrect behavior.

Proposed fix: Add size validation
+	size := stat.Size()
+	if size > int64(^uint(0)>>1) { // max int
+		return errors.New("file too large to mmap on this platform")
+	}
+
 	// Map the file directly into virtual memory (Bypassing Go's Heap)
 	c.mmapData, err = syscall.Mmap(
 		int(file.Fd()),
 		0,
-		int(stat.Size()),
+		int(size),
 		syscall.PROT_READ,  // Read-only memory
 		syscall.MAP_SHARED, // Share with OS page cache
 	)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int(stat.Size()),
size := stat.Size()
if size > int64(^uint(0)>>1) { // max int
return errors.New("file too large to mmap on this platform")
}
// Map the file directly into virtual memory (Bypassing Go's Heap)
c.mmapData, err = syscall.Mmap(
int(file.Fd()),
0,
int(size),
syscall.PROT_READ, // Read-only memory
syscall.MAP_SHARED, // Share with OS page cache
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@proxydb/proxydb.go` at line 44, int(stat.Size()) can overflow on 32-bit
systems because stat.Size() is int64; update the code to avoid truncation by
either (a) changing the receiving variable/types to int64 and use stat.Size()
directly, or (b) if an int is required, validate the size before casting: import
math, check if stat.Size() > int64(math.MaxInt) and return an error when too
large, otherwise safely cast with int(stat.Size()); refer to the call using
stat.Size() and the current int(...) cast to locate the change.

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