Skip to content

Commit 52604be

Browse files
committed
fix: Benches
1 parent cfbc169 commit 52604be

1 file changed

Lines changed: 33 additions & 24 deletions

File tree

src/c2pa/c2pa.py

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,7 +1807,24 @@ def read_callback(ctx, data, length):
18071807
if not data or length <= 0:
18081808
return -1
18091809

1810-
buffer = self._file_like_stream.read(length)
1810+
src = self._file_like_stream
1811+
# For larger reads, fill the buffer directly
1812+
# via a memoryview, avoiding the intermediate
1813+
# `bytes` allocation. BytesIO and binary file objects
1814+
# implement readinto. For smaller reads the per-call
1815+
# ctypes setup cost (from_address+memoryview) outweighs
1816+
# the savings, so we keep the bytes path for those.
1817+
READINTO_THRESHOLD = 4096
1818+
if length >= READINTO_THRESHOLD:
1819+
readinto = getattr(src, "readinto", None)
1820+
if readinto is not None:
1821+
arr = (ctypes.c_ubyte * length).from_address(
1822+
ctypes.addressof(data.contents)
1823+
)
1824+
n = readinto(memoryview(arr))
1825+
return n or 0
1826+
1827+
buffer = src.read(length)
18111828
if not buffer: # EOF
18121829
return 0
18131830

@@ -1870,17 +1887,8 @@ def write_callback(ctx, data, length):
18701887
if not data or length <= 0:
18711888
return -1
18721889

1873-
# Create a temporary buffer to safely handle the data
1874-
temp_buffer = (ctypes.c_ubyte * length)()
1875-
try:
1876-
# Copy data to our temporary buffer
1877-
ctypes.memmove(temp_buffer, data, length)
1878-
# Write from our safe buffer
1879-
self._file_like_stream.write(bytes(temp_buffer))
1880-
return length
1881-
finally:
1882-
# Ensure temporary buffer is cleared
1883-
ctypes.memset(temp_buffer, 0, length)
1890+
self._file_like_stream.write(ctypes.string_at(data, length))
1891+
return length
18841892
except Exception:
18851893
return -1
18861894

@@ -2890,10 +2898,7 @@ def wrapped_callback(
28902898
if data_len > 1024 * 1024: # 1MB limit
28912899
return -1
28922900

2893-
# Recover signed data (copy, to avoid lifetime issues)
2894-
temp_buffer = (ctypes.c_ubyte * data_len)()
2895-
ctypes.memmove(temp_buffer, data_ptr, data_len)
2896-
data = bytes(temp_buffer)
2901+
data = ctypes.string_at(data_ptr, data_len)
28972902

28982903
if not data:
28992904
# Error: empty data, invalid so return -1,
@@ -3558,10 +3563,7 @@ def _sign_internal(
35583563
manifest_bytes = b""
35593564
if manifest_bytes_ptr and result > 0:
35603565
try:
3561-
# Convert the C pointer to Python bytes
3562-
temp_buffer = (ctypes.c_ubyte * result)()
3563-
ctypes.memmove(temp_buffer, manifest_bytes_ptr, result)
3564-
manifest_bytes = bytes(temp_buffer)
3566+
manifest_bytes = ctypes.string_at(manifest_bytes_ptr, result)
35653567
except Exception:
35663568
manifest_bytes = b""
35673569
finally:
@@ -3660,7 +3662,13 @@ def sign(
36603662
context's signer is used.
36613663
format: The MIME type of the content.
36623664
source: The source stream.
3663-
dest: The destination stream (optional).
3665+
dest: The destination stream (optional). When
3666+
omitted, the signed asset is buffered into
3667+
an in-memory `BytesIO` sized to the full
3668+
output. For assets larger than a few MB,
3669+
pass a file or other writable stream to
3670+
avoid buffering the whole signed payload
3671+
in memory.
36643672
36653673
Returns:
36663674
Manifest bytes
@@ -3758,7 +3766,9 @@ def format_embeddable(format: str, manifest_bytes: bytes) -> tuple[int, bytes]:
37583766
_clear_error_state()
37593767

37603768
format_str = format.encode('utf-8')
3761-
manifest_array = (ctypes.c_ubyte * len(manifest_bytes))(*manifest_bytes)
3769+
manifest_array = (ctypes.c_ubyte * len(manifest_bytes)).from_buffer_copy(
3770+
manifest_bytes
3771+
)
37623772
result_bytes_ptr = ctypes.POINTER(ctypes.c_ubyte)()
37633773

37643774
result = _lib.c2pa_format_embeddable(
@@ -3771,10 +3781,9 @@ def format_embeddable(format: str, manifest_bytes: bytes) -> tuple[int, bytes]:
37713781
_check_ffi_operation_result(result,
37723782
"Failed to format embeddable manifest", check=lambda r: r < 0)
37733783

3774-
# Convert the result bytes to a Python bytes object
37753784
size = result
37763785
try:
3777-
result_bytes = bytes(result_bytes_ptr[:size])
3786+
result_bytes = ctypes.string_at(result_bytes_ptr, size)
37783787
except Exception as e:
37793788
raise C2paError(
37803789
f"Failed to convert embeddable manifest bytes: {e}"

0 commit comments

Comments
 (0)