Skip to content

Commit 2a378d4

Browse files
gpsheadclaude
andcommitted
pystrhex: Remove SIMD path for separator groups
The SIMD-accelerated separator insertion code (for bytes_per_sep >= 8) adds maintenance complexity with less clear benefit. Remove it along with the test_hex_simd_separator test per reviewer feedback. The no-separator SIMD path remains, which is the primary performance win for bytes.hex(), bytearray.hex(), and binascii.hexlify(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5fc294c commit 2a378d4

2 files changed

Lines changed: 0 additions & 98 deletions

File tree

Lib/test/test_bytes.py

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -615,56 +615,6 @@ def test_hex_nibble_boundaries(self):
615615
simd_boundary = self.type2test(boundary_bytes * 2)
616616
self.assertEqual(simd_boundary.hex(), '090a90999aa0a9aa00ff' * 2)
617617

618-
def test_hex_simd_separator(self):
619-
# Test SIMD path for separator insertion (sep >= 8 bytes, len >= 16).
620-
# SIMD hexlifies then shuffles in-place to insert separators.
621-
622-
# 32 bytes exercises SIMD; test various separator group sizes
623-
data = self.type2test(bytes(range(32)))
624-
625-
# bytes_per_sep=8: 4 groups of 8 bytes, 3 separators
626-
self.assertEqual(
627-
data.hex('-', 8),
628-
'0001020304050607-08090a0b0c0d0e0f-'
629-
'1011121314151617-18191a1b1c1d1e1f'
630-
)
631-
# bytes_per_sep=9: groups of 9 from start, 5 byte remainder at end
632-
self.assertEqual(
633-
data.hex('.', 9),
634-
'0001020304.05060708090a0b0c0d.'
635-
'0e0f10111213141516.1718191a1b1c1d1e1f'
636-
)
637-
# bytes_per_sep=16: 2 groups of 16 bytes
638-
self.assertEqual(
639-
data.hex(' ', 16),
640-
'000102030405060708090a0b0c0d0e0f '
641-
'101112131415161718191a1b1c1d1e1f'
642-
)
643-
# Negative bytes_per_sep: groups from end, remainder at start
644-
self.assertEqual(
645-
data.hex('|', -8),
646-
'0001020304050607|08090a0b0c0d0e0f|'
647-
'1011121314151617|18191a1b1c1d1e1f'
648-
)
649-
self.assertEqual(
650-
data.hex('_', -9),
651-
'000102030405060708_090a0b0c0d0e0f1011_'
652-
'12131415161718191a_1b1c1d1e1f'
653-
)
654-
655-
# 20 bytes: SIMD (16) + 4 byte scalar remainder
656-
data20 = self.type2test(bytes(range(20)))
657-
# Positive: groups from start, remainder at end
658-
self.assertEqual(
659-
data20.hex('#', 8),
660-
'00010203#0405060708090a0b#0c0d0e0f10111213'
661-
)
662-
# Negative: groups from end, remainder at start
663-
self.assertEqual(
664-
data20.hex('@', -8),
665-
'0001020304050607@08090a0b0c0d0e0f@10111213'
666-
)
667-
668618
def test_join(self):
669619
self.assertEqual(self.type2test(b"").join([]), b"")
670620
self.assertEqual(self.type2test(b"").join([b""]), b"")

Python/pystrhex.c

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -219,50 +219,6 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen,
219219
Py_ssize_t chunk;
220220
unsigned int k;
221221

222-
#if PY_HEXLIFY_CAN_COMPILE_SIMD
223-
/* SIMD path for separator groups >= 8 bytes.
224-
SIMD hexlify to output buffer, then shuffle in-place to insert
225-
separators. Working backwards avoids overlap issues since we're
226-
expanding (destination index >= source index). */
227-
if (abs_bytes_per_sep >= 8 && arglen >= 16) {
228-
/* SIMD hexlify all bytes to start of output buffer */
229-
_Py_hexlify_simd((const unsigned char *)argbuf, retbuf, arglen);
230-
231-
/* Shuffle in-place, working backwards */
232-
Py_ssize_t hex_chunk_size = 2 * (Py_ssize_t)abs_bytes_per_sep;
233-
Py_ssize_t remainder_bytes = arglen - chunks * (Py_ssize_t)abs_bytes_per_sep;
234-
Py_ssize_t remainder_hex_len = 2 * remainder_bytes;
235-
Py_ssize_t hex_pos = 2 * arglen; /* End of hex data */
236-
Py_ssize_t out_pos = resultlen; /* End of output */
237-
238-
if (bytes_per_sep_group < 0) {
239-
/* Forward: remainder at end, separators after each chunk */
240-
if (remainder_hex_len > 0) {
241-
hex_pos -= remainder_hex_len;
242-
out_pos -= remainder_hex_len;
243-
memmove(retbuf + out_pos, retbuf + hex_pos, remainder_hex_len);
244-
}
245-
for (Py_ssize_t c = chunks - 1; c >= 0; c--) {
246-
retbuf[--out_pos] = sep_char;
247-
hex_pos -= hex_chunk_size;
248-
out_pos -= hex_chunk_size;
249-
memmove(retbuf + out_pos, retbuf + hex_pos, hex_chunk_size);
250-
}
251-
}
252-
else {
253-
/* Backward: remainder at start, separators before each chunk */
254-
for (Py_ssize_t c = chunks - 1; c >= 0; c--) {
255-
hex_pos -= hex_chunk_size;
256-
out_pos -= hex_chunk_size;
257-
memmove(retbuf + out_pos, retbuf + hex_pos, hex_chunk_size);
258-
retbuf[--out_pos] = sep_char;
259-
}
260-
/* Remainder at start stays in place (hex_pos == out_pos == remainder_hex_len) */
261-
}
262-
goto done_hexlify;
263-
}
264-
#endif /* PY_HEXLIFY_CAN_COMPILE_SIMD */
265-
266222
if (bytes_per_sep_group < 0) {
267223
i = j = 0;
268224
for (chunk = 0; chunk < chunks; chunk++) {
@@ -300,10 +256,6 @@ static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen,
300256
}
301257
}
302258

303-
#if PY_HEXLIFY_CAN_COMPILE_SIMD
304-
done_hexlify:
305-
#endif
306-
307259
#ifdef Py_DEBUG
308260
if (!return_bytes) {
309261
assert(_PyUnicode_CheckConsistency(retval, 1));

0 commit comments

Comments
 (0)