Project

General

Profile

Actions

Feature #9814

closed

strndup() performs pathologically

Added by Robert Mustacchi over 5 years ago. Updated over 5 years ago.

Status:
Closed
Priority:
Normal
Category:
lib - userland libraries
Start date:
2018-09-09
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:
External Bug:

Description

In investigating why statemaps were slower on illumos than other platforms, it was clear that we were spending an inordinate amount of time in strndup. Take the following program:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

/*
 * Made global to prevent the compiler from just optimizing the call away.
 */
char *s;

int
main()
{
    size_t size = 10 * 1024 * 1024;
    int iter = 1000000;
    char *c = malloc(size);

    memset(c, '!', size - 1);
    c[size - 1] = '\0';

    while (iter--) {
        s = strndup(c, 3);
        free(s);
    }
}

On my Mac laptop (2.7 GHz Core i7):

$ time ./strndup 

real    0m0.084s
user    0m0.076s
sys    0m0.005s

On a 1U running SmartOS (3.5 GHz Haswell):

# time ./strndup

real    8m47.107s
user    8m47.051s
sys     0m0.140s

The problem is that strndup needless calls strlcpy to do the actual copying – which will always return (and therefore determine) the length of the source string even when it exceeds the buffer length. This is needless; this should be a bcopy with an explicit NUL byte termination instead.

Running with the fix:

[root@4e773eea-7527-ee67-90ba-de62e536c367 ~]# time ./strndup

real    0m0.051s
user    0m0.045s
sys     0m0.005s

I have also verified that the statemap code (which was the impetus for this) now runs with the expected performance.

Actions

Also available in: Atom PDF