1 1.1 christos /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 1.1 christos * 3 1.1 christos * Permission is hereby granted, free of charge, to any person obtaining a copy 4 1.1 christos * of this software and associated documentation files (the "Software"), to 5 1.1 christos * deal in the Software without restriction, including without limitation the 6 1.1 christos * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 1.1 christos * sell copies of the Software, and to permit persons to whom the Software is 8 1.1 christos * furnished to do so, subject to the following conditions: 9 1.1 christos * 10 1.1 christos * The above copyright notice and this permission notice shall be included in 11 1.1 christos * all copies or substantial portions of the Software. 12 1.1 christos * 13 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 1.1 christos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 1.1 christos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 1.1 christos * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 1.1 christos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 1.1 christos * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 1.1 christos * IN THE SOFTWARE. 20 1.1 christos */ 21 1.1 christos 22 1.1 christos #include "uv.h" 23 1.1 christos #include "task.h" 24 1.1 christos 25 1.1 christos #include <stdio.h> 26 1.1 christos #include <stdlib.h> 27 1.1 christos 28 1.1 christos #define WRITE_REQ_DATA "Hello, world." 29 1.1 christos #define NUM_WRITE_REQS (1000 * 1000) 30 1.1 christos 31 1.1 christos typedef struct { 32 1.1 christos uv_write_t req; 33 1.1 christos uv_buf_t buf; 34 1.1 christos } write_req; 35 1.1 christos 36 1.1 christos 37 1.1 christos static write_req* write_reqs; 38 1.1 christos static uv_tcp_t tcp_client; 39 1.1 christos static uv_connect_t connect_req; 40 1.1 christos static uv_shutdown_t shutdown_req; 41 1.1 christos 42 1.1 christos static int shutdown_cb_called = 0; 43 1.1 christos static int connect_cb_called = 0; 44 1.1 christos static int write_cb_called = 0; 45 1.1 christos static int close_cb_called = 0; 46 1.1 christos 47 1.1 christos static void connect_cb(uv_connect_t* req, int status); 48 1.1 christos static void write_cb(uv_write_t* req, int status); 49 1.1 christos static void shutdown_cb(uv_shutdown_t* req, int status); 50 1.1 christos static void close_cb(uv_handle_t* handle); 51 1.1 christos 52 1.1 christos 53 1.1 christos static void connect_cb(uv_connect_t* req, int status) { 54 1.1 christos write_req* w; 55 1.1 christos int i; 56 1.1 christos int r; 57 1.1 christos 58 1.1 christos ASSERT(req->handle == (uv_stream_t*)&tcp_client); 59 1.1 christos 60 1.1 christos for (i = 0; i < NUM_WRITE_REQS; i++) { 61 1.1 christos w = &write_reqs[i]; 62 1.1 christos r = uv_write(&w->req, req->handle, &w->buf, 1, write_cb); 63 1.1 christos ASSERT(r == 0); 64 1.1 christos } 65 1.1 christos 66 1.1 christos r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb); 67 1.1 christos ASSERT(r == 0); 68 1.1 christos 69 1.1 christos connect_cb_called++; 70 1.1 christos } 71 1.1 christos 72 1.1 christos 73 1.1 christos static void write_cb(uv_write_t* req, int status) { 74 1.1.1.2 christos ASSERT_NOT_NULL(req); 75 1.1 christos ASSERT(status == 0); 76 1.1 christos write_cb_called++; 77 1.1 christos } 78 1.1 christos 79 1.1 christos 80 1.1 christos static void shutdown_cb(uv_shutdown_t* req, int status) { 81 1.1 christos ASSERT(req->handle == (uv_stream_t*)&tcp_client); 82 1.1 christos ASSERT(req->handle->write_queue_size == 0); 83 1.1 christos 84 1.1 christos uv_close((uv_handle_t*)req->handle, close_cb); 85 1.1 christos free(write_reqs); 86 1.1 christos 87 1.1 christos shutdown_cb_called++; 88 1.1 christos } 89 1.1 christos 90 1.1 christos 91 1.1 christos static void close_cb(uv_handle_t* handle) { 92 1.1 christos ASSERT(handle == (uv_handle_t*)&tcp_client); 93 1.1 christos close_cb_called++; 94 1.1 christos } 95 1.1 christos 96 1.1 christos 97 1.1 christos BENCHMARK_IMPL(tcp_write_batch) { 98 1.1 christos struct sockaddr_in addr; 99 1.1 christos uv_loop_t* loop; 100 1.1 christos uint64_t start; 101 1.1 christos uint64_t stop; 102 1.1 christos int i; 103 1.1 christos int r; 104 1.1 christos 105 1.1 christos write_reqs = malloc(sizeof(*write_reqs) * NUM_WRITE_REQS); 106 1.1.1.2 christos ASSERT_NOT_NULL(write_reqs); 107 1.1 christos 108 1.1 christos /* Prepare the data to write out. */ 109 1.1 christos for (i = 0; i < NUM_WRITE_REQS; i++) { 110 1.1 christos write_reqs[i].buf = uv_buf_init(WRITE_REQ_DATA, 111 1.1 christos sizeof(WRITE_REQ_DATA) - 1); 112 1.1 christos } 113 1.1 christos 114 1.1 christos loop = uv_default_loop(); 115 1.1 christos ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); 116 1.1 christos 117 1.1 christos r = uv_tcp_init(loop, &tcp_client); 118 1.1 christos ASSERT(r == 0); 119 1.1 christos 120 1.1 christos r = uv_tcp_connect(&connect_req, 121 1.1 christos &tcp_client, 122 1.1 christos (const struct sockaddr*) &addr, 123 1.1 christos connect_cb); 124 1.1 christos ASSERT(r == 0); 125 1.1 christos 126 1.1 christos start = uv_hrtime(); 127 1.1 christos 128 1.1 christos r = uv_run(loop, UV_RUN_DEFAULT); 129 1.1 christos ASSERT(r == 0); 130 1.1 christos 131 1.1 christos stop = uv_hrtime(); 132 1.1 christos 133 1.1 christos ASSERT(connect_cb_called == 1); 134 1.1 christos ASSERT(write_cb_called == NUM_WRITE_REQS); 135 1.1 christos ASSERT(shutdown_cb_called == 1); 136 1.1 christos ASSERT(close_cb_called == 1); 137 1.1 christos 138 1.1 christos printf("%ld write requests in %.2fs.\n", 139 1.1 christos (long)NUM_WRITE_REQS, 140 1.1 christos (stop - start) / 1e9); 141 1.1 christos 142 1.1 christos MAKE_VALGRIND_HAPPY(); 143 1.1 christos return 0; 144 1.1 christos } 145