Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
spiritual bypass
Feb 19, 2008

Grimey Drawer

more falafel please posted:

- you still have to manage memory/resources, in that your code needs to be Correct or you'll have tons of leaks. If you're writing a microservice that's alive for 100ms, this is fine, I guess

This is the PHP execution model. Request comes in, program spits out a response and terminates without ever actually doing any garbage collection.

Adbot
ADBOT LOVES YOU

OddObserver
Apr 3, 2009

more falafel please posted:

We have this argument every few months but downsides:

- you still have to manage memory/resources, in that your code needs to be Correct or you'll have tons of leaks. If you're writing a microservice that's alive for 100ms, this is fine, I guess
- managing memory/resources is dependent on systems you do not have control over, i.e. the garbage collector. In many cases it may even be explicitly nondeterministic.
- GC promotes a style of programming where you don't think about managing resources, because "GC does it for you"
- GC is slow as balls, so if your application has any real-time requirements, you now have to defensively program around the GC. Don't do string manipulation! Now you're explicitly managing your own memory, with all the pitfalls that entails, without actually having determinism over memory management.

It's a common mistake to think that GCd languages protect against memory leaks. They don't, but they protect against use-after-frees which is arguably more important.

(malloc/free is also far less predictable than people tend to think, though magnitudes less noticeably so than GC).

more falafel please
Feb 26, 2005

forums poster

OddObserver posted:

It's a common mistake to think that GCd languages protect against memory leaks. They don't, but they protect against use-after-frees which is arguably more important.

(malloc/free is also far less predictable than people tend to think, though magnitudes less noticeably so than GC).

Right, plus if you're doing anything real-time, any temporary allocations are your enemy, even if they're handled "correctly". Short-term allocations mean GC is going to run eventually (or you run out of memory, either one is bad). In, say, a game that has 16ms to render a complete frame, GC running during anything interactive is Very Bad.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

more falafel please posted:

Right, plus if you're doing anything real-time, any temporary allocations are your enemy, even if they're handled "correctly". Short-term allocations mean GC is going to run eventually (or you run out of memory, either one is bad). In, say, a game that has 16ms to render a complete frame, GC running during anything interactive is Very Bad.

