dart-lang / dart-lang/native

Slow file operation both writing and reading

Open
#899 3 comments 0 reactions 0 assignees View on GitHub
package:ffi
Dominant language
Dart
Stars
275
Forks
144
Avg merge
2d 10h
Merged PRs (30d)
47

Description

I've made a libssh binding, and I'm seeing that operations taking download and file upload are slow, I'm not sure what's making it slow, I don't know if it's the dart garbage collector that's causing the slowdown. or if I'm doing something wrong, I'm using a native buffer to store chunks of the file and this same buffer to write the local file with dart.

```dart
void main() async {
// Open the dynamic library
var libraryPath = path.join(Directory.current.path, 'libssh_compiled', 'ssh.dll');
final dll = ffi.DynamicLibrary.open(libraryPath);
var libssh = Libssh(dll);

var host = "192.168.133.13";
var port = 22;
var password = "Ins257257";
var username = "isaque.neves";

// Abra a sessão e define as opções
var my_ssh_session = libssh.ssh_new();
libssh.ssh_options_set(my_ssh_session, ssh_options_e.SSH_OPTIONS_HOST, stringToNativeVoid(host));
libssh.ssh_options_set(my_ssh_session, ssh_options_e.SSH_OPTIONS_PORT, intToNativeVoid(port));
//libssh.ssh_options_set(my_ssh_session, ssh_options_e.SSH_OPTIONS_LOG_VERBOSITY, intToNativeVoid(SSH_LOG_PROTOCOL));
libssh.ssh_options_set(my_ssh_session, ssh_options_e.SSH_OPTIONS_USER, stringToNativeVoid(username));
// Conecte-se ao servidor
var rc = libssh.ssh_connect(my_ssh_session);
if (rc != SSH_OK) {
print('Error connecting to host: $host\n');
}

rc = libssh.ssh_userauth_password(my_ssh_session, stringToNativeInt8(username), stringToNativeInt8(password));
if (rc != ssh_auth_e.SSH_AUTH_SUCCESS) {
var error = libssh.ssh_get_error(my_ssh_session.cast());
print("Error authenticating with password:$error\n");
}

var start = DateTime.now();

var sftp = libssh.initSFTP(my_ssh_session);
await libssh.sftpDownloadFileTo(
my_ssh_session, '/home/isaque.neves/teste.mp4', path.join(Directory.current.path, 'teste.mp4'),
inSftp: sftp);

print(DateTime.now().difference(start));
libssh.ssh_disconnect(my_ssh_session);
libssh.ssh_free(my_ssh_session);
exit(0);
}
```

## relevant code
```dart
Future sftpDownloadFileTo(ssh_session session, String fullRemotePath, String fullLocalPath,
{Pointer? inSftp}) async {
var remotePath = fullRemotePath.toNativeUtf8();

var sftp = inSftp != null ? inSftp : initSFTP(session);

var access_type = O_RDONLY;

var remoteFile = sftp_open(sftp, remotePath.cast(), access_type, 0);
if (remoteFile.address == nullptr.address) {
sftp_free(sftp);
throw Exception('Can\'t open file for reading: ${ssh_get_error(session.cast()).cast().toDartString()}');
}
var nbytes = 0, nwritten = 0;
var bufferSize = MAX_XFER_BUF_SIZE * 2; //MAX_XFER_BUF_SIZE = 16384 = 16KB
final bufferNative = malloc(bufferSize);

var targetFile = await File(fullLocalPath).create(recursive: true);
var sink = targetFile.openWrite(); // for appending at the end of file

while (true) {
nbytes = sftp_read(remoteFile, bufferNative.cast(), sizeOf() * bufferSize);
nwritten += nbytes;
if (nbytes == 0) {
break; // EOF
} else if (nbytes < 0) {
await sink.flush();
await sink.close();
sftp_close(remoteFile);
if (inSftp == null) {
sftp_free(sftp);
}
malloc.free(bufferNative);
throw Exception('Error while reading file: ${ssh_get_error(session.cast()).cast().toDartString()}');
}

var data = bufferNative.asTypedList(nbytes);
sink.add(data);
}

await sink.flush();
await sink.close();

var localFileLength = targetFile.lengthSync();

if (localFileLength < nwritten) {
sftp_close(remoteFile);
if (inSftp == null) {
sftp_free(sftp);
}
malloc.free(bufferNative);
throw Exception('Incomplete file: ${ssh_get_error(session.cast()).cast().toDartString()}');
}

var rc = sftp_close(remoteFile);
if (rc != SSH_OK) {
if (inSftp == null) {
sftp_free(sftp);
}
malloc.free(bufferNative);
throw Exception('Can\'t close the written file: ${ssh_get_error(session.cast()).cast().toDartString()}');
}

if (inSftp == null) {
sftp_free(sftp);
}
malloc.free(bufferNative);
}
```

https://github.com/insinfo/fsbackup/tree/main/libssh_binding

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.