zeromq / clrzmq4

ZeroMQ C# namespace (.NET and mono, Windows, Linux and MacOSX, x86 and amd64)
GNU Lesser General Public License v3.0
241 stars 112 forks source link

Bug in public virtual bool Send(IEnumerable<ZFrame> frames, ZSocketFlags flags, out ZError error) #211

Open AntiTenzor opened 3 years ago

AntiTenzor commented 3 years ago

This function throws an exception in .NET Framework 4.8 if I call it with a fixed-size array as a first argument.

Here is a full listing to reproduce the issue:

` using System;

using ZeroMQ;

namespace BugClrzmq4 { internal class Program { public static void Main(string[] args) { using (ZContext clrZmqContext = ZContext.Current) using(ZSocket pub = new ZSocket(ZSocketType.PUB)) { pub.Bind("inproc://pub");

            ZFrame z1 = new ZFrame("line1");
            ZFrame z2 = new ZFrame("line2");

            /*

This line throws an exception: Unhandled Exception: System.NotSupportedException: Collection was of a fixed size. at System.SZArrayHelper.Remove[T](T value) at ZeroMQ.ZSocket.SendFrames(IEnumerable1 frames, Int32& sent, ZSocketFlags flags, ZError& error) in w:\git\clrzmq4\ZSocket.cs:line 720 at ZeroMQ.ZSocket.SendFrames(IEnumerable1 frames, ZSocketFlags flags, ZError& error) in w:\git\clrzmq4\ZSocket.cs:line 682 at BugClrzmq4.Program.Main(String[] args) in W:\Source\CS\BugClrzmq4\BugClrzmq4\BugClrzmq4\Program.cs:line 35 */ pub.Send(new ZFrame[] { z1, z2 }, ZSocketFlags.DontWait, out ZError error);

            /*

ZSocket.cs lines 719-221: if (framesIsList) { ((IList)frames).Remove(frame); } */

            /*

This is because fixed-sized array new ZFrame[] { z1, z2 } IS IList, but you can NOT remove elements from it (even after cast). */ Console.WriteLine("error: {0}", error);

            /*

Actually I do not understand why do you even bother to remove elements? AFAIK, for many collections (such as List) Remove is relatively expensive operation. */ } } } } `

AntiTenzor commented 3 years ago

Nobody is interested?

koerner-lsd commented 1 year ago

To be frank, the formatting of your post does not invite readers.

Anyways, I agree it is a bad idea to remove the ZFrames from the message to be sent. Especially when it is a List. Sending ZMessages has caused us great performance problems, because ZMessage is implemented using effectively an ArrayList, meaning the send function suddenly has quadratic complexity. Sending a 10_000 ZFrame ZMessage took 4,2s. Optimizing this by doing all the things the wrapper functions would have done (minus the remove operation) I got that down to 13ms.