The bigger problem is that the illusion makes people (primarily those who haven't shipped similar projects before) believe they don't need to care. And it's incredibly difficult to try to care about resource management after you've built up a few hundred thousand lines of code and need to hit a ship date.

I've spent way more time educating people about why they still need to care about memory than I would in environments where it's more explicit that you need to care. This is also the most amusing thing about people who maintain c++ elitism in comparison to something like unity. At least they usually have the facilities to resolve the problems. IMO it's a much harder problem to deal with in a managed language, if only due to the cultural issues and the need to educate junior staff on needing to care about something that "is done for them".

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
If you want predictability you want to start doing things like arenas - grab a chunk of memory for each request, allocate linearly within that chunk for any intra-request allocations, release the entire chunk back to a shared pool when done. Smooth and simple and fast, no rummaging around freelists or dealing with fragmentation.

more falafel please
Feb 26, 2005

forums poster

leper khan posted:

The bigger problem is that the illusion makes people (primarily those who haven't shipped similar projects before) believe they don't need to care. And it's incredibly difficult to try to care about resource management after you've built up a few hundred thousand lines of code and need to hit a ship date.

I've spent way more time educating people about why they still need to care about memory than I would in environments where it's more explicit that you need to care. This is also the most amusing thing about people who maintain c++ elitism in comparison to something like unity. At least they usually have the facilities to resolve the problems. IMO it's a much harder problem to deal with in a managed language, if only due to the cultural issues and the need to educate junior staff on needing to care about something that "is done for them".

Yup. We did a port of a Unity game to console and had two engineers assigned to memory optimizations (mostly just doing pooled object allocs so that GC was more predictable and could be handled at level transition) for over a year. Not that you don't have to care about that stuff in, say UE4, but liberal use of ref-counted smart pointers and auto allocation means that you have to explicitly care about it. Resource management isn't *hard*, but you need to do it. You still need to do it in managed languages/environments, and it's harder to do.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

more falafel please posted:

Yup. We did a port of a Unity game to console and had two engineers assigned to memory optimizations (mostly just doing pooled object allocs so that GC was more predictable and could be handled at level transition) for over a year. Not that you don't have to care about that stuff in, say UE4, but liberal use of ref-counted smart pointers and auto allocation means that you have to explicitly care about it. Resource management isn't *hard*, but you need to do it. You still need to do it in managed languages/environments, and it's harder to do.

My biggest pain point in C#/Unity is not having RAII semantics or deterministic calling of finalizers. Scope operator is so useful in c++. Close second is equality comparison on null being so bananas that eliminating them has been the largest single performance improvement on multiple projects.

That said I just got a job where we have a custom engine and I desperately look forward to maneuvering to the group working in unity.
:smith:

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man

leper khan posted:

Close second is equality comparison on null being so bananas that eliminating them has been the largest single performance improvement on multiple projects.


Wait what

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

Phobeste posted:

Wait what

I'm guessing it's the possible operator overloading of == / .Equals() screwing up hot paths?

I remember one time I had to write a small piece of code for a .NET library that needed to efficiently check for nulls and only nulls, and the correct way to do so was to use the static invocation Object.ReferenceEquals(butt, null).

Admiral H. Curtiss
May 11, 2010

I think there are a bunch of people who can create trailing images. I know some who could do this as if they were just going out for a stroll.

Phobeste posted:

Wait what

They overload == to call out to native code so that a check of a == null returns true if the native object is destroyed even if the C# reference still exists.

https://blog.unity.com/technology/custom-operator-should-we-keep-it

Xarn
Jun 26, 2015
Unity :v:

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

Phobeste posted:

Wait what

Admiral H. Curtiss posted:

They overload == to call out to native code so that a check of a == null returns true if the native object is destroyed even if the C# reference still exists.

https://blog.unity.com/technology/custom-operator-should-we-keep-it

Exactly that. In addition to the perf issues, you also don't get to use the `?.` operator on anything that inherits `UnityEngine.Object` because it sidesteps their overload (because the CLR assumes you're not _that_ dumb) and gives you inconsistent and nondeterministic results. At least the common IDEs warn you about that.

Truly an exemplar of carmacks law.



:bananacoin:

raminasi
Jan 25, 2005

a last drink with no ice

leper khan posted:

My biggest pain point in C#/Unity is not having RAII semantics or deterministic calling of finalizers. Scope operator is so useful in c++. Close second is equality comparison on null being so bananas that eliminating them has been the largest single performance improvement on multiple projects.

That said I just got a job where we have a custom engine and I desperately look forward to maneuvering to the group working in unity.
:smith:

I've never done game dev and this is a sincere question because I'm curious: What do you need deterministic finalizers for that IDisposable won't get you?

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

raminasi posted:

I've never done game dev and this is a sincere question because I'm curious: What do you need deterministic finalizers for that IDisposable won't get you?

The inability to fail to call Dispose() at the correct time and the ability to rely on scope to manage lifetimes instead of the GC so I can accurately manage frame time.

IDisposable mostly just gives me something to clean up things the GC won't capture at GC time. And trying to use it for other things is fairly error prone.

Xarn
Jun 26, 2015

raminasi posted:

I've never done game dev and this is a sincere question because I'm curious: What do you need deterministic finalizers for that IDisposable won't get you?

The use-site has to opt-out from RAII by doing something visibly weird. The use site has to opt-in to calling IDisposable.

Macichne Leainig
Jul 26, 2012

by VG
A coding horror all of my own (and maybe Python library developers) doing.

Did you know that when retrieving the shape of an image, the output tuple is different between OpenCV and Pillow?



You might guess that if you're collecting image data, correctly assigning the height to the "height" feature, as well as the width to the "width" feature is important, and if you, say, incorrectly assume that the first element returned from Image.size is the height of the image, then all your data for your images is going to be wrong. Yay!

I wasted a work day wondering why the data I collected wasn't playing nice. Turns out the data I collected disagreed with reality and that's not good, imagine that. :downs:

raminasi
Jan 25, 2005

a last drink with no ice

leper khan posted:

The inability to fail to call Dispose() at the correct time and the ability to rely on scope to manage lifetimes instead of the GC so I can accurately manage frame time.

IDisposable mostly just gives me something to clean up things the GC won't capture at GC time. And trying to use it for other things is fairly error prone.

Xarn posted:

The use-site has to opt-out from RAII by doing something visibly weird. The use site has to opt-in to calling IDisposable.

Ah, so is this just "you have to remember the using"? (I'm not being snarky, that's a fine objection, I just want to make sure I understand.)

1337JiveTurkey
Feb 17, 2005

I feel like game programming is a somewhat special case here. For most general programming the pauses in modern GCs aren't that significant, it's just this thing that's carried over from the 1990s when it was more of a problem. A modern GC is going to have thread local allocation buffers so allocations are just incrementing a pointer, moving collection so actual garbage has no cost and only the absolute minimum possible work saved for a stop the world pause. Like if it's not enough for your situation, that's fair but there's a lot of situations where it's perfectly fine.

Additionally I think it's fine for memory to have different lifecycle semantics than other forms of resources and can be helpful in that sense. Take a situation where a program needs to get some data from a server at some URL. There's multiple independent threads that may need data from several related URLs but they can share the cached data if they hit the same resource within some time window. This is something where a separate object with a lifecycle independent of the threads to do the downloads (with explicit lifecycles for the network connection), parsing and reinflation of the data can save work for all the worker threads. It can then keep the resulting cache for its lifecycle and discard old data as needed.

Where GC is helpful is that this can hand references to its (presumably immutable) shared data without fears of that data being still live when it wipes it for staleness. Once the shared object is truly no longer touched it can be deleted safely but that's not clear to the program itself without a lot of communication between the threads or simply using GC.

chglcu
May 17, 2007

I'm so bored with the USA.
I haven’t thought this through, but an optional warning when you don’t use a using statement with an IDisposable could maybe help that problem. Guess it doesn’t do anything for instances with a non-local scope, though.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
You can also store it as a class member and get the equivalent of a class which has an IDisposable member automatically itself being IDisposable and doing the right thing by default.

It's just generally a lot less error prone than having to do things manually, just like automatic memory management is a lot less error-prone than manual memory management.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

raminasi posted:

Ah, so is this just "you have to remember the using"? (I'm not being snarky, that's a fine objection, I just want to make sure I understand.)

Yeah, the thing we aren't saying that you also need to keep in mind is the average tenure in the game industry is very short and trends to the beginning of people's careers. There's not a small amount of cleaning up after juniors and chasing bad patterns. Combined with a different set of priorities than general software, and some weirdly lacking areas of common practice (I _still_ run into people who claim game code can't be tested) things can get weird.

