5

It is 2019 and we have a banking project which uses mainframe as data store and transactions.

We are using DTO's (Commarea, plain c# class) that is converted to plain string (this is how mainframe works) then sent to Mainframe.

While converting a class to string representation we use several string operations such as substring, pad left, pad right, trim etc.

As you can imagine, this causes several string allocations and hence garbage collection. It is usually at generation 0 but still.

Especially types like Decimal which is a Pack type in mainframe that fits into 8 bytes creates several strings.

I tried using ReadonlySpan<char> for example for substring. See example.

However, there are operations like PadRight, PadLeft which is not avaiable, because it is a read only span.

Update: To clarify a part of conversion happens as follows:

val.Trim().Substring(5).PadRight(10);

I know that this creates 3 string. I know strings are immutable. My question is about doing the above operation with ReadonlySpan or Memory.

I can not use ReadonlySpan only for substring because as soon as I call ToString method I m losing the benefits.

I have to call ToString all the way at the end.

Is there another construct that supports other operations behind substring, that I can actually add remove data to the memory?

Thanks.

DarthVader
  • 52,984
  • 76
  • 209
  • 300
  • Have you considered making DTO's immutable with Copy-on-write feature? with immutable types, you can cache the resulting strings and they will always be valid for immutable instances. use string builder for generating strings. you can combine Copy-on-write with flyweight pattern (use shared memory as much as possible, common example is string interning). – M.kazem Akhgary Feb 02 '19 at 17:25
  • 2
    Is GC actually a performance issue for your application, or are you looking for a solution to a nonexistent problem? – Ian Kemp Feb 02 '19 at 17:25
  • ^Agreed. Not saying this is the case here, but make sure you're not falling into a [premature optimization](http://wiki.c2.com/?PrematureOptimization) scenario – devNull Feb 02 '19 at 18:26
  • 1
    Strings in .NET are immutable, so any manipulation will create a new string object, involving copying of data. Mainframe strings are just ``char`` arrays, so if your application is sensitive enough to all the copying involved in creating strings, you may want/need to rewrite some basic string functionality for ``char`` arrays, and use these instead. – dumetrulo Feb 02 '19 at 22:15
  • Ok folks. i have updated the question. I am familiar with .net so your comments are not helpful. – DarthVader Feb 03 '19 at 08:41
  • 2
    This is not actually a problem until your profiler says it is a problem. And you shouldn't try to solve things that aren't problems. As you know, strings in .NET are immutable. If there was a massive performance problem here, you wouldn't be the first one to notice it. The run-time is optimized to handle it. – Cody Gray - on strike Feb 03 '19 at 08:41
  • @CodyGray I am curious about manipulating memory. I am aware that I need a concrete proof to indicate there is a perf problem but that is not my claim here. I want to find out how to use and if there is a way to efficiently work with memory for string manipulation. Thanks for your comment. – DarthVader Feb 05 '19 at 11:18

1 Answers1

0

Using ReadOnlySpan can help reduce the number of string allocations in your code, but it won't eliminate them completely. This is because ReadOnlySpan is a read-only view of a sequence of characters, so you cannot modify the underlying data using a ReadOnlySpan.

To avoid unnecessary string allocations, you can use the string.AsSpan() method to get a ReadOnlySpan view of a string, and then use the Span.Slice() method to get substrings without allocating new strings. For example, you could use the following code to get a substring of a string without allocating a new string:

string val = "Hello world";
ReadOnlySpan<char> span = val.AsSpan();
ReadOnlySpan<char> substring = span.Slice(5);

However, as mentioned earlier, you cannot use ReadOnlySpan to modify the underlying data, so you will still need to allocate new strings for operations like PadRight and PadLeft. To avoid these allocations, you can use a StringBuilder to build up the string piece by piece, and then call ToString() on the StringBuilder when you're done. This will allow you to perform string operations without allocating new strings for each operation.

In summary, using ReadOnlySpan can help reduce the number of string allocations in your code, but it won't eliminate them completely. To avoid allocating new strings for each string operation, you can use a StringBuilder to build up the final string piece by piece.

string val = "Hello world";

StringBuilder builder = new StringBuilder(val.Length);

// Trim the string
builder.Append(val.Trim());

// Get a substring starting at the 5th character
builder.Append(val, 5, val.Length - 5);

// Pad the string with spaces to the right, to make it 10 characters long
builder.PadRight(10, ' ');

// Convert the final string to a regular string
string result = builder.ToString();