Was ich verstehe, ist, dass Sie eine Liste des Paares (Key, Score), mit dem Sie ausführen möchten halten:
- häufige Aktualisierung der Partitur,
- häufig einen vollständigen oder teilweise angezeigt werden Ansicht der Liste nach Punkten sortiert
ich Ihnen vorschlagen, speichern Sie Ihre Daten in 2 verschiedenen ets:
- Der erste für den schnellen Zugriff auf den Schlüssel ist ein Satz, in dem Sie den Schlüssel im ersten Feld und den Wert im zweiten Feld speichern.
- Die zweite ist eine geordnete Menge, in der Sie ein Tupel {Score, Key} als Schlüssel und keinen Wert speichern. Dies sollte die Eindeutigkeit jedes Datensatzes garantieren und die Liste nach Punkten geordnet halten.
Wenn Sie Noten anzeigen müssen, ist die geordnete Menge ausreichend.
Wenn Sie eine Partitur aktualisieren müssen, sollten Sie die Ets verwenden, um den Wert der vorherigen Partitur für Key zu erhalten, den Datensatz {PrevScore, Key} löschen und {NewScore, Key} in die geordnete Menge einfügen und einfach die Erste Ets mit neuem Wert.
Ich testete diese Lösung auf einer 1 000 000 Artikel Liste, das Update von 1 Score dauert durchschnittlich 3 μs auf meinem Laptop (Windows XP, Core i5, 2Go RAM, alle Festplatten voll und viele App im Hintergrund laufen). I der verwendete Code:
note Ich benutzte private Tische und einen einzelnen Server sie zuzugreifen, um die Konsistenz der zwei Tabellen, so gleichzeitige Prozesse zu gewährleisten, kann auf den Server zugreifen (namens score) ohne Konflikte, die Anforderungen werden in der Reihenfolge ausgeführt, in der sie beim Server ankommen. Es könnte möglich sein, eine Antwort auf jede get (N) Anfrage mit 2 Empfangsblöcken zu erhalten.
hier ist das Testergebnis auf meinem Heim-PC (ubuntu 12.04, 8gb ddr, AMD Phenom II X6) ...
[Bearbeiten] ich das Update/2-Funktion, um synchron zu sein modifiziert, So ist die Maßnahme jetzt signifikant und das Ergebnis verständlicher. Es scheint, dass für eine Tabelle, die kleiner als 10000 Datensätze ist, der Overhead der ETS-Verwaltung und der Nachrichtenweitergabe überwiegt.
-module (score).
-export ([start/0]).
-export ([update/2,delete/1,get/1,stop/0]).
score ! {update,M,S,self()},
receive
ok -> ok
end.
delete(M) ->
score ! {delete,M}.
get(N) ->
score ! {getbest,N,self()},
receive
{ok,L} -> L
after 5000 ->
timeout
end.
stop() ->
score ! stop.
start() ->
P = spawn(fun() -> initscore() end),
register(score,P).
initscore() ->
ets:new(score,[ordered_set,private,named_table]),
ets:new(member,[set,private,named_table]),
loop().
loop() ->
receive
{getbest,N,Pid} when is_integer(N), N > 0 ->
Pid ! {ok,lists:reverse(getbest(N))},
loop();
{update,M,S,P} ->
update_member(M,S),
P ! ok,
loop();
{delete,M} ->
delete_member(M),
loop();
stop ->
ok
end.
update_member(M,S) ->
case ets:lookup(member,M) of
[] ->
ok;
[{M,S1}] ->
ets:delete(score,{S1,M})
end,
ets:insert(score,{{S,M}}),
ets:insert(member,{M,S}).
delete_member(M) ->
case ets:lookup(member,M) of
[] ->
ok;
[{M,S}] ->
ets:delete(score,{S,M}),
ets:delete(member,M)
end.
getbest(N) ->
K= ets:last(score),
getbest(N-1,K,[]).
getbest(_N,'$end_of_table',L) -> L;
getbest(0,{S,M},L) -> [{M,S}|L];
getbest(N,K={S,M},L) ->
K1 = ets:prev(score,K),
getbest(N-1,K1,[{M,S}|L]).
und der Code für den Test:
-module (test_score).
-compile([export_all]).
init(N) ->
score:start(),
random:seed(erlang:now()),
init(N,10*N).
stop() ->
score:stop().
init(0,_) -> ok;
init(N,M) ->
score:update(N,random:uniform(M)),
init(N-1,M).
test_update(N,M) ->
test_update(N,M,0).
test_update(0,_,T) -> T;
test_update(N,M,T) -> test_update(N-1,M,T+update(random:uniform(M),random:uniform(10*M))).
update(K,V) ->
{R,_} = timer:tc(score,update,[K,V]),
R.
Werfen Sie einen Blick auf Oddict http://erdocs.com/R15B/stdlib/orddict.html. Ich habe nicht überprüft, ob es die Funktionalität unterstützt, die Sie benötigen, aber es sieht so aus, Sie können einen Wrapper erstellen, um Ihre Funktionalität zu implementieren – Arunmu
@ArunMu Es tut mir leid, es scheint orddict "Die Liste ist nach den Schlüsseln geordnet". Ich möchte nach dem Wert – mingchaoyan
ordere Ich bin nur neugierig zu wissen, warum Sie nach Wert sortieren möchten. Wie hilft es beim Abrufen der Schlüssel/Wert-Paare? – Arunmu