Games sort of sit on the edge where the convenient things are nice until they're the root cause of needing to spend an extra couple months of dev time reworking systems. I would unironically rather write game clients in C than C#, but that's not generally an option that's been available to me. I did not hold that view earlier in my career.

Games backends these days look a lot like web backends. So there's less drift there in the problems you run into, how you might think about them, and their solutions.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Protocol7 posted:

A coding horror all of my own (and maybe Python library developers) doing.

Did you know that when retrieving the shape of an image, the output tuple is different between OpenCV and Pillow?



You might guess that if you're collecting image data, correctly assigning the height to the "height" feature, as well as the width to the "width" feature is important, and if you, say, incorrectly assume that the first element returned from Image.size is the height of the image, then all your data for your images is going to be wrong. Yay!

I wasted a work day wondering why the data I collected wasn't playing nice. Turns out the data I collected disagreed with reality and that's not good, imagine that. :downs:

The fault here is with those libraries - both of them - for returning tuples, instead of objects with named attributes for Height and Width.

NihilCredo posted:

I'm guessing it's the possible operator overloading of == / .Equals() screwing up hot paths?

I remember one time I had to write a small piece of code for a .NET library that needed to efficiently check for nulls and only nulls, and the correct way to do so was to use the static invocation Object.ReferenceEquals(butt, null).

Correct me if I'm wrong but that's exactly what "is null" does, and until they added "is null" to the language it was the single correct way to compare with null any time you were implementing comparison for a type that overrides == and !=.

Qwertycoatl
Dec 31, 2008

Hammerite posted:

The fault here is with those libraries - both of them - for returning tuples, instead of objects with named attributes for Height and Width.

It's possible that one of the libraries has a deeper fault - the jpeg file format allows you to specify the orientation of the image instead of just assuming that the data starts at the topleft. Careless library writers don't pay attention to that and can give you images that are rotated by 90 degrees or flipped.

