Merge "Add musl benchmarks."
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index fae6f20..93f62cf 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -35,6 +35,7 @@
         "string_benchmark.cpp",
         "time_benchmark.cpp",
         "unistd_benchmark.cpp",
+        "stdlib_benchmark.cpp",
     ],
     shared_libs: ["libtinyxml2"],
     static_libs: [
diff --git a/benchmarks/bionic_benchmarks.cpp b/benchmarks/bionic_benchmarks.cpp
index f1ae4ff..1f362e3 100644
--- a/benchmarks/bionic_benchmarks.cpp
+++ b/benchmarks/bionic_benchmarks.cpp
@@ -306,21 +306,21 @@
 std::map<std::string, args_vector_t> GetShorthand() {
   std::map<std::string, args_vector_t> args_shorthand {
     {"AT_ALIGNED_TWOBUF", args_vector_t{ {8, 0, 0},
-                                       {64, 0, 0},
-                                       {512, 0, 0},
-                                       {1 * KB, 0, 0},
-                                       {8 * KB, 0, 0},
-                                       {16 * KB, 0, 0},
-                                       {32 * KB, 0, 0},
-                                       {64 * KB, 0, 0} }},
+                                         {64, 0, 0},
+                                         {512, 0, 0},
+                                         {1 * KB, 0, 0},
+                                         {8 * KB, 0, 0},
+                                         {16 * KB, 0, 0},
+                                         {32 * KB, 0, 0},
+                                         {64 * KB, 0, 0} }},
     {"AT_ALIGNED_ONEBUF", args_vector_t{ {(8), 0},
-                                           {(64), 0},
-                                           {(512), 0},
-                                           {(1*KB), 0},
-                                           {(8*KB), 0},
-                                           {(16*KB), 0},
-                                           {(32*KB), 0},
-                                           {(64*KB), 0}}},
+                                         {(64), 0},
+                                         {(512), 0},
+                                         {(1*KB), 0},
+                                         {(8*KB), 0},
+                                         {(16*KB), 0},
+                                         {(32*KB), 0},
+                                         {(64*KB), 0}}},
 
     {"AT_COMMON_SIZES", args_vector_t{ {8}, {64}, {512}, {1*KB}, {8*KB}, {16*KB},
                                                        {32*KB}, {64*KB}}},
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp
index 756a698..a1ca60e 100644
--- a/benchmarks/stdio_benchmark.cpp
+++ b/benchmarks/stdio_benchmark.cpp
@@ -63,9 +63,10 @@
 BIONIC_BENCHMARK(BM_stdio_fwrite_unbuffered);
 
 static void FopenFgetsFclose(benchmark::State& state, bool no_locking) {
-  char buf[1024];
+  size_t nbytes = state.range(0);
+  char buf[nbytes];
   while (state.KeepRunning()) {
-    FILE* fp = fopen("/proc/version", "re");
+    FILE* fp = fopen("/dev/zero", "re");
     if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
     if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
     fclose(fp);
@@ -81,3 +82,27 @@
   FopenFgetsFclose(state, true);
 }
 BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking);
