Hiện tại, mã của bạn đang sử dụng API đồng bộ (StringSet
), và đang được tải đồng thời bởi 10 chủ đề. Điều này sẽ không có thách thức đáng kể nào đối với SE.Redis - nó hoạt động tốt ở đây. Tôi nghi ngờ rằng nó thực sự là một khoảng thời gian chờ mà máy chủ mất nhiều thời gian hơn bạn muốn để xử lý một số dữ liệu, rất có thể cũng liên quan đến trình cấp phát của máy chủ. Sau đó, một tùy chọn là chỉ cần tăng thời gian chờ lên một chút . Không nhiều lắm ... hãy thử 5 giây thay vì 1 giây mặc định. Có thể, hầu hết các hoạt động đều hoạt động rất nhanh.
Liên quan đến việc tăng tốc:một tùy chọn ở đây là không đợi - tức là giữ dữ liệu pipelining. Nếu bạn không muốn kiểm tra từng thông báo để tìm trạng thái lỗi, thì một cách đơn giản để thực hiện việc này là thêm , flags: CommandFlags.FireAndForget
vào cuối StringSet
của bạn gọi điện. Trong thử nghiệm cục bộ của tôi, điều này đã tăng tốc ví dụ 1M lên 25% (và tôi nghi ngờ phần lớn thời gian còn lại thực sự được dành cho việc tuần tự hóa chuỗi).
Vấn đề lớn nhất mà tôi gặp phải với ví dụ 10M chỉ đơn giản là chi phí làm việc với ví dụ 10M - đặc biệt là vì điều này chiếm một lượng lớn bộ nhớ cho cả redis-server
và ứng dụng (để mô phỏng thiết lập của bạn) trên cùng một máy. Điều này tạo ra áp lực bộ nhớ cạnh tranh, với GC tạm dừng, v.v. trong mã được quản lý. Nhưng có lẽ quan trọng hơn: chỉ đơn giản là mất vĩnh viễn để bắt đầu làm bất cứ điều gì . Do đó, tôi đã cấu trúc lại mã để sử dụng yield return
song song máy phát điện hơn là một danh sách duy nhất. Ví dụ:
static IEnumerable<Person> InventPeople(int seed, int count)
{
for(int i = 0; i < count; i++)
{
int f = 1 + seed + i;
var item = new Person
{
Id = f,
Name = Path.GetRandomFileName().Replace(".", "").Substring(0, appRandom.Value.Next(3, 6)) + " " + Path.GetRandomFileName().Replace(".", "").Substring(0, new Random(Guid.NewGuid().GetHashCode()).Next(3, 6)),
Age = f % 90,
Friends = ParallelEnumerable.Range(0, 100).Select(n => appRandom.Value.Next(1, f)).ToArray()
};
yield return item;
}
}
static IEnumerable<T> Batchify<T>(this IEnumerable<T> source, int count)
{
var list = new List<T>(count);
foreach(var item in source)
{
list.Add(item);
if(list.Count == count)
{
foreach (var x in list) yield return x;
list.Clear();
}
}
foreach (var item in list) yield return item;
}
với:
foreach (var element in InventPeople(PER_THREAD * counter1, PER_THREAD).Batchify(1000))
Đây, mục đích của Batchify
là để đảm bảo rằng chúng tôi không trợ giúp máy chủ quá nhiều bằng cách dành thời gian đáng kể giữa mỗi lần hoạt động - dữ liệu được phát minh theo lô 1000 và mỗi lô được cung cấp rất nhanh chóng.
Tôi cũng lo lắng về hiệu suất JSON, vì vậy tôi đã chuyển sang JIL:
public static string ToJSON<T>(this T obj)
{
return Jil.JSON.Serialize<T>(obj);
}
và sau đó chỉ để cho vui, tôi đã chuyển công việc JSON vào nhóm (để các vòng xử lý thực tế:
foreach (var element in InventPeople(PER_THREAD * counter1, PER_THREAD)
.Select(x => new { x.Id, Json = x.ToJSON() }).Batchify(1000))
Điều này làm giảm thời gian hơn một chút, vì vậy tôi có thể tải 10M trong 3 phút 57 giây, tốc độ 42.194 vòng. Hầu hết thời gian này thực sự là xử lý cục bộ bên trong ứng dụng. Nếu tôi thay đổi nó để mỗi luồng tải giống nhau mục ITEMS / THREADS
lần, sau đó điều này thay đổi thành 1 phút 48 giây - tốc độ 92.592 vòng.
Tôi không chắc liệu mình đã thực sự trả lời điều gì chưa, nhưng phiên bản ngắn có thể chỉ đơn giản là "thử thời gian chờ lâu hơn; cân nhắc sử dụng fire-and-forget).