Skip to content

Pure Python SMB client benchmarking

Robin Wilson edited this page Apr 22, 2020 · 10 revisions

Using smbprotocol:

------------------------------------------------------------------------------------------------ benchmark: 4 tests -----------------------------------------------------------------------------------------------
Name (time in ms)                    Min                    Max                   Mean                StdDev                Median                   IQR            Outliers      OPS          Rounds  Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_mkdir                       27.1690 (1.0)         118.0649 (1.72)         37.9165 (1.0)         16.8438 (2.02)        31.4735 (1.0)          7.8783 (1.0)           3;5  26.3737 (1.0)          35           1
test_short_string_write          38.3419 (1.41)         68.6655 (1.0)          48.0369 (1.27)         8.3455 (1.0)         45.8934 (1.46)        11.2189 (1.42)          5;0  20.8174 (0.79)         16           1
test_copy_larger_file           976.3894 (35.94)     1,233.0581 (17.96)     1,141.1065 (30.10)       90.0268 (10.79)    1,163.5137 (36.97)      133.9724 (17.01)         3;0   0.8763 (0.03)         10           1
test_copy_very_large_file     9,398.3793 (345.92)   12,569.7552 (183.06)   10,155.2101 (267.83)   1,106.6363 (132.60)   9,604.7380 (305.17)   1,188.5017 (150.86)        2;1   0.0985 (0.00)         10           1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Using pysmb:

--------------------------------------------------------------------------------------------- benchmark: 3 tests --------------------------------------------------------------------------------------------
Name (time in ms)                    Min                   Max                  Mean              StdDev                Median                 IQR            Outliers      OPS    Rounds  Iterations
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_short_string_write          30.7420 (1.0)         80.7924 (1.0)         43.7129 (1.0)       13.1190 (1.0)         41.5045 (1.0)       11.4453 (1.0)           3;2  22.8765 (1.0)        17           1
test_copy_larger_file           845.4560 (27.50)      980.0222 (12.13)      894.2136 (20.46)     42.2219 (3.22)       876.1998 (21.11)     53.6339 (4.69)          2;0   1.1183 (0.05)        10           1
test_copy_very_large_file     7,957.6078 (258.85)   9,354.0760 (115.78)   8,608.0208 (196.92)   489.7915 (37.33)    8,670.2460 (208.90)   902.6466 (78.87)         4;0   0.1162 (0.01)        10           1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Using a Windows mapped drive and standard Python open/copy functions (ie. not a pure-Python solution):

------------------------------------------------------------------------------------------------- benchmark: 4 tests -------------------------------------------------------------------------------------------------
Name (time in ms)                     Min                    Max                   Mean                StdDev                 Median                    IQR            Outliers      OPS            Rounds  Iterations
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
test_short_string_write           16.7014 (1.0)          21.4578 (1.0)          18.4363 (1.0)          1.1071 (1.0)          18.4308 (1.0)           1.2456 (1.0)           9;2  54.2408 (1.0)          35           1
test_mkdir                        17.3022 (1.04)         84.2097 (3.92)         27.2523 (1.48)        12.5868 (11.37)        23.2646 (1.26)          3.7816 (3.04)          4;7  36.6941 (0.68)         58           1
test_copy_larger_file          1,399.7678 (83.81)     2,827.1930 (131.76)    1,788.6201 (97.02)      399.8889 (361.20)    1,766.5214 (95.85)       324.8020 (260.76)        1;1   0.5591 (0.01)         10           1
test_copy_very_large_file     12,427.0299 (744.07)   27,758.3489 (>1000.0)  18,145.4980 (984.23)   6,033.7927 (>1000.0)  15,850.3429 (859.99)   10,450.3625 (>1000.0)       2;0   0.0551 (0.00)         10           1
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

The code used to produce these benchmarks is below. It should be run via pytest with the pytest-benchmark plugin loaded - just run pytest name_of_file.py and you'll get a summary of times at the end of the run.

smbprotocol_benchmarks.py

import shutil
import os
import smbclient
import smbclient.path
import smbclient.shutil
import pytest

BASE_PATH = r"\\WINVM\SecretFolder"

STRING_DATA = ["Hello, this is a test\n"] * 200


def short_string_write():
    if smbclient.path.exists(os.path.join(BASE_PATH, "StringTest.txt"), username="pepysadmin", password="pepysadmin"):
        smbclient.remove(os.path.join(BASE_PATH, "StringTest.txt"))

    with smbclient.open_file(os.path.join(BASE_PATH, "StringTest.txt"), mode="w") as f:
        f.writelines(STRING_DATA)

def mkdir():
    if smbclient.path.exists(os.path.join(BASE_PATH, "NewDirectory"), username="pepysadmin", password="pepysadmin"):
        smbclient.rmdir(os.path.join(BASE_PATH, "NewDirectory"))

    smbclient.mkdir(os.path.join(BASE_PATH, "NewDirectory"))

