kinetic-c  v0.12.0
Seagate Kinetic Protocol Client Library for C
test_threadpool_stress.c
Go to the documentation of this file.
1 /*
2 * kinetic-c
3 * Copyright (C) 2015 Seagate Technology.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <assert.h>
24 #include <err.h>
25 #include <poll.h>
26 #include <sys/time.h>
27 
28 #include "threadpool.h"
29 
30 /* Stress maximum throughput of no-op tasks */
31 
32 static size_t task_count = 0;
33 static size_t last_count = 0;
34 
35 static void dump_stats(const char *prefix, struct threadpool_info *stats, size_t ticks) {
36  size_t delta = task_count - last_count;
37  printf("%s -- %8ld thread tasks / sec -- (at %d, dt %d, bl %zd) -- delta %zd\n",
38  prefix, task_count / ticks,
39  stats->active_threads, stats->dormant_threads,
40  stats->backlog_size, delta);
41  last_count = task_count;
42 }
43 
44 #define ATOMIC_BOOL_COMPARE_AND_SWAP(PTR, OLD, NEW) \
45  (__sync_bool_compare_and_swap(PTR, OLD, NEW))
46 
47 /* Spin attempting to atomically adjust F by ADJ until successful */
48 #define SPIN_ADJ(F, ADJ) \
49  do { \
50  for (;;) { \
51  size_t v = F; \
52  if (ATOMIC_BOOL_COMPARE_AND_SWAP(&F, v, v + ADJ)) { \
53  break; \
54  } \
55  } \
56  } while (0)
57 
58 static size_t fibs(size_t arg) {
59  if (arg < 2) { return 1; }
60  return fibs(arg - 1) + fibs(arg - 2);
61 }
62 
63 static void task_cb(void *udata) {
64  SPIN_ADJ(task_count, 1);
65  (void)fibs;
66  (void)udata;
67  (void)task_count;
68 }
69 
70 int main(int argc, char **argv) {
71  uint8_t sz2 = 12;
72  uint8_t max_threads = 8;
73 
74  char *sz2_env = getenv("SZ2");
75  char *max_threads_env = getenv("MAX_THREADS");
76  if (sz2_env) { sz2 = atoi(sz2_env); }
77  if (max_threads_env) { max_threads = atoi(max_threads_env); }
78 
79  struct threadpool_config cfg = {
80  .task_ringbuf_size2 = sz2,
81  .max_threads = max_threads,
82  };
83  struct threadpool *t = Threadpool_Init(&cfg);
84  assert(t);
85 
86  struct threadpool_task task = {
87  .task = task_cb, .udata = t,
88  };
89 
90  struct threadpool_info stats;
91 
92  struct timeval tv;
93  gettimeofday(&tv, NULL);
94  time_t last_sec = tv.tv_sec;
95  size_t counterpressure = 0;
96  size_t ticks = 0;
97 
98  for (;;) {
99  gettimeofday(&tv, NULL);
100  if (tv.tv_sec > last_sec) {
101  last_sec = tv.tv_sec;
102  Threadpool_Stats(t, &stats);
103  ticks++;
104  dump_stats("tick...", &stats, ticks);
105  }
106 
107  /* Every 16 seconds, pause scheduling for 5 seconds to test
108  * thread sleep/wake-up alerts. */
109  if ((ticks & 15) == 0) {
110  sleep(5);
111  }
112 
113  for (size_t i = 0; i < 1000; i++) {
114  if (!Threadpool_Schedule(t, &task, &counterpressure)) {
115  size_t msec = i * 1000 * counterpressure;
116  usleep(msec >> 12);
117  } else {
118  break;
119  }
120  }
121  }
122 
123  return 0;
124 }
static size_t last_count
int main(int argc, char **argv)
static size_t task_count
size_t backlog_size
Definition: threadpool.h:58
threadpool_task_cb * task
Definition: threadpool.h:49
Configuration for thread pool.
Definition: threadpool.h:34
static size_t fibs(size_t arg)
Internal threadpool state.
uint8_t active_threads
Definition: threadpool.h:56
uint8_t task_ringbuf_size2
Definition: threadpool.h:35
#define SPIN_ADJ(F, ADJ)
struct threadpool * Threadpool_Init(struct threadpool_config *cfg)
Initialize a threadpool, according to a config.
Definition: threadpool.c:52
Statistics about the current state of the threadpool.
Definition: threadpool.h:55
A task.
Definition: threadpool.h:48
static void task_cb(void *udata)
static void dump_stats(const char *prefix, struct threadpool_info *stats, size_t ticks)
void Threadpool_Stats(struct threadpool *t, struct threadpool_info *info)
If TI is non-NULL, fill out some statistics about the operating state of the thread pool...
Definition: threadpool.c:149
uint8_t dormant_threads
Definition: threadpool.h:57
uint8_t max_threads
Definition: threadpool.h:37
bool Threadpool_Schedule(struct threadpool *t, struct threadpool_task *task, size_t *pushback)
Schedule a task in the threadpool.
Definition: threadpool.c:99