2008-11-19 28 views
10

Chúng tôi có một ứng dụng tạo dữ liệu mô phỏng cho một trong các dịch vụ của chúng tôi cho mục đích thử nghiệm. Mỗi mục dữ liệu có một Hướng dẫn duy nhất. Tuy nhiên, khi chúng tôi chạy một thử nghiệm sau khi một số mã nhỏ thay đổi để giả lập tất cả các đối tượng được tạo ra bởi nó có cùng một hướng dẫn.Bản sao được trả lại bởi Guid.NewGuid()?

Có một đối tượng dữ liệu được tạo, sau đó là vòng lặp for nơi các thuộc tính của đối tượng đã được sửa đổi, bao gồm một Guid duy nhất mới và nó được gửi đến dịch vụ qua remoting (serializable, chứ không phải marshal-by-ref, nếu đó là những gì bạn đang suy nghĩ), lặp lại và làm lại, v.v.

Nếu chúng ta đặt một Thread.Sleep (...) nhỏ trong vòng lặp, nó tạo ra id duy nhất. Tôi nghĩ rằng đó là một cá trích đỏ. Tôi tạo ra một ứng dụng thử nghiệm mà chỉ cần tạo ra một guid sau khi khác và không nhận được một bản sao duy nhất.

Lý thuyết của tôi là IL được tối ưu hóa theo cách gây ra hành vi này. Nhưng đủ về lý thuyết của tôi. Bạn nghĩ sao? Tôi đang mở để gợi ý và cách để kiểm tra nó.

CẬP NHẬT: Dường như có nhiều nhầm lẫn về câu hỏi của tôi, vì vậy hãy để tôi làm rõ. Tôi KHÔNG nghĩ rằng NewGuid() bị hỏng. Rõ ràng nó hoạt động. Tốt rồi! Có một lỗi ở đâu đó, điều đó khiến cho NewGuid() thành một trong hai: 1) chỉ được gọi một lần trong vòng lặp của tôi 2) được gọi là mọi lúc trong vòng lặp của tôi nhưng chỉ được gán một lần 3) cái gì khác mà tôi chưa từng nghĩ đến

Lỗi này có thể nằm trong mã của tôi (có khả năng nhất) hoặc trong tối ưu hóa ở đâu đó.

Vì vậy, để nhắc lại câu hỏi của mình, tôi nên gỡ lỗi kịch bản này như thế nào?

(và cảm ơn bạn đã thảo luận rất lớn, điều này thực sự đã giúp tôi làm rõ các vấn đề trong tâm trí của tôi)

CẬP NHẬT # 2: Tôi rất muốn gửi một ví dụ cho thấy vấn đề, nhưng đó là một phần của vấn đề của tôi. Tôi không thể sao chép nó bên ngoài toàn bộ các ứng dụng (máy khách và máy chủ).

Dưới đây là một đoạn có liên quan mặc dù:

OrderTicket ticket = new OrderTicket(...); 

for(int i = 0; i < _numOrders; i++) 
{ 
    ticket.CacheId = Guid.NewGuid(); 
    Submit(ticket); // note that this simply makes a remoting call 
} 
+0

Nếu bạn nghĩ rằng có một lỗi trong IL - sử dụng Reflector để theo dõi nó xuống. –

+0

Ah, vâng. Tôi nghĩ về điều đó. Nhưng dự đoán ban đầu của tôi là nó có thể nằm trong trình tối ưu hóa JIT. Không thể sử dụng Reflector cho điều đó. – dviljoen

+0

Nếu bạn không nghĩ đó là lỗi của NewGuid, hãy đăng một số mã hiển thị sự cố.Hoặc, ít nhất, hãy đăng mã * có * vấn đề. Ngoài ra, hãy trả lời câu hỏi về việc xóa Thread.Sleep có gây ra sự cố xuất hiện lại hay không. Tôi khá giỏi trong việc gỡ rối tâm linh - nhưng thậm chí tốt hơn với một số chi tiết. –

Trả lời

21

Không gửi thực hiện cuộc gọi không đồng bộ hoặc đối tượng vé chuyển sang chuỗi khác ở bất kỳ giai đoạn nào.

Trong ví dụ mã, bạn đang sử dụng lại cùng một đối tượng. Điều gì sẽ xảy ra nếu Gửi gửi vé trong chuỗi nền sau một thời gian trễ ngắn (và không lấy bản sao). Khi bạn thay đổi CacheId bạn đang thực sự cập nhật tất cả các đệ trình đang chờ xử lý. Điều này cũng giải thích lý do tại sao Thread.Sleep khắc phục sự cố. Hãy thử điều này:

