0 votes
by (210 points)

Hi, we have a Rebex SFTP server running on a low end PDA device under Windows CE 6.0.
The problem is that while there is file transfer going on, the SFTP server seems to take 100% CPU and the GUI isn't responding any more.
I'm aware that enciphering/deciphering takes some effort.
So, is it possible to lower the thread priority of the SFTP server so the rest of the system gets responsive again? I think it's not an option to increase all other threads' priorities because as far as I know the Windows GUI's priority cannot be changed.

Thanks!

2 Answers

0 votes
by (210 points)

As there seems to be no simple solution like just setting a Property, I investigated further and found the following solutions. Perhaps somebody may find them useful:

1) write a dedicated program just for the SFTP server, whose process priority may be decreased and according to Windows CE documentation, the threads of a process start with the same priority as the process, so they should have a lower priority, too.
Although this is the most obvious solution, I didn't go that way and preferred embedding the SFTP server into our application, so I could share resources like configuration files and logging.

2) intercepting the PathAccessAuthorization event and there lowering the thread priority like:

m_server = new FileServer();
m_server.PathAccessAuthorization += ( sender, e ) =>
{
    Thread.CurrentThread.Priority = ThreadPriority.Lowest;
    e.Allow();
};

It is not sufficient to do this only once in the Connecting event, as there seem to be several threads that are selected randomly to execute transactions. So, it is better to change the priority for every transaction.

This lowering of the priority was a solution for Reading files from our device (SFTP server -> client), but it had no effect when sending a big file to our device. Perhaps the OS just accepts the data and the application has to deal with it, no matter how its priority is set. So, for this case, I had to change the client to send the data much slower, e.g. only with 50000 bytes/s. This lowered the CPU load of the SFTP server significatly and the device was responsive again.

0 votes
by (148k points)

There is no quick obvious straightforward solution to this, and we needed to do some investigation first. Sorry for the late answer, and thanks for sharing your research.

I'll address your solutions first:

1) This is an obvious solution, but hard to do in practice, as you already found out.

2) There is no dedicated thread pool used only by the SFTP server code, which means decreasing thread priority is not a viable option - doing so using a PathAccessAuthorization event would actually affect the current thread indefinitely, which is undesirable because the same thread could be used by other parts of the application later. Despite this limitation, the approach might be usable in scenarios where you have complete control over all other threads.

And some other ideas:

3) I'm sure the SFTP server code could be optimized further to be faster, and we will most likely look into this in future. However, many of the optimizations we would like to do are not suitable for .NET Compact Framework and Windows CE 6.0. In fact, it's quite possible that the far-from-ideal speed on these platforms might be caused by some of the features we use, such as asynchronous socket API. Unfortunately, .NET CF is already a legacy platform that has been deprecated by its vendor years ago, which means substantial enhancements in this area no longer make financial sense.

4) Throttling the data flow at the socket level seems to be the most simple way to mitigate this issue. This would make the whole SFTP server run "slower" and therefore consume less CPU power (simply because it would spent more time waiting for data to arrive or get sent). However, this would require us to add support for custom transfer layers to Rebex File Server first. We will look into this when we are done with the upcoming Rebex HTTPS component.

by (210 points)
Thanks for your elaborate answer! I anyway stick to 2) because a quick test showed that the priority is indeed reset to "Normal" when a thread from the pool is reused; at least on .NET Compact Framework 3.5.
I know, this workaround is crude but I think it's the best I have right now. As you said, .NET Compact Framework is outdated. We are already planning to develop a new device with different OS.  :-)
...