+
+static void FopenFgetcFclose(benchmark::State& state, bool no_locking) {
+  size_t nbytes = state.range(0);
+  while (state.KeepRunning()) {
+    FILE* fp = fopen("/dev/zero", "re");
+    if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
+    volatile int c __attribute__((unused));
+    for (size_t i = 0; i < nbytes; ++i) {
+      c = fgetc(fp);
+    }
+    fclose(fp);
+  }
+}
+
+static void BM_stdio_fopen_fgetc_fclose_locking(benchmark::State& state) {
+  FopenFgetcFclose(state, false);
+}
+BIONIC_BENCHMARK(BM_stdio_fopen_fgetc_fclose_locking);
+
+void BM_stdio_fopen_fgetc_fclose_no_locking(benchmark::State& state) {
+  FopenFgetcFclose(state, true);
+}
+BIONIC_BENCHMARK(BM_stdio_fopen_fgetc_fclose_no_locking);
+
diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp
new file mode 100644
index 0000000..7a12eb6
--- /dev/null
+++ b/benchmarks/stdlib_benchmark.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <langinfo.h>
+#include <locale.h>
+#include <stdlib.h>
+
+#include <benchmark/benchmark.h>
+#include "util.h"
+
+static void BM_stdlib_malloc_free(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+
+  void* c;
+  while (state.KeepRunning()) {
+    c = malloc(nbytes);
+    free(c);
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BIONIC_BENCHMARK(BM_stdlib_malloc_free);
+
+static void BM_stdlib_mbstowcs(benchmark::State& state) {
+  const size_t buf_alignment = state.range(0);
+  const size_t widebuf_alignment = state.range(1);
+
+  std::vector<char> buf;
+  std::vector<wchar_t> widebuf;
+
+  setlocale(LC_CTYPE, "C.UTF-8")
+  || setlocale(LC_CTYPE, "en_US.UTF-8")
+  || setlocale(LC_CTYPE, "en_GB.UTF-8")
+  || setlocale(LC_CTYPE, "en.UTF-8")
+  || setlocale(LC_CTYPE, "de_DE-8")
+  || setlocale(LC_CTYPE, "fr_FR-8");
+  if (strcmp(nl_langinfo(CODESET), "UTF-8")) abort();
+
+  char* buf_aligned = GetAlignedPtr(&buf, buf_alignment, 500000);
+  wchar_t* widebuf_aligned = GetAlignedPtr(&widebuf, widebuf_alignment, 500000);
+  size_t i, j, k, l;
+  l = 0;
+  for (i=0xc3; i<0xe0; i++)
+    for (j=0x80; j<0xc0; j++)
+      buf[l++] = i, buf[l++] = j;
+  for (i=0xe1; i<0xed; i++)
+    for (j=0x80; j<0xc0; j++)
+      for (k=0x80; k<0xc0; k++)
+        buf[l++] = i, buf[l++] = j, buf[l++] = k;
+  for (i=0xf1; i<0xf4; i++)
+    for (j=0x80; j<0xc0; j++)
+      for (k=0x80; k<0xc0; k++)
+        buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k;
+  buf[l++] = 0;
+
+  volatile size_t c __attribute__((unused)) = 0;
+  while (state.KeepRunning()) {
+    c = mbstowcs(widebuf_aligned, buf_aligned, 500000);
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000));
+}
+BIONIC_BENCHMARK(BM_stdlib_mbstowcs);
+
+static void BM_stdlib_mbrtowc(benchmark::State& state) {
+  const size_t buf_alignment = state.range(0);
+
+  std::vector<char> buf;
+
+  setlocale(LC_CTYPE, "C.UTF-8")
+  || setlocale(LC_CTYPE, "en_US.UTF-8")
+  || setlocale(LC_CTYPE, "en_GB.UTF-8")
+  || setlocale(LC_CTYPE, "en.UTF-8")
+  || setlocale(LC_CTYPE, "de_DE-8")
+  || setlocale(LC_CTYPE, "fr_FR-8");
+  if (strcmp(nl_langinfo(CODESET), "UTF-8")) abort();
+
+  char* buf_aligned = GetAlignedPtr(&buf, buf_alignment, 500000);
+  size_t i, j, k, l;
+  l = 0;
+  for (i=0xc3; i<0xe0; i++)
+    for (j=0x80; j<0xc0; j++)
+      buf[l++] = i, buf[l++] = j;
+  for (i=0xe1; i<0xed; i++)
+    for (j=0x80; j<0xc0; j++)
+      for (k=0x80; k<0xc0; k++)
+        buf[l++] = i, buf[l++] = j, buf[l++] = k;
+  for (i=0xf1; i<0xf4; i++)
+    for (j=0x80; j<0xc0; j++)
+      for (k=0x80; k<0xc0; k++)
+        buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k;
+  buf[l++] = 0;
+
+  wchar_t wc = 0;
+  while (state.KeepRunning()) {
+    for (j = 0; buf_aligned[j]; j+=mbrtowc(&wc, buf_aligned + j, 4, NULL)) {
+    }
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000));
+}
+BIONIC_BENCHMARK(BM_stdlib_mbrtowc);
diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp
index 729b20d..94e7583 100644
--- a/benchmarks/string_benchmark.cpp
+++ b/benchmarks/string_benchmark.cpp
@@ -241,3 +241,49 @@
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
 }
 BIONIC_BENCHMARK(BM_string_strcmp);
