Open ndfred opened 5 years ago
Running Instruments (on a simulator) we see most time spent in:
12.5% in result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
in iperf_run_client
67.9% in r = write(fd, buf, nleft);
in Nwrite
iperf_new_stream
will create a temporary file but immediately delete it and mmaps that region to a buffer of 130kb. The test still runs if MAP_ANONYMOUS
is passed to mmap and the file descriptor is -1, which makes me think we can patch the source and avoid creating a file altogether.
The library uses JSON and might output quite a bit of text when running a test, maybe worth avoiding, though profiling suggests otherwise, and that code is needed to properly function as a server eventually
Analysing the data used for profile guided optimisations with llvm-profdata show -topn=50 iperf.profdata
, these are the top called methods, we see quite a bit of JSON activity which we could get rid of:
Top 50 functions with the largest internal block counts: iperf_recv, max count = 479940 iperf_api.c:darwin_fd_isset, max count = 479940 Nread, max count = 355048 timer.c:getnow, max count = 193583 iperf_tcp_recv, max count = 100847 tmr_timeout, max count = 97594 iperf_run_client, max count = 97594 iperf_client_api.c:darwin_fd_isset, max count = 97579 tmr_run, max count = 96047 cjson.c:print_string_ptr, max count = 404 cjson.c:case_insensitive_strcmp, max count = 327 cjson.c:parse_string, max count = 291 cjson.c:ensure, max count = 231 cjson.c:print_number, max count = 223 cjson.c:get_object_item, max count = 185 timeval_diff, max count = 160 cjson.c:buffer_skip_whitespace, max count = 158 iperf_stats_callback, max count = 150 iperf_free_stream, max count = 150 add_to_interval_list, max count = 150 has_tcpinfo, max count = 150 IPFTestRunner.m:-[IPFTestRunner handleStatsCallback:], max count = 150 cjson.c:parse_number, max count = 139 cJSON_AddItemToArray, max count = 138 cjson.c:update_offset, max count = 113 cjson.c:cJSON_New_Item, max count = 101 cJSON_Delete, max count = 101 cjson.c:get_decimal_point, max count = 83 timer.c:list_add, max count = 63 timer.c:list_remove, max count = 63 timer.c:add_usecs, max count = 63 cjson.c:print_value, max count = 60 timer.c:list_resort, max count = 60 cjson.c:cJSON_strdup, max count = 54 cJSON_AddItemToObject, max count = 53 cJSON_AddItemToObjectCS, max count = 53 cjson.c:print_object, max count = 53 cjson.c:suffix_object, max count = 50 cJSON_CreateNumber, max count = 49 cJSON_GetObjectItem, max count = 46 cjson.c:parse_value, max count = 41 make_cookie, max count = 36 cjson.c:parse_object, max count = 35 IPFTestRunner.m:dispatch_get_main_queue, max count = 31 IPFTestRunnerViewController.m:40-[IPFTestRunnerViewController startTest]_block_invoke.126, max count = 31 IPFTestRunner.m:vc_reporter_callback, max count = 30 iperf_client_api.c:client_stats_timer_proc, max count = 30 IPFTestRunner.m:vc_reporter_callback_block_invoke, max count = 30 iperf_client_api.c:client_reporter_timer_proc, max count = 30 iperf_api.c:get_results, max count = 15
Actually the iPerf protocol uses JSON which is why we are seeing so much of it, not a big deal
There are a few tricks on the iperf3 at 40Gbps and above page that could apply to tests on mobile devices too:
sendfile
(-Z) instead of read / write system calls might reduce CPU overhead (see disk testing)