Mam utworzyć aplikację Windows, która rutynowo pobierze plik z serwera równoważenia obciążenia, obecnie prędkość wynosi około 30 MB/s. Jednak próbuję użyć FastCopy lub TeraCopy, który może kopiować z prędkością około 100 MB/s. Chcę wiedzieć, jak poprawić szybkość kopiowania, aby móc szybciej kopiować pliki niż obecnie.Jak sprawić, by mój plik kopii aplikacji był szybszy?
Odpowiedz
Jednym z częstych błędów podczas korzystania ze strumieni jest jednoczesne kopiowanie bajtów lub użycie małego bufora. W większości przypadków zapisywanie danych na dysku jest poszukiwaniem, więc użycie większego bufora obniży średni czas wyszukiwania na bajt.
Systemy operacyjne zapisują pliki na dysku w klastrach. Oznacza to, że podczas zapisywania pojedynczego bajtu na dysku system Windows będzie faktycznie zapisywać blok o rozmiarze od 512 bajtów do 64 kb. Możesz uzyskać znacznie lepszą wydajność dysku, używając bufora, który jest wielokrotnością całkowitą 64 kb.
Dodatkowo można zwiększyć wykorzystanie bufora stanowiącego wielokrotność rozmiaru strony pamięci używanego procesora. W przypadku maszyn x86/x64 można ustawić wartość 4 kB lub 4 MB.
Więc chcesz użyć wielokrotności całkowitej równej 4mb.
Dodatkowo, jeśli korzystasz z asynchronicznego IO, możesz w pełni wykorzystać duży rozmiar bufora.
class Downloader
{
const int size = 4096 * 1024;
ManualResetEvent done = new ManualResetEvent(false);
Socket socket;
Stream stream;
void InternalWrite(IAsyncResult ar)
{
var read = socket.EndReceive(ar);
if (read == size)
InternalRead();
stream.Write((byte[])ar.AsyncState, 0, read);
if (read != size)
done.Set();
}
void InternalRead()
{
var buffer = new byte[size];
socket.BeginReceive(buffer, 0, size, System.Net.Sockets.SocketFlags.None, InternalWrite, buffer);
}
public bool Save(Socket socket, Stream stream)
{
this.socket = socket;
this.stream = stream;
InternalRead();
return done.WaitOne();
}
}
bool Save(System.Net.Sockets.Socket socket, string filename)
{
using (var stream = File.OpenWrite(filename))
{
var downloader = new Downloader();
return downloader.Save(socket, stream);
}
}
Ewentualnie aplikacja może zrobić wielowątkowości, aby pobrać plik za pomocą wielu wątków, jednak przepustowość jest ograniczona do prędkości urządzeń, które przenoszą treść
Najprostszym sposobem jest otwarcie pliku w formacie RAW/binarny tryb (który mówi C nie jest pewien, czy jest odpowiednik C#) i czyta i zapisuje bardzo duże bloki (kilka MB) na raz.
Sztuką, z której korzysta TeraCopy, jest asynchroniczne czytanie i pisanie. Oznacza to, że blok danych można zapisać podczas odczytu innego.
Musisz rozejrzeć się za liczbą klocków i rozmiarem bloków, aby uzyskać optymalną dla siebie sytuację. Użyłem tej metody używając C++ i dla nas optymalnym było używanie czterech bloków po 256 KB podczas kopiowania z udziału sieciowego na dysk lokalny.
Pozdrawiam,
Sebastiaan
Jeśli prowadzisz Process Monitor można zobaczyć rozmiary bloku, który Eksploratora Windows lub TeraCopy używasz.
W systemie Vista domyślny rozmiar bloku dla sieci lokalnej wynosi 2 MB, co znacznie przyspiesza kopiowanie plików przez ogromną rurę.
Po co na nowo odkrywać koło?
Jeśli twoja sytuacja na to pozwala, prawdopodobnie lepiej jest użyć jednego z istniejących "szybkich" narzędzi do kopiowania, niż próbować napisać samemu. Istnieje wiele nieoczywistych przypadków krawędziowych, z którymi należy się uporać, a uzyskiwanie niezmiennie dobrego wykonania wymaga wielu eksperymentów z błędem próbnym.
- 1. Jak sprawić, by Pycharm był szybszy/lżejszy?
- 2. Jak sprawić, by mój triest był bardziej wydajny?
- 3. Jak sprawić, by zwykły WebRequest był asynchroniczny?
- 4. Jak sprawić, by wget był odpowiednio cichy?
- 5. Jak sprawić, by Tomcat był przenośny?
- 6. Jak sprawić, by fancybox href był dynamiczny?
- 7. Jak sprawić, by atrybut modelu był globalny?
- 8. jak sprawić, aby mój obraz był klikalny
- 9. Jak sprawić, by numer był nieosiągalny (podobnie jak blokada połączeń)?
- 10. Jak mogę sprawić, by mój mecz nie był chciwy w vimie?
- 11. Jak sprawić, by komponent był powszechnie dostępny w Angular2
- 12. Jak sprawić, by log Gita nie był wyświetlany, aby kontynuować?
- 13. Jak mogę sprawić, by kolor Valdatora był czerwony?
- 14. Jak sprawić, by Dapper był odporny na SqlAzure?
- 15. Jak sprawić, by try-except-KeyError był krótszy w pythonie?
- 16. Jak sprawić, by wybrany element był przezroczysty w przeglądarce Chrome?
- 17. Jak sprawić, by biały układ HTML był nieproporcjonalny?
- 18. Jak sprawić, by Head był mistrzem w git?
- 19. Jak mogę sprawić, aby mój UIPickerView Multiline był szybki?
- 20. Jak sprawić, by czas realizacji Placu zabaw był tak szybki, jak gdybyśmy działali w aplikacji iOS?
- 21. Jak sprawić, by @ Html.EditorFor niepełnosprawnych
- 22. Jak sprawić, by interfejs działał?
- 23. Jak sprawić, aby wygląd html był wyłączony?
- 24. Jak sprawić, by wybór strefy czasowej był bardziej przyjazny dla użytkownika?
- 25. Jak sprawić, by element podrzędny był ograniczony przez jego rodzica w WPF?
- 26. Jak sprawić, by Gedit wyglądał jak Textmate?
- 27. Jak sprawić, by Vim szanował .editorconfig?
- 28. Jak sprawić, by Projekt Startowy stał się VS2012
- 29. Jak sprawić, by Asio rozwidlało się bezpieczniej
- 30. Jak sprawić, by Intellij Idea zaczął używać glassfish jako sudo?
Czy mogę używać "szybkich" narzędzi do kopiowania dla skryptów (wiersza poleceń)? – Kiquenet
Co najmniej niektóre są skryptowalne - robocopy to jeden z przykładów. – Addys