+
+static void BM_string_strstr(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t haystack_alignment = state.range(1);
+  const size_t needle_alignment = state.range(2);
+
+  std::vector<char> haystack;
+  std::vector<char> needle;
+  char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
+  char* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment,
+                                             std::min(nbytes, static_cast<size_t>(5)), 'x');
+
+  if (nbytes / 4 > 2) {
+    for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) {
+      haystack_aligned[4 * i + 3] = 'y';
+    }
+  }
+  haystack_aligned[nbytes - 1] = '\0';
+  needle_aligned[needle.size() - 1] = '\0';
+
+  while (state.KeepRunning()) {
+    if (strstr(haystack_aligned, needle_aligned) == nullptr) {
+      abort();
+    }
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BIONIC_BENCHMARK(BM_string_strstr);
+
+static void BM_string_strchr(benchmark::State& state) {
+  const size_t nbytes = state.range(0);
+  const size_t haystack_alignment = state.range(1);
+
+  std::vector<char> haystack;
+  char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
+
+  while (state.KeepRunning()) {
+    if (strchr(haystack_aligned, 'y') != nullptr) {
+      abort();
+    }
+  }
+
+  state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
+}
+BIONIC_BENCHMARK(BM_string_strchr);
diff --git a/benchmarks/suites/full.xml b/benchmarks/suites/full.xml
index 707a3d6..8c9aef6 100644
--- a/benchmarks/suites/full.xml
+++ b/benchmarks/suites/full.xml
@@ -180,9 +180,19 @@
 </fn>
 <fn>
   <name>BM_stdio_fopen_fgets_fclose_locking</name>
+  <args>1024</args>
 </fn>
 <fn>
   <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_no_locking</name>
+  <args>1024</args>
 </fn>
 <fn>
   <name>BM_string_memcmp</name>
@@ -233,6 +243,14 @@
   <args>AT_ALIGNED_TWOBUF</args>
 </fn>
 <fn>
+  <name>BM_string_strstr</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strchr</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
   <name>BM_time_clock_gettime</name>
 </fn>
 <fn>
@@ -265,3 +283,15 @@
 <fn>
   <name>BM_unistd_gettid_syscall</name>
 </fn>
+<fn>
+  <name>BM_stdlib_malloc_free</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbstowcs</name>
+  <args>0 0</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbrtowc</name>
+  <args>0</args>
+</fn>
diff --git a/benchmarks/suites/host.xml b/benchmarks/suites/host.xml
index c4d0d3a..05769e9 100644
--- a/benchmarks/suites/host.xml
+++ b/benchmarks/suites/host.xml
@@ -160,9 +160,19 @@
 </fn>
 <fn>
   <name>BM_stdio_fopen_fgets_fclose_locking</name>
+  <args>1024</args>
 </fn>
 <fn>
   <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_no_locking</name>
+  <args>1024</args>
 </fn>
 <fn>
   <name>BM_string_memcmp</name>
@@ -213,6 +223,14 @@
   <args>AT_ALIGNED_TWOBUF</args>
 </fn>
 <fn>
+  <name>BM_string_strstr</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strchr</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
   <name>BM_time_clock_gettime</name>
 </fn>
 <fn>
@@ -242,3 +260,15 @@
 <fn>
   <name>BM_unistd_gettid_syscall</name>
 </fn>
+<fn>
+  <name>BM_stdlib_malloc_free</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbstowcs</name>
+  <args>0 0</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbrtowc</name>
+  <args>0</args>
+</fn>
diff --git a/benchmarks/suites/test_full.xml b/benchmarks/suites/test_full.xml
index f9d97ee..adc3f28 100644
--- a/benchmarks/suites/test_full.xml
+++ b/benchmarks/suites/test_full.xml
@@ -180,9 +180,19 @@
 </fn>
 <fn>
   <name>BM_stdio_fopen_fgets_fclose_locking</name>
+  <args>1024</args>
 </fn>
 <fn>
   <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_locking</name>
+  <args>1024</args>
+</fn>
+<fn>
+  <name>BM_stdio_fopen_fgetc_fclose_no_locking</name>
+  <args>1024</args>
 </fn>
 <fn>
   <name>BM_string_memcmp</name>
@@ -233,6 +243,14 @@
   <args>AT_ALIGNED_TWOBUF</args>
 </fn>
 <fn>
+  <name>BM_string_strstr</name>
+  <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+  <name>BM_string_strchr</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
   <name>BM_time_clock_gettime</name>
 </fn>
 <fn>
@@ -259,3 +277,15 @@
 <fn>
   <name>BM_unistd_gettid_syscall</name>
 </fn>
+<fn>
+  <name>BM_stdlib_malloc_free</name>
+  <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbstowcs</name>
+  <args>0 0</args>
+</fn>
+<fn>
+  <name>BM_stdlib_mbrtowc</name>
+  <args>0</args>
+</fn>
diff --git a/benchmarks/tests/interface_test.cpp b/benchmarks/tests/interface_test.cpp
index a9e3031..9283e6b 100644
--- a/benchmarks/tests/interface_test.cpp
+++ b/benchmarks/tests/interface_test.cpp
@@ -242,8 +242,10 @@
     "BM_stdio_fwrite_unbuffered/16384/iterations:1\n"
     "BM_stdio_fwrite_unbuffered/32768/iterations:1\n"
     "BM_stdio_fwrite_unbuffered/65536/iterations:1\n"
-    "BM_stdio_fopen_fgets_fclose_locking/iterations:1\n"
-    "BM_stdio_fopen_fgets_fclose_no_locking/iterations:1\n"
+    "BM_stdio_fopen_fgets_fclose_locking/1024/iterations:1\n"
+    "BM_stdio_fopen_fgets_fclose_no_locking/1024/iterations:1\n"
+    "BM_stdio_fopen_fgetc_fclose_locking/1024/iterations:1\n"
+    "BM_stdio_fopen_fgetc_fclose_no_locking/1024/iterations:1\n"
     "BM_string_memcmp/8/0/0/iterations:1\n"
     "BM_string_memcmp/64/0/0/iterations:1\n"
     "BM_string_memcmp/512/0/0/iterations:1\n"
@@ -340,6 +342,22 @@
     "BM_string_strcmp/16384/0/0/iterations:1\n"
     "BM_string_strcmp/32768/0/0/iterations:1\n"
     "BM_string_strcmp/65536/0/0/iterations:1\n"
+    "BM_string_strstr/8/0/0/iterations:1\n"
+    "BM_string_strstr/64/0/0/iterations:1\n"
+    "BM_string_strstr/512/0/0/iterations:1\n"
+    "BM_string_strstr/1024/0/0/iterations:1\n"
+    "BM_string_strstr/8192/0/0/iterations:1\n"
+    "BM_string_strstr/16384/0/0/iterations:1\n"
+    "BM_string_strstr/32768/0/0/iterations:1\n"
+    "BM_string_strstr/65536/0/0/iterations:1\n"
+    "BM_string_strchr/8/0/iterations:1\n"
+    "BM_string_strchr/64/0/iterations:1\n"
+    "BM_string_strchr/512/0/iterations:1\n"
+    "BM_string_strchr/1024/0/iterations:1\n"
+    "BM_string_strchr/8192/0/iterations:1\n"
+    "BM_string_strchr/16384/0/iterations:1\n"
+    "BM_string_strchr/32768/0/iterations:1\n"
+    "BM_string_strchr/65536/0/iterations:1\n"
     "BM_time_clock_gettime/iterations:1\n"
     "BM_time_clock_gettime_syscall/iterations:1\n"
     "BM_time_gettimeofday/iterations:1\n"
@@ -348,7 +366,17 @@
     "BM_unistd_getpid/iterations:1\n"
     "BM_unistd_getpid_syscall/iterations:1\n"
     "BM_unistd_gettid/iterations:1\n"
-    "BM_unistd_gettid_syscall/iterations:1\n";
+    "BM_unistd_gettid_syscall/iterations:1\n"
+    "BM_stdlib_malloc_free/8/0/iterations:1\n"
+    "BM_stdlib_malloc_free/64/0/iterations:1\n"
+    "BM_stdlib_malloc_free/512/0/iterations:1\n"
+    "BM_stdlib_malloc_free/1024/0/iterations:1\n"
+    "BM_stdlib_malloc_free/8192/0/iterations:1\n"
+    "BM_stdlib_malloc_free/16384/0/iterations:1\n"
+    "BM_stdlib_malloc_free/32768/0/iterations:1\n"
+    "BM_stdlib_malloc_free/65536/0/iterations:1\n"
+    "BM_stdlib_mbstowcs/0/0/iterations:1\n"
+    "BM_stdlib_mbrtowc/0/iterations:1\n";
   Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_full.xml",
                                                 "--bionic_iterations=1"});
 }
