Skip to content

Commit fbb5635

Browse files
committed
Optimized getBytes loop processing
1 parent df6d85a commit fbb5635

File tree

2 files changed

+100
-6
lines changed

2 files changed

+100
-6
lines changed

ext/random/php_random.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,4 +214,51 @@ PHPAPI ZEND_EXTERN_MODULE_GLOBALS(random)
214214

215215
# define RANDOM_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(random, v)
216216

217+
#ifdef WORDS_BIGENDIAN
218+
# define RANDOM_LITTLE_ENDIAN 0
219+
#else
220+
# define RANDOM_LITTLE_ENDIAN 1
221+
#endif
222+
223+
/* Bytes swap */
224+
#ifdef _MSC_VER
225+
# include <stdlib.h>
226+
# define RANDOM_BSWAP32(u) _byteswap_ulong(u)
227+
# define RANDOM_BSWAP64(u) _byteswap_uint64(u)
228+
#else
229+
# ifdef __GNUC__
230+
# define RANDOM_BSWAP32(u) __builtin_bswap32(u)
231+
# define RANDOM_BSWAP64(u) __builtin_bswap64(u)
232+
# elif defined(__has_builtin)
233+
# if __has_builtin(__builtin_bswap32)
234+
# define RANDOM_BSWAP32(u) __builtin_bswap32(u)
235+
# endif // __has_builtin(__builtin_bswap32)
236+
# if __has_builtin(__builtin_bswap64)
237+
# define RANDOM_BSWAP64(u) __builtin_bswap64(u)
238+
# endif // __has_builtin(__builtin_bswap64)
239+
# endif // __GNUC__
240+
#endif // _MSC_VER
241+
#ifndef RANDOM_BSWAP32
242+
static inline uint32_t RANDOM_BSWAP32(uint32_t u)
243+
{
244+
return (((u & 0xff000000) >> 24)
245+
| ((u & 0x00ff0000) >> 8)
246+
| ((u & 0x0000ff00) << 8)
247+
| ((u & 0x000000ff) << 24));
248+
}
249+
#endif
250+
#ifndef RANDOM_BSWAP64
251+
static inline uint64_t RANDOM_BSWAP64(uint64_t u)
252+
{
253+
return (((u & 0xff00000000000000ULL) >> 56)
254+
| ((u & 0x00ff000000000000ULL) >> 40)
255+
| ((u & 0x0000ff0000000000ULL) >> 24)
256+
| ((u & 0x000000ff00000000ULL) >> 8)
257+
| ((u & 0x00000000ff000000ULL) << 8)
258+
| ((u & 0x0000000000ff0000ULL) << 24)
259+
| ((u & 0x000000000000ff00ULL) << 40)
260+
| ((u & 0x00000000000000ffULL) << 56));
261+
}
262+
#endif
263+
217264
#endif /* PHP_RANDOM_H */

ext/random/randomizer.c

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,43 @@ PHP_METHOD(Random_Randomizer, getInt)
270270
}
271271
/* }}} */
272272

273+
static zend_always_inline char *bulk_convert_generated_result_to_char_32(char *ptr, uint64_t result, size_t *to_read)
274+
{
275+
if (*to_read >= sizeof(uint32_t)) {
276+
uint32_t tmp = (uint32_t) result;
277+
#if RANDOM_LITTLE_ENDIAN == 0
278+
tmp = RANDOM_BSWAP32(tmp);
279+
#endif
280+
memcpy(ptr, &tmp, sizeof(uint32_t));
281+
ptr += sizeof(uint32_t);
282+
*to_read -= sizeof(uint32_t);
283+
} else {
284+
while (*to_read > 0) {
285+
*ptr++ = result & 0xff;
286+
result >>= 8;
287+
*to_read -= 1;
288+
}
289+
}
290+
291+
return ptr;
292+
}
293+
294+
static zend_always_inline char *bulk_convert_generated_result_to_char_64(char *ptr, uint64_t result, size_t *to_read)
295+
{
296+
if (*to_read >= sizeof(uint64_t)) {
297+
#if RANDOM_LITTLE_ENDIAN == 0
298+
result = RANDOM_BSWAP64(result);
299+
#endif
300+
memcpy(ptr, &result, sizeof(uint64_t));
301+
ptr += sizeof(uint64_t);
302+
*to_read -= sizeof(uint64_t);
303+
} else {
304+
ptr = bulk_convert_generated_result_to_char_32(ptr, result, to_read);
305+
}
306+
307+
return ptr;
308+
}
309+
273310
/* {{{ Generate random bytes string in ordered length */
274311
PHP_METHOD(Random_Randomizer, getBytes)
275312
{
@@ -278,7 +315,6 @@ PHP_METHOD(Random_Randomizer, getBytes)
278315

279316
zend_string *retval;
280317
zend_long user_length;
281-
size_t total_size = 0;
282318

283319
ZEND_PARSE_PARAMETERS_START(1, 1)
284320
Z_PARAM_LONG(user_length)
@@ -291,17 +327,28 @@ PHP_METHOD(Random_Randomizer, getBytes)
291327

292328
size_t length = (size_t)user_length;
293329
retval = zend_string_alloc(length, 0);
330+
char *rptr = ZSTR_VAL(retval);
294331

295-
while (total_size < length) {
332+
size_t to_read = length;
333+
while (to_read > 0) {
296334
php_random_result result = engine.algo->generate(engine.state);
297335
if (EG(exception)) {
298336
zend_string_free(retval);
299337
RETURN_THROWS();
300338
}
301-
for (size_t i = 0; i < result.size; i++) {
302-
ZSTR_VAL(retval)[total_size++] = (result.result >> (i * 8)) & 0xff;
303-
if (total_size >= length) {
304-
break;
339+
if (EXPECTED(result.size == sizeof(uint64_t))) {
340+
rptr = bulk_convert_generated_result_to_char_64(rptr, result.result, &to_read);
341+
} else if (EXPECTED(result.size == sizeof(uint32_t))){
342+
rptr = bulk_convert_generated_result_to_char_32(rptr, result.result, &to_read);
343+
} else {
344+
uint64_t tmp_ret = result.result;
345+
for (size_t i = 0; i < result.size; i++) {
346+
*rptr++ = tmp_ret & 0xff;
347+
tmp_ret >>= 8;
348+
to_read--;
349+
if (to_read == 0) {
350+
break;
351+
}
305352
}
306353
}
307354
}

0 commit comments

Comments
 (0)