7

Muszę wykonywać operacje chronologicznie na ogromnych szeregach czasowych zaimplementowanych jako IList. Dane są ostatecznie przechowywane w bazie danych, ale nie ma sensu przesyłanie dziesiątek milionów zapytań do bazy danych.Plik mapowany w pamięci Implementacja IList, do przechowywania dużych zbiorów danych "w pamięci"?

Obecnie IList w pamięci wywołuje wyjątek OutOfMemory przy próbie przechowania ponad 8 milionów (małych) obiektów, chociaż musiałbym radzić sobie z dziesiątkami milionów.

Po przeprowadzeniu badań wygląda na to, że najlepiej będzie zapisać dane na dysku i uzyskać do niego dostęp za pomocą opakowania IList.

Memory-mapped files (wprowadzony w .NET 4.0) wydaje się być właściwym interfejsem do wykorzystania, ale zastanawiam się, jaki jest najlepszy sposób napisania klasy, która powinna implementować IList (dla łatwego dostępu) i wewnętrznie zajmować się plikiem mapowanym w pamięci.

Jestem również ciekawy, czy znasz inne sposoby! Myślałem na przykład o opakowaniu IList przy użyciu danych z db4o (someone mentionned here przy użyciu pliku odwzorowanego w pamięci jako IoAdapterFile, chociaż użycie db4o prawdopodobnie zwiększa koszt wydajności w porównaniu z bezpośrednią obsługą z plikiem mapowanym w pamięci).

Natknąłem się na this question zadawane w 2009 roku, ale nie przyniosło użytecznych odpowiedzi lub poważnych pomysłów.

+0

są operacje wykonywane sekwencyjnie? czy korzystasz z całości danych naraz? – Yahia

+0

Dostęp powinien być sekwencyjny (iteracja nad kolekcją, aby wykonać aktualizację), a także musi być w stanie usunąć/usunąć obiekty na drugim końcu. –

+2

Baza danych to właściwe narzędzie do tego zadania. Aktualizuj dane w partiach, aby uniknąć zbyt wielu wywołań bazy danych. Możesz również zainteresować się przetwarzaniem stylu zmniejszającym mapę, aby trochę przyspieszyć. – dtb

Odpowiedz

8

Znalazłem to PersistentDictionary<>, ale działa tylko z ciągami, a czytając kod źródłowy nie jestem pewien, czy został zaprojektowany dla bardzo dużych zestawów danych.

Bardziej skalowalny (do 16 TB), ESENT PersistentDictionary<>, wykorzystuje silnik baz danych ESENT obecny w systemie Windows (XP +) i może przechowywać wszystkie obiekty serializowalne zawierające typy proste.

Disk Based Data Structures, including Dictionary, List and Array with an "intelligent" serializer wyglądał dokładnie tak, jak tego szukałem, ale nie działał płynnie z bardzo dużymi zestawami danych, zwłaszcza że nie korzysta jeszcze z "natywnego" .NET MemoryMappedFiles, a obsługa systemów 32-bitowych jest eksperymentalna .

Aktualizacja 1: Skończyło się na implementacji mojej własnej wersji, która szeroko wykorzystuje .NET MemoryMappedFiles; jest bardzo szybki i prawdopodobnie wypuszczę go na Codeplex, gdy tylko zrobię to lepiej dla zastosowań o bardziej ogólnym przeznaczeniu.

Aktualizacja 2: TeaFiles.Net działała również doskonale do mojego celu. Gorąco polecam (i za darmo).

+0

Dziękujemy za podzielenie się wrażeniami. Zajmuję się tym samym problemem i zastanawiałem się, czy już opublikowałeś swoją implementację na Codeplex, czy nie. Dziękuję Ci. – alhazen

+0

Cześć, jeszcze nie. Jednym z ograniczeń, które obecnie mam, jest to, że wszystkie obiekty, które mają być przechowywane, muszą być typu wartości. Jeśli tak jest w twoim przypadku (lub możesz przejść z typu referencyjnego do typów wartości), to mogę udostępnić mój kod przed opublikowaniem w Codeplex. –

+0

@ErwinMayer Zastanawiam się, czy gdzieś podzieliłeś kod. Potrzebuję implementacji IList wspieranej przez pliki dla niektórych dużych obiektów. –

1

Pliki odwzorowane w pamięci to dobry sposób na zrobienie tego. Ale będzie to bardzo powolne, jeśli chcesz uzyskać dostęp do rzeczy losowo.

Najlepszym rozwiązaniem jest prawdopodobnie wymyślenie stałego rozmiaru struktury po zapisaniu w pamięci (jeśli możesz), wtedy użyj przesunięcia jako identyfikatora elementu listy. Jednak usuwanie/sortowanie zawsze stanowi problem.

+0

AFAIK, dostęp losowy powinien być równy O (1), biorąc pod uwagę, że znamy przesunięcie bajtu. –

3

Widzę kilka możliwości:

  • "in-memory-DB"
    na przykład SQLite mogą być używane w ten sposób - nie ma potrzeby jakiejkolwiek konfiguracji itp tylko Wdrażanie DLL (1 lub 2) wraz z aplikacją i resztą można zrobić programowo
  • Załaduj wszystkie dane do tabel tymczasowych do DB, z nieznanymi (ale dużymi) ilościami danych, które odkryłem, że to się opłaca bardzo szybko (i przetwarzanie może być zwykle wykonane wewnątrz DB, który jest jeszcze lepszy!)
  • użyć MemoryMappedFile a wielkość stałej strukturze (array podobny dostępu poprzez przesunięcie) ale uwaga, pamięć fizyczną jest limit wyjątkiem użyć jakiegoś „okna przesuwnego” mapować tylko części do pamięci