SubmitAsync memory consumption without deallocation

.NET library for SMPP protocol
Locked
Kernighan
Posts: 3
Joined: Fri Jun 12, 2015 9:17 am

SubmitAsync memory consumption without deallocation

Post by Kernighan » Mon Sep 07, 2015 7:49 am

Hi guys, with performance test i noticed that SubmitAsync consum a lot of memory without stops a deallocating.
Can someone help me to resolve this issue? Possible i made something wrong. Thanks for any help.

Code: Select all

  private static void SmppClientOnEvSubmitComplete(object sender, SubmitSmResp submitSmResp)
  {
   try
   {
    lock (LockSubmitComplete)
    {
     var clientExtension = clientCollection[(int)submitSmResp.Sequence % clientCollection.Count];

     if (submitSmResp.Status != CommandStatus.ESME_ROK)
     {
      var serverMessageId = Guid.NewGuid().GetHashCode();

      var submitSmRespExtension = new SubmitSmRespExtension
       {
        Sequence = (int)submitSmResp.Sequence,
        DestAddr = long.Parse(submitSmResp.Request.DestAddr),
        DestAddrTon = submitSmResp.Request.DestAddrNpi,
        DestAddrNpi = submitSmResp.Request.DestAddrTon,
        SourceAddr = submitSmResp.Request.SourceAddr,
        SourceAddrTon = submitSmResp.Request.SourceAddrTon,
        SourceAddrNpi = submitSmResp.Request.SourceAddrNpi,
        ServerMessageId = serverMessageId,
        OriginalMessageId = "NO MESSAGEID",
        Origin = "INBOUND",
        Status = submitSmResp.Status.ToString(),
        DataCoding = GetDataCoding(submitSmResp.Request.DataCoding),
        IsReportSent = false,
       };

      SubmitSmRespCollector.Enqueue(submitSmRespExtension);

      var deliverSmExtension = new DeliverSmExtension
       {
        Status = 8,
        DestAddr = long.Parse(submitSmResp.Request.DestAddr),
        SourceAddr = submitSmResp.Request.SourceAddr,
        MessageId = serverMessageId,
        DateTime = DateTime.Now
       };

      DeliverSmCollector.Enqueue(deliverSmExtension);
     }
     else
     {
      int value;

      switch (CommandParser(clientExtension.MessageFormat.ToUpper()))
      {
       case MessageFormat.HexToDec:
        {
         if (!int.TryParse(submitSmResp.MessageId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out value))
         {
          DbLayer.AddToLog("ERROR", "Controller::ProcessClientSubmitSmTimer_Elapsed", "SUBMITSMRESP FAILED TO PARSE MESSAGE ID", submitSmResp.MessageId, "");
          return;
         }
        }
        break;

       case MessageFormat.DecToHex:
        {
         if (!int.TryParse(submitSmResp.MessageId, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
         {
          DbLayer.AddToLog("ERROR", "Controller::ProcessClientSubmitSmTimer_Elapsed", "SUBMITSMRESP FAILED TO PARSE MESSAGE ID", submitSmResp.MessageId, "");
          return;
         }
        }
        break;

       case MessageFormat.ToHash:
        {
         value = submitSmResp.MessageId.GetHashCode();
        }
        break;

       default:
        DbLayer.AddToLog("ERROR", "Controller::ProcessClientSubmitSmTimer_Elapsed", "SUBMITSMRESP MESSAGEID UNKNOWN FORMAT", submitSmResp.MessageId, "");
        return;
      }

      var submitSmRespExtension = new SubmitSmRespExtension
       {
        Sequence = (int)submitSmResp.Sequence,
        DestAddr = long.Parse(submitSmResp.Request.DestAddr),
        DestAddrTon = submitSmResp.Request.DestAddrNpi,
        DestAddrNpi = submitSmResp.Request.DestAddrTon,
        SourceAddr = submitSmResp.Request.SourceAddr,
        SourceAddrTon = submitSmResp.Request.SourceAddrTon,
        SourceAddrNpi = submitSmResp.Request.SourceAddrNpi,
        ServerMessageId = value,
        OriginalMessageId = submitSmResp.MessageId,
        Origin = "INBOUND",
        Status = submitSmResp.Status.ToString(),
        DataCoding = GetDataCoding(submitSmResp.Request.DataCoding),
        IsReportSent = false,
       };

      SubmitSmRespCollector.Enqueue(submitSmRespExtension);
     }
    }
   }
   catch (Exception ex)
   {
    DbLayer.AddToLog("ERROR", "Controller::ProcessClientSubmitSmTimer_Elapsed", ex.Message, ex.StackTrace, ex.Source);
   }
  }

  private static void ProcessClientSubmitSmTimer_Elapsed(object sender, ElapsedEventArgs e)
  {
   submitSmTimer.Enabled = false;

   var task = new Task(() =>
    {
     try
     {
      var unsentMessages = DbLayer.GetUnsentMessages();

      if (unsentMessages == null || unsentMessages.Tables.Count != 1 || unsentMessages.Tables[0].Rows.Count <= 0)
      {
       return;
      }

      var tableCollection = unsentMessages.Tables[0];

      foreach (DataRow row in tableCollection.Rows)
      {
       var sequence = Convert.ToInt32(row["sequence"]);
       var destAddr = row["destAddr"].ToString();
       var destAddrNpi = Convert.ToByte(row["destAddrNpi"]);
       var destAddrTon = Convert.ToByte(row["destAddrTon"]);
       var sourceAddr = row["sourceAddr"].ToString();
       var sourceAddrNpi = Convert.ToByte(row["sourceAddrNpi"]);
       var sourceAddrTon = Convert.ToByte(row["sourceAddrTon"]);
       var messageText = row["messageText"].ToString();
       var sequenceNumber = Convert.ToByte(row["sequenceNumber"]);
       var referenceNumber = Convert.ToInt32(row["referenceNumber"]);
       var total = Convert.ToByte(row["total"]);
       var dataCoding = row["dataCoding"].ToString();
       var bitEncoding = Convert.ToByte(row["bitEncoding"]);

       Guid clientMessageId;

       Guid.TryParse(row["clientMessageId"].ToString(), out clientMessageId);

       DataCodings dataCodings;

       var clientExtension = clientCollection[sequence % clientCollection.Count];

       if (!Enum.TryParse(dataCoding, true, out dataCodings))
       {
        DbLayer.AddToLog("ERROR", "Controller::ProcessClientSubmitSmTimer_Elapsed", "FAILED TO PARSE DATACODING", dataCoding, "");
        return;
       }

       #region SUBMIT SM RESP

       var pduBuilder = SMS.ForSubmit().From(sourceAddr, sourceAddrTon, sourceAddrNpi).To(destAddr, destAddrTon, destAddrNpi).Text(messageText).DeliveryReceipt();

       foreach (var pdu in pduBuilder.Create(clientExtension.SmppClient))
       {
        pdu.Sequence = (uint)sequence;

        pdu.UserDataPdu = clientExtension.SmppClient.GetMessageBytes(messageText, dataCodings);

        if (total > 1)
        {
         switch (bitEncoding)
         {
          case 8:
           pdu.UserDataPdu.Headers.Add(new ConcatenatedShortMessages8bit(Convert.ToByte(referenceNumber), Convert.ToByte(total), Convert.ToByte(sequenceNumber)));
           break;

          case 16:
           pdu.UserDataPdu.Headers.Add(new ConcatenatedShortMessage16bit(Convert.ToUInt16(referenceNumber), Convert.ToByte(total), Convert.ToByte(sequenceNumber)));
           break;

          default:
           pdu.UserDataPdu.Headers.Add(new ConcatenatedShortMessages8bit(Convert.ToByte(referenceNumber), Convert.ToByte(total), Convert.ToByte(sequenceNumber)));
           break;
         }
        }

        clientExtension.SmppClient.SubmitAsync(pdu);
       }

       #endregion
      }
     }
     catch (Exception ex)
     {
      DbLayer.AddToLog("ERROR", "Controller::ProcessClientSubmitSmTimer_Elapsed", ex.Message, ex.StackTrace, ex.Source);
     }
     finally
     {
      submitSmTimer.Enabled = true;
     }
    }, TaskCreationOptions.LongRunning);

   task.Start();
  }

alt
Site Admin
Posts: 985
Joined: Tue Apr 25, 2006 9:45 am

Re: SubmitAsync memory consumption without deallocation

Post by alt » Fri Sep 11, 2015 9:08 am

Hi,

Possible you don't empty SubmitSmRespCollector and DeliverSmCollector. When you do it in another thread you need to use lock on LockSubmitComplete or even better to use SubmitSmRespCollector and DeliverSmCollector as lock objects.
Alexandr.Unifun
Posts: 6
Joined: Thu Dec 05, 2013 4:51 pm

Re: SubmitAsync memory consumption without deallocation

Post by Alexandr.Unifun » Tue Sep 15, 2015 6:29 am

Hello Alexei I can confirm that there is bug, we made simple test using SybmitAsync and its look like Action Queue doesnt dequie item after Consume().
We recieve and send 20 000 for test please see screen for more details.

Await your responce.
Attachments
Memory Usage Problem.png
Memory Usage Problem.png (154.39 KiB) Viewed 11360 times
alt
Site Admin
Posts: 985
Joined: Tue Apr 25, 2006 9:45 am

Re: SubmitAsync memory consumption without deallocation

Post by alt » Tue Sep 15, 2015 8:24 am

Which version do you use?
Alexandr.Unifun
Posts: 6
Joined: Thu Dec 05, 2013 4:51 pm

Re: SubmitAsync memory consumption without deallocation

Post by Alexandr.Unifun » Tue Sep 15, 2015 8:59 am

1.1.8.0
alt
Site Admin
Posts: 985
Joined: Tue Apr 25, 2006 9:45 am

Re: SubmitAsync memory consumption without deallocation

Post by alt » Tue Sep 15, 2015 11:50 am

Yes, in this version was a memory leak
You need to upgrade to latest version
Locked