Page 1 of 1

SubmitAsync memory consumption without deallocation

Posted: Mon Sep 07, 2015 7:49 am
by Kernighan
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();
  }


Re: SubmitAsync memory consumption without deallocation

Posted: Fri Sep 11, 2015 9:08 am
by alt
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.

Re: SubmitAsync memory consumption without deallocation

Posted: Tue Sep 15, 2015 6:29 am
by Alexandr.Unifun
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.

Re: SubmitAsync memory consumption without deallocation

Posted: Tue Sep 15, 2015 8:24 am
by alt
Which version do you use?

Re: SubmitAsync memory consumption without deallocation

Posted: Tue Sep 15, 2015 8:59 am
by Alexandr.Unifun
1.1.8.0

Re: SubmitAsync memory consumption without deallocation

Posted: Tue Sep 15, 2015 11:50 am
by alt
Yes, in this version was a memory leak
You need to upgrade to latest version