diff --git a/benchmarks/util.cpp b/benchmarks/util.cpp
index 9afca6f..0c7254c 100644
--- a/benchmarks/util.cpp
+++ b/benchmarks/util.cpp
@@ -16,9 +16,11 @@
 
 #include "util.h"
 
+#include <math.h>
 #include <sched.h>
 #include <stdio.h>
 #include <string.h>
+#include <wchar.h>
 
 #include <cstdlib>
 
@@ -49,6 +51,12 @@
   return GetAlignedMemory(buf->data(), alignment, 0);
 }
 
+wchar_t* GetAlignedPtr(std::vector<wchar_t>* buf, size_t alignment, size_t nchars) {
+  buf->resize(nchars + ceil((3 * alignment) / sizeof(wchar_t)));
+  return reinterpret_cast<wchar_t*>(GetAlignedMemory(reinterpret_cast<char*>(buf->data()),
+                                                     alignment, 0));
+}
+
 char* GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte) {
   char* buf_aligned = GetAlignedPtr(buf, alignment, nbytes);
   memset(buf_aligned, fill_byte, nbytes);
diff --git a/benchmarks/util.h b/benchmarks/util.h
index c8c39e3..cf6f50e 100644
--- a/benchmarks/util.h
+++ b/benchmarks/util.h
@@ -52,6 +52,8 @@
 
 char* GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes);
 
+wchar_t* GetAlignedPtr(std::vector<wchar_t>* buf, size_t alignment, size_t nbytes);
+
 char* GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte);
 
 bool LockToCPU(long cpu_to_lock);