Macichne Leainig
Jul 26, 2012

by VG

Qwertycoatl posted:

It's possible that one of the libraries has a deeper fault - the jpeg file format allows you to specify the orientation of the image instead of just assuming that the data starts at the topleft. Careless library writers don't pay attention to that and can give you images that are rotated by 90 degrees or flipped.

This actually burned me a bit too because of I believe mixed usage of PIL and OpenCV in this third party library I'm using (mmdetection, if anyone is curious). One of them handles EXIF transpositions properly when loading an image from disk and the other does not.

Simple solution was to just burn through all the images, apply necessary EXIF transpositions and re-save the image to disk and strip EXIF. :shrug:

Xarn
Jun 26, 2015

raminasi posted:

Ah, so is this just "you have to remember the using"? (I'm not being snarky, that's a fine objection, I just want to make sure I understand.)

Basically yeah, also automatic composition (in RAII model types propagate disposal automatically, in IDispose afaik they do not).

Absurd Alhazred
Mar 27, 2010

by Athanatos

more falafel please posted:

We have this argument every few months but downsides:

- you still have to manage memory/resources, in that your code needs to be Correct or you'll have tons of leaks. If you're writing a microservice that's alive for 100ms, this is fine, I guess
- managing memory/resources is dependent on systems you do not have control over, i.e. the garbage collector. In many cases it may even be explicitly nondeterministic.
- GC promotes a style of programming where you don't think about managing resources, because "GC does it for you"
- GC is slow as balls, so if your application has any real-time requirements, you now have to defensively program around the GC. Don't do string manipulation! Now you're explicitly managing your own memory, with all the pitfalls that entails, without actually having determinism over memory management.

The Unity people wanted to make their basic engine in C#, so they settled on a subset of C# that circumvents the GC. Some early reporting here

chglcu
May 17, 2007

I'm so bored with the USA.
The DOTS stuff just seems like a workaround for C# being a pretty poor language choice for games. I’d rather work in a language that natively supports controlling memory layout than hack it into some other language. It’s also Unity in the 2020s so you can’t trust that it’ll ever actually be feature complete before they deprecate it in favor of some other shiny thing.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

chglcu posted:

The DOTS stuff just seems like a workaround for C# being a pretty poor language choice for games. I’d rather work in a language that natively supports controlling memory layout than hack it into some other language. It’s also Unity in the 2020s so you can’t trust that it’ll ever actually be feature complete before they deprecate it in favor of some other shiny thing.

DOTS is a very troubled project. That's already essentially happened to it twice.

It's important to realize that though unity frames themselves as a game engine company to the games industry, essentially all of their revenue is from ads.

QuarkJets
Sep 8, 2008

Protocol7 posted:

A coding horror all of my own (and maybe Python library developers) doing.

Did you know that when retrieving the shape of an image, the output tuple is different between OpenCV and Pillow?



You might guess that if you're collecting image data, correctly assigning the height to the "height" feature, as well as the width to the "width" feature is important, and if you, say, incorrectly assume that the first element returned from Image.size is the height of the image, then all your data for your images is going to be wrong. Yay!

I wasted a work day wondering why the data I collected wasn't playing nice. Turns out the data I collected disagreed with reality and that's not good, imagine that. :downs:

This comes down to what's convenient for processing vs parlance and is encountered at some point by everyone who works with image data. When we talk about images we tend to order things by (width, height), but in row-major ordering the data is stored as (height, width). Note that PIL's size attribute doesn't say anything about how the data is stored, just that it returns a tuple of (width, height). Numpy and opencv return the actual shape of the array in memory, which is (height, width) if you use default row-major ordering

This discrepancy exists because PIL sucks poo poo through a straw, hth

repiv
Aug 13, 2009

leper khan posted:

DOTS is a very troubled project. That's already essentially happened to it twice.

It's important to realize that though unity frames themselves as a game engine company to the games industry, essentially all of their revenue is from ads.

And just now they've acquired WETA, so look forward to some half assed integration between the Unity engine and WETAs tooling, that will never leave alpha

QuarkJets
Sep 8, 2008

Hammerite posted:

The fault here is with those libraries - both of them - for returning tuples, instead of objects with named attributes for Height and Width.

Both libraries provide those values as attributes of the image objects, but they return tuples if you want all of the dimensions

