Skip to content

Commit

Permalink
apps/speed.c: Lock buffer in memory
Browse files Browse the repository at this point in the history
Lock the buffers used for throughput measurements into memory.  This removes
some side effects of paging.

Errors from the memory locking functions are ignored since they are not
critical to the application.

This feature is limited to Linux and Windows.

Signed-off-by: Juergen Christ <[email protected]>

Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl#19091)
  • Loading branch information
juergenchrist authored and paulidale committed Sep 28, 2022
1 parent ac44dea commit 9710d72
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 11 deletions.
61 changes: 50 additions & 11 deletions apps/speed.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@

#if defined(_WIN32)
# include <windows.h>
/*
* While VirtualLock is available under the app partition (e.g. UWP),
* the headers do not define the API. Define it ourselves instead.
*/
WINBASEAPI
BOOL
WINAPI
VirtualLock(
_In_ LPVOID lpAddress,
_In_ SIZE_T dwSize
);
#endif

# if defined(OPENSSL_SYS_UNIX)
# include <sys/mman.h>
#endif

#include <openssl/bn.h>
Expand Down Expand Up @@ -111,6 +126,8 @@ static void print_result(int alg, int run_no, int count, double time_used);
static int do_multi(int multi, int size_num);
#endif

static int domlock = 0;

static const int lengths_list[] = {
16, 64, 256, 1024, 8 * 1024, 16 * 1024
};
Expand Down Expand Up @@ -212,7 +229,7 @@ typedef enum OPTION_choice {
OPT_COMMON,
OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG,
OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC
OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC, OPT_MLOCK
} OPTION_CHOICE;

const OPTIONS speed_options[] = {
Expand All @@ -238,6 +255,7 @@ const OPTIONS speed_options[] = {
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
{"mlock", OPT_MLOCK, '-', "Lock memory for better result determinism"},
OPT_CONFIG_OPTION,

OPT_SECTION("Selection"),
Expand Down Expand Up @@ -1625,6 +1643,15 @@ int speed_main(int argc, char **argv)
case OPT_AEAD:
aead = 1;
break;
case OPT_MLOCK:
domlock = 1;
#if !defined(_WIN32) && !defined(OPENSSL_SYS_LINUX)
BIO_printf(bio_err,
"%s: -mlock not supported on this platform\n",
prog);
goto end;
#endif
break;
}
}

Expand Down Expand Up @@ -1778,6 +1805,14 @@ int speed_main(int argc, char **argv)
app_malloc(loopargs_len * sizeof(loopargs_t), "array of loopargs");
memset(loopargs, 0, loopargs_len * sizeof(loopargs_t));

buflen = lengths[size_num - 1];
if (buflen < 36) /* size of random vector in RSA benchmark */
buflen = 36;
if (INT_MAX - (MAX_MISALIGNMENT + 1) < buflen) {
BIO_printf(bio_err, "Error: buffer size too large\n");
goto end;
}
buflen += MAX_MISALIGNMENT + 1;
for (i = 0; i < loopargs_len; i++) {
if (async_jobs > 0) {
loopargs[i].wait_ctx = ASYNC_WAIT_CTX_new();
Expand All @@ -1787,18 +1822,8 @@ int speed_main(int argc, char **argv)
}
}

buflen = lengths[size_num - 1];
if (buflen < 36) /* size of random vector in RSA benchmark */
buflen = 36;
if (INT_MAX - (MAX_MISALIGNMENT + 1) < buflen) {
BIO_printf(bio_err, "Error: buffer size too large\n");
goto end;
}
buflen += MAX_MISALIGNMENT + 1;
loopargs[i].buf_malloc = app_malloc(buflen, "input buffer");
loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer");
memset(loopargs[i].buf_malloc, 0, buflen);
memset(loopargs[i].buf2_malloc, 0, buflen);

/* Align the start of buffers on a 64 byte boundary */
loopargs[i].buf = loopargs[i].buf_malloc + misalign;
Expand All @@ -1818,6 +1843,20 @@ int speed_main(int argc, char **argv)
goto show_res;
#endif

for (i = 0; i < loopargs_len; ++i) {
if (domlock) {
#if defined(_WIN32)
(void)VirtualLock(loopargs[i].buf_malloc, buflen);
(void)VirtualLock(loopargs[i].buf2_malloc, buflen);
#elif defined(OPENSSL_SYS_LINUX)
(void)mlock(loopargs[i].buf_malloc, buflen);
(void)mlock(loopargs[i].buf_malloc, buflen);
#endif
}
memset(loopargs[i].buf_malloc, 0, buflen);
memset(loopargs[i].buf2_malloc, 0, buflen);
}

/* Initialize the engine after the fork */
e = setup_engine(engine_id, 0);

Expand Down
5 changes: 5 additions & 0 deletions doc/man1/openssl-speed.pod.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ B<openssl speed>
[B<-seconds> I<num>]
[B<-bytes> I<num>]
[B<-mr>]
[B<-mlock>]
{- $OpenSSL::safe::opt_r_synopsis -}
{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
[I<algorithm> ...]
Expand Down Expand Up @@ -115,6 +116,10 @@ int would be 2147483583 bytes.

Produce the summary in a mechanical, machine-readable, format.

=item B<-mlock>

Lock memory into RAM for more deterministic measurements.

{- $OpenSSL::safe::opt_r_item -}

{- $OpenSSL::safe::opt_engine_item -}
Expand Down

0 comments on commit 9710d72

Please sign in to comment.