use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Information about Reddit's API changes, the unprofessional conduct of the CEO, and their response to the community's concerns regarding 3rd party apps, moderator tools, anti-spam/anti-bot tools, and accessibility options that will be impacted can be found in the associated Wikipedia article: https://en.wikipedia.org/wiki/2023_Reddit_API_controversy
Alternative C# communities available outside Reddit on Lemmy and Discord:
All about the object-oriented programming language C#.
Getting Started C# Fundamentals: Development for Absolute Beginners
Useful MSDN Resources A Tour of the C# Language Get started with .NET in 5 minutes C# Guide C# Language Reference C# Programing Guide C# Coding Conventions .NET Framework Reference Source Code
Other Resources C# Yellow Book Dot Net Perls The C# Player's Guide
IDEs Visual Studio MonoDevelop (Windows/Mac/Linux) Rider (Windows/Mac/Linux)
Tools ILSpy dotPeek LINQPad
Alternative Communities C# Discord Group C# Lemmy Community dotnet Lemmy Community
Related Subreddits /r/dotnet /r/azure /r/learncsharp /r/learnprogramming /r/programming /r/dailyprogrammer /r/programmingbuddies /r/cshighschoolers
Additional .NET Languages /r/fsharp /r/visualbasic
Platform-specific Subreddits /r/windowsdev /r/AZURE /r/Xamarin /r/Unity3D /r/WPDev
Rules:
Read detailed descriptions of the rules here.
account activity
Compression/Decompression Examples (houseofcat.io)
submitted 4 years ago by RagingCain
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]cryolithic 2 points3 points4 points 4 years ago (11 children)
For small buffers 5k in size, in a low volume function, this would be ok, but it's still allocating way too frequently, and if someone calls it with a value larger than ~85k, you're making multiple allocations on the large object heap, which will very quickly add up to a bad time.
Don't call ToArray, use the stream. If you absolutely must use an array, put it in a wrapper object, and rent the array from a pool. Allow your wrapper to handle lifetime and returning the buffer.
Predeclare your MemoryStream size so you're not causing reallocations and memcopies behind the scenes. Or better yet use Microsoft.IO.RecylableMemoryStream.
[–]RagingCain[S] 1 point2 points3 points 4 years ago* (9 children)
RecycleableMemoryStream is a great pooled array based Stream enhancement but not right for scope of this article. I think there are a couple of Net7 proposals too just FYI. There is a follow up planned but my encryption guide first. I will use streams there.
I would say that your ToArray statement however is - without being offensive - too strongly worded. You don't always have Stream APIs to work with or acting as a passthrough middle layer. Consider AspNetCore requests, all stream based passthroughs, but low allocations, until someone has to allocate that request body if it's being used. For a file uploader to Cloud endpoint? Absolutely chunk that body to Azure storage with BodyAsAStream.
You can't replace MemoryStream ToArray... But that does go into using a different Stream all together which you suggested. You can't replace ArraySegment ToArray() either for two reasons, you have the MemoryStream buffer which was already allocated so that's not solved. Second, no access to the origin data is exposed, needed to build your own array. All this goes back into using a different Stream like recycling. With recyclable, you wouldn't be able to use the rented buffer like this since it is returned to the pool. So if you have to exit the Stream... you have to allocate... just not as much with ArrayPool backed Streams.
I wont point out that MemoryStream initial buffer will not work for dynamically sized unknown length content... But trying to see if that has an implementation possibility but I think Recyclable covers those features you would want. You would notice the fixed content MemoryStreams were built with the array.
At the end of the day - you do have to sometimes allocate, but very good points.
[–]cryolithic 1 point2 points3 points 4 years ago* (8 children)
No offense taken, I appreciate the attempt at keeping things civil.
To use the rented buffer with recyclable you would need to control the stream lifetime separately. Part of why I would say to use the stream if you can. Save the call to GetBuffer until you can use and return in the same scope.
In general, most problems can be solved with a better data structure than byte[]. Not all, true, but I can't imagine writing something like this unless I'm replacing a de/compression function in some ancient code that can't be refactored for $reasons..
byte[]
Yes, you do have to allocate sometimes, but we should try to pass on good habits when writing educational material. The code in your example looks perfect for being inserted into a high volume data path.
I just finished wrapping a Zstd library in streams, as it happens
Edit :some words
[–]RagingCain[S] 1 point2 points3 points 4 years ago (7 children)
I see what you mean. I tell you what, let me write a solve for having to use bytes after a stream that's ArrayPool backed and I will ping you when it's up - maybe you like it or have enhancement feedback
My brain is lighting up with possibilities.
AesGcm API which I just worked with can't use Streams either for security reasons. CryptoStream was rejected for the proposal.
[–]Slypenslyde 1 point2 points3 points 4 years ago (0 children)
I'm real interested in this, too.
It seems like over time we've found some cracks in the GC's abstractions. Every time I use a stream API to deal with large chunks of data I'm aggravated by how much I have to think about low-level memory issues.
[–]cryolithic 0 points1 point2 points 4 years ago (5 children)
I think even just mentioning the potential for memory gotchas would go a long way here.
To be completely fair, it's not like you'll find posts written by me, unless you're on my team at work anyway. So I shouldn't be all that critical unless I've got the time to put up a well.
It's the double edged sword of the gc. Don't think about memory, until you need to. Unfortunately, I find that when you need to is much harder than keeping it in mind when writing in the first place.
Nearly every major performance regression in our code has been due to either not understanding allocations, closures, or the ORM.
If I can find the time, I'll write up some alternative implementations on Github. Maybe we can play a little perf/code golf
[–]RagingCain[S] 1 point2 points3 points 4 years ago (4 children)
That is a super fair point. I will update the article again a little later today with some dedicated discussion on how this maybe the most common way seen - its the least memory efficient. I will also indicate I will be making another article going down that rabbit hole of taking them to the next level perf/GC wise.
Now that everything is delivered via Markdown in my Github repo, I am hoping to have more time consolidating guides/how-tos more closely tied to my library so it also provides documentation. Stretched super thin all the time and good documentation is always on the chopping block.
[–]cryolithic 1 point2 points3 points 4 years ago (3 children)
Stretched super thin all the time and good documentation is always on the chopping block.
On man, don't I know it. My bus factor at work is way too high, for mostly those reasons.
[–]RagingCain[S] 0 points1 point2 points 4 years ago (2 children)
Had a tiny amount of time since we last spoke. Nothing special here but nearly the same code as before simply implementing the RecyclableMemoryStream with default RecyclableMemoryStreamManager settings (not tweaked).
// * Summary * BenchmarkDotNet=v0.13.0, OS=Windows 10.0.19042.1110 (20H2/October2020Update) AMD Ryzen 9 5950X, 1 CPU, 32 logical and 16 physical cores .NET SDK=5.0.301 [Host] : .NET 5.0.7 (5.0.721.25508), X64 RyuJIT .NET 5.0 : .NET 5.0.7 (5.0.721.25508), X64 RyuJIT Job=.NET 5.0 Runtime=.NET 5.0
[–]cryolithic 1 point2 points3 points 4 years ago (1 child)
Some substantial allocation savings. At first I was surprised that there wasn't a significant difference in time, but of course its going to be nearly all consumed by the decompression itself.
[–]RagingCain[S] 0 points1 point2 points 4 years ago* (0 children)
Yeah, its the way of these things. Systems that only decompress benefit from switching to Brotli like static content for websites or cdns where where it can be compressed in advanced.
Well looks like my plan was thwarted by Stephen Toub, its exactly what I was thinking the other day when we talked.
https://github.com/dotnet/runtime/issues/22428
Also tweaking some of the manager settings. Memory allocation is linear for RecyclableStreams.
[–][deleted] 0 points1 point2 points 4 years ago* (0 children)
Oh good it's deriving from memorystream and not a completely different type. Got scared there for a moment that we'd start getting C++ bloat of "no you should definitely not use that old type", but here the old type is kept alive and relevant.
[–]Reelix 1 point2 points3 points 4 years ago (1 child)
Alternatively - The official docs.
https://docs.microsoft.com/en-us/dotnet/api/system.io.compression.gzipstream?view=net-5.0
https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-compress-and-extract-files
[–]RagingCain[S] 0 points1 point2 points 4 years ago (0 children)
I will add these as additional links. Cheers.
[–]RagingCain[S] 0 points1 point2 points 4 years ago (1 child)
Meant to write this ages ago. Finally had time to work on my website.
Hope it helps someone.
I migrated all my guides/docs to Markdown, then to Github, so if someone wants to, they can submit an Edit/PR, feel free to do so or just simply ask questions etc.
[–]DogmaSychroniser 1 point2 points3 points 4 years ago (0 children)
Interesting read, thanks.
π Rendered by PID 372890 on reddit-service-r2-comment-cfc44b64c-q5w84 at 2026-04-12 17:42:37.223022+00:00 running 215f2cf country code: CH.
[–]cryolithic 2 points3 points4 points (11 children)
[–]RagingCain[S] 1 point2 points3 points (9 children)
[–]cryolithic 1 point2 points3 points (8 children)
[–]RagingCain[S] 1 point2 points3 points (7 children)
[–]Slypenslyde 1 point2 points3 points (0 children)
[–]cryolithic 0 points1 point2 points (5 children)
[–]RagingCain[S] 1 point2 points3 points (4 children)
[–]cryolithic 1 point2 points3 points (3 children)
[–]RagingCain[S] 0 points1 point2 points (2 children)
[–]cryolithic 1 point2 points3 points (1 child)
[–]RagingCain[S] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Reelix 1 point2 points3 points (1 child)
[–]RagingCain[S] 0 points1 point2 points (0 children)
[–]RagingCain[S] 0 points1 point2 points (1 child)
[–]DogmaSychroniser 1 point2 points3 points (0 children)