It'd be really dumb to return some sort of Size object instead of an iterable of integers and I think this is a sign that you have a severe case of Java Poisoning

QuarkJets fucked around with this message at 22:37 on Nov 9, 2021

champagne posting
Apr 5, 2006

YOU ARE A BRAIN
IN A BUNKER

QuarkJets posted:

Both libraries provide those values as attributes of the image objects, but they return tuples if you want all of the dimensions

It'd be really dumb to return some sort of Size object instead of an iterable of integers and I think this is a sign that you have a severe case of Java Poisoning

Having a method that returns a size map would be nice for these situations tho. You can have both it's no biggie.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

QuarkJets posted:

It'd be really dumb to return some sort of Size object instead of an iterable of integers and I think this is a sign that you have a severe case of Java Poisoning

What

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
It would be really dumb to [do the most sensible thing in the circumstances], clearly what it should do instead is [obviously awful cowboy coder bullshit]. If you disagree then you're one of the bad people, and my enemy.

OddObserver
Apr 3, 2009

Hammerite posted:

It would be really dumb to [do the most sensible thing in the circumstances], clearly what it should do instead is [obviously awful cowboy coder bullshit]. If you disagree then you're one of the bad people, and my enemy.

I think someone here needs to be sentenced to spending time with STL map containers. A few ->second.first's and the desire to use these sorts of types for public interfaces flows right out of the window.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

QuarkJets posted:

Both libraries provide those values as attributes of the image objects, but they return tuples if you want all of the dimensions

It'd be really dumb to return some sort of Size object instead of an iterable of integers and I think this is a sign that you have a severe case of Java Poisoning

An object responding to "width" and "height" doesn't exclude it also being an iterable of integers? It's strictly more useful.

Xerophyte
Mar 17, 2008

This space intentionally left blank
I don't know enough about OpenCV to know if it does this sanely but you may reasonably want a data processing library to be able to rearrange your WxHx3 RGB image to an 3xHxW image for an algorithm that prefers a channel-column-row traversal order, or to a 16x16x3x(H/16)x(W/16) tiling, or something worse. You quickly reach the point at which trying to shoehorn in contextually specific notions that one dimension is going to be "width" and another "color channel" is more confusing than helpful. If that's the standard use case then it makes sense for your library to import all its data as abstract multidimensional arrays to begin with and let the programmer slice, rearrange and transform them freely.

PIL and Pillow are not abstract data processing libraries, probably should have named properties for their dimensions, and are generally hot garbage last I checked. I'd suggest OpenImageIO, which incidentally has all that sort of data in a ImageSpec class full of named properties including width and height, but installing OIIO for just python is likely still a pain.

QuarkJets
Sep 8, 2008

Xerophyte posted:

I don't know enough about OpenCV to know if it does this sanely but you may reasonably want a data processing library to be able to rearrange your WxHx3 RGB image to an 3xHxW image for an algorithm that prefers a channel-column-row traversal order, or to a 16x16x3x(H/16)x(W/16) tiling, or something worse. You quickly reach the point at which trying to shoehorn in contextually specific notions that one dimension is going to be "width" and another "color channel" is more confusing than helpful. If that's the standard use case then it makes sense for your library to import all its data as abstract multidimensional arrays to begin with and let the programmer slice, rearrange and transform them freely.

PIL and Pillow are not abstract data processing libraries, probably should have named properties for their dimensions, and are generally hot garbage last I checked. I'd suggest OpenImageIO, which incidentally has all that sort of data in a ImageSpec class full of named properties including width and height, but installing OIIO for just python is likely still a pain.

That's the thing though, PIL images do have named properties for width and height. They are named "width" and "height", and they are integers. The OP used a method that happens to return tuple of (width, height)

redleader
Aug 18, 2005

Engage according to operational parameters
recent versions of c# and .net have recognized that sometimes allocations are bad, and have added a bunch of (pretty niche) features to give devs more control over memory while still remaining memory-safe. it'll be interesting to see if these end up being used anywhere and/or making a difference

Adbot
ADBOT LOVES YOU

Tei
Feb 19, 2011

gently caress speed, gently caress optimizing memory

just write good code that is also easy to read and understand

If the cost is some expensive invisible operation is invoqued when doing ==. So be it.

Edit:
this thread need good old WTFeries. I am doing my part.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply