MarketSquare / SSHLibrary

Robot Framework test library for SSH and SFTP
http://marketsquare.github.io/SSHLibrary/
Other
158 stars 139 forks source link

Read until very slow comparing to Paramiko #425

Closed michalwitwicki closed 2 months ago

michalwitwicki commented 1 year ago

Hi, I have similar (or same) issue as discussed in following tickets: #338, #347, #151 and #203 - basically Read Until is slow.

I have created setup to compare Read Until directly to Paramiko, that comparison is not exactly 1-to-1 but I think it is enough to show the problem.

requirements.txt

bcrypt==4.0.1
cffi==1.15.1
cryptography==39.0.0
paramiko==2.12.0
pycparser==2.21
PyNaCl==1.5.0
robotframework==6.0.2
robotframework-sshlibrary==3.8.0
scp==0.14.4
six==1.16.0

long_output.sh

#!/bin/bash
for i in {1..10000}
do
   echo "$i. long output long output long output"
done
echo "DONE"

long_output.robot

*** Settings ***
Library                SSHLibrary
Library                utils.py

*** Variables ***
${HOST}                
${USERNAME}            
${PASSWORD}            

*** Test Cases ***
Send file
    Open Connection     ${HOST}            timeout=120
    Login               ${USERNAME}        ${PASSWORD}
    Put File            ./long_output.sh   /root/
    Close All Connections

Paramiko test
    paramiko_write      cd /root && time ./long_output.sh    ${HOST}    ${USERNAME}    ${PASSWORD}

SSHLibrary test
    Open Connection     ${HOST}            timeout=120
    Login               ${USERNAME}        ${PASSWORD}
    Write               cd /root && time ./long_output.sh
    Read Until          DONE     
    Close All Connections

utils.py

import paramiko
from robot.api.deco import keyword, library
import robot.api.logger as logger

@library(scope='GLOBAL')
class utils:
    @keyword
    def paramiko_write(self, cmd, host, username, password):
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(host, 22, username, password, timeout=10)

        stdin, stdout, stderr = ssh.exec_command(cmd)

        output = []
        for line in stdout.readlines():
            logger.info(line)
            output.append(line)

        ssh.close()

        return "\n".join(output)

This is how I started Robot: robot -d ./results -v HOST:<ip> -v USERNAME:<user> -v PASSWORD:<pass> long_output.robot

And finally the result of running above: Zrzut ekranu 2023-02-09 152241

I am running this from virtual machine with Fedora and machine I am connecting to has CentOS. I am using Python3.

All files to download: shhlib_slow_read_until.zip

Any idea where problem might be?

Thanks, Michał Witwicki

raychenv commented 1 year ago

Check commit https://github.com/robotframework/SSHLibrary/commit/8e77942557e704dfb13ae9ee6eb1365791999a87 The bottleneck may be here in _read_until. self.read_char reads only a character each loop. And need match every output. It is really time consuming for long output.

Should use Execute Command keyword to get the output and check.

michalwitwicki commented 1 year ago

@raychenv Thanks for explanation. Execute Command is indeed much faster but still not as fast as paramiko approach. Thank you for suggestion anyway.