for(int i = 0; i < _numOrders; i++) 
{ 
    OrderTicket ticket = new OrderTicket(...); 
    ticket.CacheId = Guid.NewGuid(); 
    Submit(ticket); // note that this simply makes a remoting call 
} 

Nếu vì lý do này là không thể, hãy thử này và xem nếu họ vẫn đều giống nhau:

ticket.CacheId = new Guid("00000000-0000-0000-0000-" + 
    string.Format("{0:000000000000}", i)); 
+0

Bạn đã hiểu! Đó chính là vấn đề. Tuyệt vời!!! Cảm ơn. – dviljoen

+3

@dviljoen: có vẻ như tôi sẽ thắng cược sau tất cả. :) – MusiGenesis

3

Đó là một lỗi trong mã của bạn. Nếu bạn đã quản lý để tạo ra nhiều guid thì đó là giải thích có khả năng nhất. Các đầu mối là ở đây trong câu hỏi của bạn: "khi chúng tôi chạy một thử nghiệm sau khi một số thay đổi mã nhỏ để mô phỏng tất cả các đối tượng được tạo ra bởi nó có cùng Guid"

+0

Yup, đó cũng là những gì tôi nghĩ. Nhưng tôi không thể tìm thấy nó. Mỗi lần lặp lại đang gọi NewGuid() mỗi lần và mỗi lần nó trả về cùng một Id. Gợi ý? – dviljoen

+0

Đó là vấn đề với các trình tạo số ngẫu nhiên, bạn không bao giờ có thể chắc chắn. – tsilb

+0

Tôi không mua nó. Các guid có một số ngẫu nhiên trong nó, và có, sao chép về mặt lý thuyết là "có thể" nhưng không MỌI MỘT. Đó rõ ràng không phải là vấn đề ở đây. Đã xảy ra sự cố với mã của chúng tôi hoặc trình tối ưu hóa. Vấn đề của tôi là tôi không biết cách tìm ra cái nào. Gợi ý? – dviljoen

2

Xem article này về làm thế nào một Guid được tạo ra.

Cúp nghệ thuật này đến từ câu trả lời This.

Điểm mấu chốt nếu bạn đang tạo GUID quá nhanh và đồng hồ không di chuyển về phía trước đó là lý do tại sao bạn nhận được một số tương tự. Tuy nhiên khi bạn đặt một giấc ngủ trong nó hoạt động vì đồng hồ đã di chuyển.

+0

Cảm ơn, nhưng một lần nữa, điều này không giúp tôi. Tôi biết rằng một Guid có tính thống kê độc đáo. Vấn đề của tôi KHÔNG phải là tôi có 2 trong số 10.000 Hướng dẫn đã bị lừa đảo. Vấn đề của tôi là 10.000 trong số 10.000 người đã bị lừa đảo. Đó không phải là một vụ va chạm thống kê. Đó là một lỗi. Nhưng ở đâu? Và làm thế nào để tìm? – dviljoen

+0

Xin lỗi, đã bỏ phiếu cho bạn để không đọc toàn bộ bài viết bạn đã liên kết. – MusiGenesis

2

Mã trong Submit và OrderTicket cũng sẽ hữu ích ...

Bạn đang sử dụng lại OrderTicket. Tôi nghi ngờ rằng hoặc là bạn (hoặc remoting chính nó) là batching cuộc gọi ra - có lẽ liên quan đến số lượng kết nối/giới hạn máy chủ - và chọn lên giá trị cuối cùng của CacheId khi nó cuối cùng gửi chúng cùng.

Nếu bạn gỡ lỗi hoặc Chủ đề.Ngủ ứng dụng, bạn đang thay đổi thời gian để cuộc gọi từ xa kết thúc trước khi bạn gán một CacheId mới.

Bạn có đang đồng bộ hóa cuộc gọi từ xa không? Tôi nghĩ rằng một cuộc gọi đồng bộ sẽ chặn - nhưng tôi muốn kiểm tra với một gói sniffer như Wireshark để chắc chắn. Bất kể, chỉ cần thay đổi để tạo ra một OrderTicket mới trong mỗi lần lặp lại có lẽ sẽ làm các trick.

Chỉnh sửa: Câu hỏi là không về NewGuid bị hỏng ... vì vậy câu trả lời trước của tôi đã bị xóa.