# def copy_larger_file(path='../tests/sample_data/track_files/NMEA/NMEA_TRIAL.log'):
#     if smbclient.path.exists(os.path.join(BASE_PATH, "CopiedLargeFile.txt"), username="pepysadmin", password="pepysadmin"):
#         smbclient.remove(os.path.join(BASE_PATH, "CopiedLargeFile.txt"), username="pepysadmin", password="pepysadmin")

#     with open(path, 'rb') as in_file:
#         with smbclient.open_file(os.path.join(BASE_PATH, "CopiedLargeFile.txt"), mode='wb') as out_file:
#             data = in_file.read()
#             out_file.write(data)

def copy_larger_file(path='../tests/sample_data/track_files/NMEA/NMEA_TRIAL.log'):
    smbclient.shutil.copy(path, os.path.join(BASE_PATH, "CopiedLargeFile.txt"), username="pepysadmin", password="pepysadmin")

def test_short_string_write(benchmark):
    benchmark(short_string_write)

def test_mkdir(benchmark):
    benchmark(mkdir)

def test_copy_larger_file(benchmark):
    benchmark(copy_larger_file)

def test_copy_very_large_file(benchmark):
    benchmark(copy_larger_file, path=r"C:\Users\Robin Wilson\Desktop\NGCM_ReproducibilitySeminar.pptx")

pysmb_benchmarks.py

import shutil
from io import BytesIO
import os
from smb.SMBConnection import SMBConnection
from smb.smb_structs import OperationFailure
import pytest


STRING_DATA = ["Hello, this is a test\n"] * 200


def short_string_write():
    conn = SMBConnection("pepysadmin", "pepysadmin", "WINVM", "WINVM", use_ntlm_v2 = True)
    assert conn.connect("winvm", 139)

    try:
        attrib = conn.getAttributes("SecretFolder", "StringTest.txt")
        conn.deleteFiles("SecretFolder", "StringTest.txt")
    except OperationFailure:
        pass

    s = BytesIO(bytes("\n".join(STRING_DATA), encoding='utf-8'))
    conn.storeFile('SecretFolder', "StringTest.txt", s)

def mkdir():
    conn = SMBConnection("pepysadmin", "pepysadmin", "WINVM", "WINVM", use_ntlm_v2 = True)
    assert conn.connect("winvm", 139)

    try:
        attrib = conn.getAttributes("SecretFolder", "NewDirectory")
        conn.deleteDirectory("SecretFolder", "NewDirectory")
    except OperationFailure:
        pass

    conn.createDirectory('SecretFolder', 'NewDirectory')

def copy_larger_file(path='../tests/sample_data/track_files/NMEA/NMEA_TRIAL.log'):
    # smbclient.shutil.copy(path, os.path.join(BASE_PATH, "CopiedLargeFile.txt"), username="pepysadmin", password="pepysadmin")

    conn = SMBConnection("pepysadmin", "pepysadmin", "WINVM", "WINVM", use_ntlm_v2 = True)
    assert conn.connect("winvm", 139)

    with open(path, mode='rb') as f:
        n_bytes = conn.storeFile('SecretFolder', 'CopiedLargeFile2.txt', f)

def test_short_string_write(benchmark):
    benchmark(short_string_write)

def test_mkdir(benchmark):
    benchmark(mkdir)

def test_copy_larger_file(benchmark):
    benchmark(copy_larger_file)

def test_copy_very_large_file(benchmark):
    benchmark(copy_larger_file, path=r"C:\Users\Robin Wilson\Desktop\NGCM_ReproducibilitySeminar.pptx")

mapped_drive_benchmarks.py

import shutil
import os
import smbclient
import smbclient.path
import smbclient.shutil
import pytest

BASE_PATH = "s:/"

STRING_DATA = ["Hello, this is a test\n"] * 200


def short_string_write():
    with open(os.path.join(BASE_PATH, "StringTest.txt"), 'w') as f:
        f.writelines(STRING_DATA)

def mkdir():
    if os.path.exists(os.path.join(BASE_PATH, "NewDirectory")):
        os.rmdir(os.path.join(BASE_PATH, "NewDirectory"))

    os.mkdir(os.path.join(BASE_PATH, "NewDirectory"))

def copy_larger_file(path='../tests/sample_data/track_files/NMEA/NMEA_TRIAL.log'):
    shutil.copy(path, os.path.join(BASE_PATH, "CopiedLargeFile.txt"))

def test_short_string_write(benchmark):
    benchmark(short_string_write)

def test_mkdir(benchmark):
    benchmark(mkdir)

def test_copy_larger_file(benchmark):
    benchmark(copy_larger_file)

def test_copy_very_large_file(benchmark):
    benchmark(copy_larger_file, path=r"C:\Users\Robin Wilson\Desktop\NGCM_ReproducibilitySeminar.pptx")