From b11567ed9bf47688369fec2cf4884082790c43c4 Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Mon, 29 Aug 2011 20:13:24 +0300 Subject: benchmarks: refactoring + sync sftp tests no surprise, sync sftp is much slower, even for localhost, especially for download. --- tests/benchmarks/CMakeLists.txt | 2 +- tests/benchmarks/bench_raw.c | 11 ++- tests/benchmarks/bench_scp.c | 131 +++++++++++++++++++++++++++++++++- tests/benchmarks/bench_sftp.c | 152 ++++++++++++++++++++++++++++++++++++++++ tests/benchmarks/benchmarks.c | 105 +++++++++++++++++++++------ tests/benchmarks/benchmarks.h | 27 ++++++- 6 files changed, 401 insertions(+), 27 deletions(-) create mode 100644 tests/benchmarks/bench_sftp.c (limited to 'tests/benchmarks') diff --git a/tests/benchmarks/CMakeLists.txt b/tests/benchmarks/CMakeLists.txt index 02488bd9..8dc8552f 100644 --- a/tests/benchmarks/CMakeLists.txt +++ b/tests/benchmarks/CMakeLists.txt @@ -1,7 +1,7 @@ project(libssh-benchmarks C) set(benchmarks_SRCS - bench_scp.c bench_raw.c benchmarks.c latency.c + bench_scp.c bench_sftp bench_raw.c benchmarks.c latency.c ) include_directories( diff --git a/tests/benchmarks/bench_raw.c b/tests/benchmarks/bench_raw.c index 62e1055d..579ad08e 100644 --- a/tests/benchmarks/bench_raw.c +++ b/tests/benchmarks/bench_raw.c @@ -189,11 +189,16 @@ const char python_giver[] = "r=sys.stdin.read(2)\n" "towrite=XXXXXXXXXX\n" "wrote=0\n" +"mtu = 32786\n" +"buf = 'A'*mtu\n" "while(wrote < towrite):\n" " buffersize=towrite-wrote\n" -" if(buffersize > 4096):\n" -" buffersize=4096\n" -" sys.stdout.write('A'*buffersize)\n" +" if(buffersize > mtu):\n" +" buffersize=mtu\n" +" if(buffersize == mtu):\n" +" sys.stdout.write(buf)\n" +" else:\n" +" sys.stdout.write('A'*buffersize)\n" " wrote+=buffersize\n" "sys.stdout.flush()\n"; diff --git a/tests/benchmarks/bench_scp.c b/tests/benchmarks/bench_scp.c index 3ef3bbfc..3e0a7c00 100644 --- a/tests/benchmarks/bench_scp.c +++ b/tests/benchmarks/bench_scp.c @@ -2,7 +2,7 @@ * * This file is part of the SSH Library * - * Copyright (c) 2010 by Aris Adamantiadis + * Copyright (c) 2011 by Aris Adamantiadis * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -22,4 +22,133 @@ #include "benchmarks.h" #include +#include +#define SCPDIR "/tmp/" +#define SCPFILE "scpbenchmark" + +/** @internal + * @brief benchmarks a scp upload using an + * existing SSH session. + * @param[in] session Open SSH session + * @param[in] args Parsed command line arguments + * @param[out] bps The calculated bytes per second obtained via benchmark. + * @return 0 on success, -1 on error. + */ +int benchmarks_scp_up (ssh_session session, struct argument_s *args, + float *bps){ + unsigned long bytes=0x1000000; + static char buffer[0x10000]; + struct timestamp_struct ts; + float ms=0.0; + unsigned long total=0; + ssh_scp scp; + + if(args->data != 0) + bytes = args->data * 1024 * 1024; + scp = ssh_scp_new(session,SSH_SCP_WRITE,SCPDIR); + if(scp == NULL) + goto error; + if(ssh_scp_init(scp)==SSH_ERROR) + goto error; + if(ssh_scp_push_file(scp,SCPFILE,bytes,0777) != SSH_OK) + goto error; + if(args->verbose>0) + fprintf(stdout,"Starting upload of %lu bytes now\n",bytes); + timestamp_init(&ts); + while(total < bytes){ + unsigned long towrite = bytes - total; + int w; + if(towrite > 32758) + towrite = 32758; + w=ssh_scp_write(scp,buffer,towrite); + if(w == SSH_ERROR) + goto error; + total += towrite; + } + ms=elapsed_time(&ts); + *bps=8000 * (float)bytes / ms; + if(args->verbose > 0) + fprintf(stdout,"Upload took %f ms for %lu bytes, at %f bps\n",ms, + bytes,*bps); + ssh_scp_close(scp); + ssh_scp_free(scp); + return 0; +error: + fprintf(stderr,"Error during scp upload : %s\n",ssh_get_error(session)); + if(scp){ + ssh_scp_close(scp); + ssh_scp_free(scp); + } + return -1; +} + +/** @internal + * @brief benchmarks a scp download using an + * existing SSH session. + * @param[in] session Open SSH session + * @param[in] args Parsed command line arguments + * @param[out] bps The calculated bytes per second obtained via benchmark. + * @return 0 on success, -1 on error. + */ +int benchmarks_scp_down (ssh_session session, struct argument_s *args, + float *bps){ + unsigned long bytes=0x1000000; + static char buffer[0x10000]; + struct timestamp_struct ts; + float ms=0.0; + unsigned long total=0; + ssh_scp scp; + int r; + size_t size; + + if(args->data != 0) + bytes = args->data * 1024 * 1024; + scp = ssh_scp_new(session,SSH_SCP_READ,SCPDIR SCPFILE); + if(scp == NULL) + goto error; + if(ssh_scp_init(scp)==SSH_ERROR) + goto error; + r=ssh_scp_pull_request(scp); + if(r == SSH_SCP_REQUEST_NEWFILE){ + size=ssh_scp_request_get_size(scp); + if(bytes > size){ + printf("Only %d bytes available (on %lu requested).\n",size,bytes); + bytes = size; + } + if(size > bytes){ + printf("File is %d bytes (on %lu requested). Will cut the end\n",size,bytes); + } + if(args->verbose>0) + fprintf(stdout,"Starting download of %lu bytes now\n",bytes); + timestamp_init(&ts); + ssh_scp_accept_request(scp); + while(total < bytes){ + unsigned long toread = bytes - total; + if(toread > sizeof(buffer)) + toread = sizeof(buffer); + r=ssh_scp_read(scp,buffer,toread); + if(r == SSH_ERROR || r == 0) + goto error; + total += r; + } + ms=elapsed_time(&ts); + *bps=8000 * (float)bytes / ms; + if(args->verbose > 0) + fprintf(stdout,"download took %f ms for %lu bytes, at %f bps\n",ms, + bytes,*bps); + } else { + fprintf(stderr,"Expected SSH_SCP_REQUEST_NEWFILE, got %d\n",r); + goto error; + } + ssh_scp_close(scp); + ssh_scp_free(scp); + return 0; +error: + fprintf(stderr,"Error during scp download : %s\n",ssh_get_error(session)); + if(scp){ + ssh_scp_close(scp); + ssh_scp_free(scp); + } + return -1; +} diff --git a/tests/benchmarks/bench_sftp.c b/tests/benchmarks/bench_sftp.c new file mode 100644 index 00000000..915d1b7a --- /dev/null +++ b/tests/benchmarks/bench_sftp.c @@ -0,0 +1,152 @@ +/* bench_sftp.c + * + * This file is part of the SSH Library + * + * Copyright (c) 2011 by Aris Adamantiadis + * + * The SSH Library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The SSH Library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the SSH Library; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#include "benchmarks.h" +#include +#include +#include +#include + +#define SFTPDIR "/tmp/" +#define SFTPFILE "scpbenchmark" + +/** @internal + * @brief benchmarks a synchronous sftp upload using an + * existing SSH session. + * @param[in] session Open SSH session + * @param[in] args Parsed command line arguments + * @param[out] bps The calculated bytes per second obtained via benchmark. + * @return 0 on success, -1 on error. + */ +int benchmarks_sync_sftp_up (ssh_session session, struct argument_s *args, + float *bps){ + unsigned long bytes=0x1000000; + static char buffer[0x10000]; + struct timestamp_struct ts; + float ms=0.0; + unsigned long total=0; + sftp_session sftp; + sftp_file file; + + if(args->data != 0) + bytes = args->data * 1024 * 1024; + sftp = sftp_new(session); + if(sftp == NULL) + goto error; + if(sftp_init(sftp)==SSH_ERROR) + goto error; + file = sftp_open(sftp,SFTPDIR SFTPFILE,O_RDWR | O_CREAT | O_TRUNC, 0777); + if(!file) + goto error; + if(args->verbose>0) + fprintf(stdout,"Starting upload of %lu bytes now\n",bytes); + timestamp_init(&ts); + while(total < bytes){ + unsigned long towrite = bytes - total; + int w; + if(towrite > 32758) + towrite = 32758; + w=sftp_write(file,buffer,towrite); + if(w == SSH_ERROR) + goto error; + total += w; + } + sftp_close(file); + ms=elapsed_time(&ts); + *bps=8000 * (float)bytes / ms; + if(args->verbose > 0) + fprintf(stdout,"Upload took %f ms for %lu bytes, at %f bps\n",ms, + bytes,*bps); + sftp_free(sftp); + return 0; +error: + fprintf(stderr,"Error during scp upload : %s\n",ssh_get_error(session)); + if(file) + sftp_close(file); + if(sftp) + sftp_free(sftp); + return -1; +} + +/** @internal + * @brief benchmarks a synchronous sftp download using an + * existing SSH session. + * @param[in] session Open SSH session + * @param[in] args Parsed command line arguments + * @param[out] bps The calculated bytes per second obtained via benchmark. + * @return 0 on success, -1 on error. + */ +int benchmarks_sync_sftp_down (ssh_session session, struct argument_s *args, + float *bps){ + unsigned long bytes=0x1000000; + static char buffer[0x10000]; + struct timestamp_struct ts; + float ms=0.0; + unsigned long total=0; + sftp_session sftp; + sftp_file file; + int r; + + if(args->data != 0) + bytes = args->data * 1024 * 1024; + sftp = sftp_new(session); + if(sftp == NULL) + goto error; + if(sftp_init(sftp)==SSH_ERROR) + goto error; + file = sftp_open(sftp,SFTPDIR SFTPFILE,O_RDONLY,0); + if(!file) + goto error; + if(args->verbose>0) + fprintf(stdout,"Starting download of %lu bytes now\n",bytes); + timestamp_init(&ts); + while(total < bytes){ + unsigned long toread = bytes - total; + if(toread > sizeof(buffer)) + toread = sizeof(buffer); + r=sftp_read(file,buffer,toread); + if(r == SSH_ERROR) + goto error; + total += r; + /* we had a smaller file */ + if(r==0){ + fprintf(stdout,"File smaller than expected : %lu (expected %lu).\n",total,bytes); + bytes = total; + break; + } + } + sftp_close(file); + ms=elapsed_time(&ts); + *bps=8000 * (float)bytes / ms; + if(args->verbose > 0) + fprintf(stdout,"download took %f ms for %lu bytes, at %f bps\n",ms, + bytes,*bps); + sftp_free(sftp); + return 0; +error: + fprintf(stderr,"Error during sftp download : %s\n",ssh_get_error(session)); + if(file) + sftp_close(file); + if(sftp) + sftp_free(sftp); + return -1; +} diff --git a/tests/benchmarks/benchmarks.c b/tests/benchmarks/benchmarks.c index 0dd0d0df..3ee57b0d 100644 --- a/tests/benchmarks/benchmarks.c +++ b/tests/benchmarks/benchmarks.c @@ -27,15 +27,43 @@ #include #include -const char *libssh_benchmarks_names[]={ - "benchmark_raw_upload", - "benchmark_raw_download" +struct benchmark benchmarks[]= { + { + .name="benchmark_raw_upload", + .fct=benchmarks_raw_up, + .enabled=0 + }, + { + .name="benchmark_raw_download", + .fct=benchmarks_raw_down, + .enabled=0 + }, + { + .name="benchmark_scp_upload", + .fct=benchmarks_scp_up, + .enabled=0 + }, + { + .name="benchmark_scp_download", + .fct=benchmarks_scp_down, + .enabled=0 + }, + { + .name="benchmark_sync_sftp_upload", + .fct=benchmarks_sync_sftp_up, + .enabled=0 + }, + { + .name="benchmark_sync_sftp_download", + .fct=benchmarks_sync_sftp_down, + .enabled=0 + } }; #ifdef HAVE_ARGP_H #include -const char *argp_program_version = "libssh benchmarks 2010-12-28"; +const char *argp_program_version = "libssh benchmarks 2011-08-28"; const char *argp_program_bug_address = "Aris Adamantiadis "; static char **cmdline; @@ -70,6 +98,40 @@ static struct argp_option options[] = { .doc = "Download raw data using channel", .group = 0 }, + { + .name = "scp-upload", + .key = '3', + .arg = NULL, + .flags = 0, + .doc = "Upload data using SCP", + .group = 0 + }, + { + .name = "scp-download", + .key = '4', + .arg = NULL, + .flags = 0, + .doc = "Download data using SCP", + .group = 0 + }, + { + .name = "sync-sftp-upload", + .key = '5', + .arg = NULL, + .flags = 0, + .doc = "Upload data using synchronous SFTP", + .group = 0 + + }, + { + .name = "sync-sftp-download", + .key = '6', + .arg = NULL, + .flags = 0, + .doc = "Download data using synchronous SFTP", + .group = 0 + + }, { .name = "host", .key = 'h', @@ -102,7 +164,11 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) { switch (key) { case '1': case '2': - arguments->benchmarks[key - '1'] = 1; + case '3': + case '4': + case '5': + case '6': + benchmarks[key - '1'].enabled = 1; arguments->ntests ++; break; case 'v': @@ -193,7 +259,9 @@ static void do_benchmarks(ssh_session session, struct argument_s *arguments, float ping_rtt=0.0; float ssh_rtt=0.0; float bps=0.0; + int i; int err; + struct benchmark *b; if(arguments->verbose>0) fprintf(stdout,"Testing ICMP RTT\n"); @@ -205,18 +273,13 @@ static void do_benchmarks(ssh_session session, struct argument_s *arguments, if(err==0){ fprintf(stdout, "SSH RTT : %f ms\n",ssh_rtt); } - if(arguments->benchmarks[BENCHMARK_RAW_UPLOAD]){ - err=benchmarks_raw_up(session,arguments,&bps); - if(err==0){ - fprintf(stdout, "%s : %s : %s\n",hostname, - libssh_benchmarks_names[BENCHMARK_RAW_UPLOAD], network_speed(bps)); - } - } - if(arguments->benchmarks[BENCHMARK_RAW_DOWNLOAD]){ - err=benchmarks_raw_down(session,arguments,&bps); - if(err==0){ - fprintf(stdout, "%s : %s : %s\n",hostname, - libssh_benchmarks_names[BENCHMARK_RAW_DOWNLOAD], network_speed(bps)); + for (i=0 ; ienabled){ + err=b->fct(session,arguments,&bps); + if(err==0){ + fprintf(stdout, "%s : %s : %s\n",hostname, b->name, network_speed(bps)); + } } } } @@ -234,7 +297,7 @@ int main(int argc, char **argv){ } if (arguments.ntests==0){ for(i=0; i < BENCHMARK_NUMBER ; ++i){ - arguments.benchmarks[i]=1; + benchmarks[i].enabled=1; } arguments.ntests=BENCHMARK_NUMBER; } @@ -245,8 +308,8 @@ int main(int argc, char **argv){ } fprintf(stdout,"with benchmarks "); for(i=0;i 0) fprintf(stdout,"Success\n"); if(session == NULL){ - fprintf(stderr,"Errors occured, stopping\n"); + fprintf(stderr,"Errors occurred, stopping\n"); return EXIT_FAILURE; } do_benchmarks(session, &arguments, arguments.hosts[i]); diff --git a/tests/benchmarks/benchmarks.h b/tests/benchmarks/benchmarks.h index ffa1bfae..4aba1431 100644 --- a/tests/benchmarks/benchmarks.h +++ b/tests/benchmarks/benchmarks.h @@ -32,18 +32,30 @@ enum libssh_benchmarks { BENCHMARK_RAW_UPLOAD=0, BENCHMARK_RAW_DOWNLOAD, + BENCHMARK_SCP_UPLOAD, + BENCHMARK_SCP_DOWNLOAD, + BENCHMARK_SYNC_SFTP_UPLOAD, + BENCHMARK_SYNC_SFTP_DOWNLOAD, BENCHMARK_NUMBER }; struct argument_s { const char *hosts[MAX_HOSTS_CONNECT]; - char benchmarks[BENCHMARK_NUMBER]; int verbose; int nhosts; int ntests; int data; }; +typedef int (*bench_fct)(ssh_session session, struct argument_s *args, + float *bps); + +struct benchmark { + const char *name; + bench_fct fct; + int enabled; +}; + /* latency.c */ struct timestamp_struct { @@ -63,4 +75,17 @@ int benchmarks_raw_up (ssh_session session, struct argument_s *args, int benchmarks_raw_down (ssh_session session, struct argument_s *args, float *bps); +/* bench_scp.c */ + +int benchmarks_scp_up (ssh_session session, struct argument_s *args, + float *bps); +int benchmarks_scp_down (ssh_session session, struct argument_s *args, + float *bps); + +/* bench_sftp.c */ + +int benchmarks_sync_sftp_up (ssh_session session, struct argument_s *args, + float *bps); +int benchmarks_sync_sftp_down (ssh_session session, struct argument_s *args, + float *bps); #endif /* BENCHMARKS_H_ */ -- cgit v1.2.3