+0

Tôi biết một lỗi của nó. Nhưng giống như nhiều người khác ở đây bạn dường như đang cố định tính độc đáo của một Guid. Đó không phải là vấn đề. Một lần nữa, 2 người trong số 10.000 người sẽ là một vấn đề duy nhất. Tôi nhận được 10.000 của cùng một Guid. – dviljoen

+0

Nếu bạn biết đó là lỗi (có nghĩa là bạn nghĩ đó là lỗi ứng dụng), thì tại sao tiêu đề "Bản sao được trả về bởi Guid.NewGuid()" và lý thuyết cho rằng trình tối ưu hóa JIT gây ra sự cố? –

+0

Đối với việc sửa lỗi "tính duy nhất của một hướng dẫn", điều đó thậm chí không gần với những gì tôi đã đặt ra. Ví dụ, một ví dụ có thể gây ra tất cả các loại vấn đề - bao gồm cả các hướng dẫn lặp đi lặp lại (có khả năng - một lần nữa lý thuyết được tìm nạp nhiều cho lựa chọn của bạn là suy nghĩ bị hỏng). –

6

Hàng nghìn nhà phát triển sử dụng Hướng dẫn trong .NET. Nếu Guid.NewGuid() có bất kỳ xu hướng nào để bị "kẹt" trên một giá trị, thì vấn đề này đã gặp phải từ lâu rồi.

Thay đổi mã nhỏ là nguyên nhân chắc chắn ở đây. Thực tế là Thread.Sleep (ít cá trích đỏ hơn cá bị thối rữa dưới ánh nắng mặt trời) "khắc phục" vấn đề của bạn cho thấy rằng tài sản của bạn đang được đặt theo một cách kỳ lạ mà không thể có hiệu lực cho đến khi vòng lặp dừng chặn hoặc bởi Thread.Sleep). Tôi thậm chí còn sẵn sàng đặt cược rằng "thay đổi nhỏ" là đặt lại tất cả các thuộc tính từ một chuỗi riêng biệt.

Nếu bạn đã đăng một số mã mẫu, điều đó sẽ hữu ích.

+1

Bạn sẽ thua cược đó. Đây là một chuỗi đơn giản chỉ tạo dữ liệu đối tượng trên dây. – dviljoen

+0

Thôi nào, đăng một số mã. Guid.NewGuid() không phải là vấn đề. – MusiGenesis

+0

Được rồi, tôi đã bình chọn cho bạn bởi vì, vâng, tôi sẽ trả tiền. ;-) – dviljoen

1

Tôi không biết chi tiết về cách GUID được tạo. Tuy nhiên hiện tại tổ chức của tôi. là nuôi GUID với tốc độ khiến thỏ xấu hổ. Vì vậy, tôi có thể xác minh cho thực tế là GUID không bị hỏng .. chưa.

  • Đăng mã nguồn nếu có thể .. hoặc ứng dụng sao chép bản sao. Nhiều lần tôi thấy hành động tạo ra ứng dụng nhân bản đó để repro vấn đề cho tôi thấy vấn đề.
  • Cách tiếp cận khác sẽ là nhận xét "những thay đổi nhỏ" đó. Nếu điều đó khắc phục được sự cố, bạn có thể tạo hình tam giác để tìm ra dòng mã vi phạm. Eye-ball những thay đổi nhỏ cứng ... Tôi có nghĩa là thực sự cứng.

Hãy cho chúng tôi biết nó như thế nào ... điều này nghe có vẻ thú vị.

+0

Tôi sẽ gặp rắc rối sâu sắc một cách chuyên nghiệp nếu Guid.NewGuid() nhổ ra một cuộc trò chuyện mỗi vài triệu cuộc gọi, hãy để một mình mỗi lần. – MusiGenesis

0

ruột của tôi là nói cho tôi một cái gì đó dọc theo những dòng đang xảy ra. ..

class OrderTicket 
{ 
    Guid CacheId {set {_guid = new Guid("00000000-0000-0000-0000-");} 
} 

Ghi giá trị của CacheId vào tệp nhật ký mỗi lần được gọi bằng dấu vết ngăn xếp ... Có thể ai đó đang đặt nó.

+0

Không. Nó chỉ đơn giản là kết thúc tốt đẹp _cacheId được khởi tạo để Guid.NewGuid() – dviljoen

+0

Điều gì xảy ra khi bạn đăng nhập giá trị + system.diagnostics stack trac ... –

Các vấn đề liên quan