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
ToxicFrog
Apr 26, 2008


That Turkey Story posted:

Speaking as someone who has worked on multiple professional games that have used lua for gameplay scripting, performance problems do get traced back to lua, through profiling, and it's really not specific to lua either. The problem for us was mainly due to creating lots of objects in lua, which all end up being dynamically allocated and garbage collected. If for every bullet or projectile you're spawning an object in lua, and all of your objects are dynamically typed and all of your function calls are on types in a dynamic language, it does cripple performance, and the worst part is, there's no simple way to parallelize the logic code that is typically implemented in a scripting language, so you end up really hurting without many options.

What's dumb is that most of these things don't need to be dynamically allocated nor does the language need to be dynamically typed.

My point is that these issues can be - and are in many games - solved by "not allocating shitloads of lua objects every frame" and "running independent scripts in separate threads" (which is actually quite easy to do) respectively. Yes, it will never be as fast as writing equivalent code in a language that compiles ahead of time to optimized machine code, but it can be "fast enough", and evidently a lot of development teams consider that a worthwhile tradeoff in exchange for faster development and increased moddability.

That said, I'm certainly interested in suggestions for languages that have better performance characteristics than Lua/LuaJIT while still being threadsafe, suitable for embedding, and capable of on-the-fly script editing and loading.

Adbot
ADBOT LOVES YOU

That Turkey Story
Mar 30, 2003

ToxicFrog posted:

My point is that these issues can be - and are in many games - solved by "not allocating shitloads of lua objects every frame" and "running independent scripts in separate threads" (which is actually quite easy to do) respectively.
If you have to bend over backwards to avoid allocating objects (which is not as trivial as it sounds), you're complicating things. If you simply used a language where you don't have a bunch of implied overhead when simply creating an object that could easily have just been on the stack, none of this would be a problem. Using a scripting language is supposed to make your life easier, not harder. If you have to do things an an unintuitive manner and avoid abstraction for performance reasons, the code only ends up difficult to write, understand, and maintain. There is nothing intrinsic about a scripting language that requires this nonsense, it's just that lua has become common for a variety of reasons -- it's a small language with good support that cooperates well with C++ and C, it's similar to javascript meaning that a lot of people somewhat know it even if they've never written in lua before, it's easy for modders to pick up and write little scripts, etc. Unfortunately, it does not make a great choice when you want to do the bulk of your gameplay programming in it in a complicated game.

Also, you usually cannot simply "run independent scripts in separate threads" nor would that necessarily be a good idea or even fix anything to begin with. First, we're talking about general gameplay code that cannot easily be run concurrently with other scripts (and other code does run at the same time: C++ code runs in parallel occupying the cores that it can, but the lua is actually the bottleneck). Simply running certain scripts concurrently does not scale well, either, even if it were an actual option in our case, which it is not.

ToxicFrog posted:

Yes, it will never be as fast as writing equivalent code in a language that compiles ahead of time to optimized machine code, but it can be "fast enough", and evidently a lot of development teams consider that a worthwhile tradeoff in exchange for faster development and increased moddability.
It depends on the project and what you're doing in scripts. Again, this isn't some hypothetical here, this is actual experience on a game that isn't some casual game, and where the lua isn't simply for basic scripting -- the entirety of the engine is in C++, and the entirety of the gameplay and gui, etc. is in lua, with the idea being that it's easy for modders to work with (which is very true). It's caused a lot of performance problems as the game became more complex.

ToxicFrog posted:

That said, I'm certainly interested in suggestions for languages that have better performance characteristics than Lua/LuaJIT while still being threadsafe, suitable for embedding, and capable of on-the-fly script editing and loading.
That was my question. With LLVM, this should not be as difficult as it used to be. You can even use C++ if you actually wanted to (trust me, I would have loved it, but the modding community probably would not). Lua just happens to be popular at this point because it is an existing solution and it's a simple language that people know. It's good enough for a lot of cases so there's not a huge push for anything else, but many teams do have problems with it, and the more that gameplay code is done in scripts, the more people are going to run into it as a bottleneck.

SavageMessiah
Jan 28, 2009

Emotionally drained and spookified

Toilet Rascal
Angelscript is basically what you're talking about. I don't know what the performance is like though. I do know that this is what most of the gameplay code of Star Ruler is written in.

Toady
Jan 12, 2009

Zombywuf posted:

This is the real horror.

When enabled, Squirrel uses wchar_t for its strings. I haven't tried that feature since I rely on UTF8, but my experience with Squirrel has been good.

Toady fucked around with this message at 20:44 on Sep 15, 2012

God of Mischief
Oct 22, 2010

Suspicious Dish posted:

Their code contribution process is pasting code in wordpress comments. Just want to point that out.

http://phpjs.org/pages/develop

The comments on this page are great

http://phpjs.org/contributions/add/

It's even better when you look at their github page. You have to build their website to work on anything.

Optimus Prime Ribs
Jul 25, 2007

Huh, apparently the dude who made that phpjs abomination is the same guy who made CakePHP (or at least the repo for it is on his account). Whattya know.

Look Around You
Jan 19, 2009

Optimus Prime Ribs posted:

Huh, apparently the dude who made that phpjs abomination is the same guy who made CakePHP (or at least the repo for it is on his account). Whattya know.

I think it's just a fork that he made to include some changes to the source.

Optimus Prime Ribs
Jul 25, 2007

Ah, so it is. I missed the Forked from renansaddam/cakephp part.
That would have been too perfect.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

That Turkey Story posted:

If you have to bend over backwards to avoid allocating objects (which is not as trivial as it sounds), you're complicating things.
WoW UI modders came up with a library that made this fairly easy -- by switching to manual memory management and clearing and reusing tables rather than allocating new ones. The whole thing was hilariously slow compared to the amortized cost of lua's garbage collector, but triggering the GC during combat could lock up the UI for multiple seconds.

That Turkey Story
Mar 30, 2003

Plorkyeran posted:

WoW UI modders came up with a library that made this fairly easy -- by switching to manual memory management and clearing and reusing tables rather than allocating new ones. The whole thing was hilariously slow compared to the amortized cost of lua's garbage collector, but triggering the GC during combat could lock up the UI for multiple seconds.

Yeah, when you have to manually manage memory in a dynamically typed language with GC, I really start to question the benefits of using that language as a scripting language.

PrBacterio
Jul 19, 2000

Plorkyeran posted:

WoW UI modders came up with a library that made this fairly easy -- by switching to manual memory management and clearing and reusing tables rather than allocating new ones. The whole thing was hilariously slow compared to the amortized cost of lua's garbage collector, but triggering the GC during combat could lock up the UI for multiple seconds.
Wait, Lua doesn't have an incremental GC?

The Gripper
Sep 14, 2004
i am winner
In what world would someone even learn to write code this way?:
C++ code:
_beginthread(Function1,0,NULL);
Sleep(1420);
_beginthread(Function2,0,NULL);
Sleep(5100);
_beginthread(Function3,0,NULL);
Sleep(2144);
_beginthread(Function4,0,NULL);
Sleep(13600);
... repeat a few dozen more times in this block, and more elsewhere ...
The Sleep calls are there solely to wait until the thread finishes (original developer benchmarked on their original deployment platform). None of the functions do anything that would necessitate being in a separate thread, none take arguments, and all are intended to complete by the time the next call is made.

I was paid to *fix* this application since the company running it changed some of the hardware it controlled (manufacturing) to a slower profile and the whole thing broke. And by fix, I mean "apply 2 regexp replaces and it's done".

FrantzX
Jan 28, 2007
My first thought was some sort of COM MTA/STA threading issue, but still, why would you sleep the current thread instead of joining the created one?

The Gripper
Sep 14, 2004
i am winner

FrantzX posted:

My first thought was some sort of COM MTA/STA threading issue, but still, why would you sleep the current thread instead of joining the created one?
That was one of my first thoughts, along with "maybe it's just sleeping because the function returns before the machinery actually finalizes", but in that case it would be just as useful to keep it on the main thread and Sleep() after the call returns, which would also prevent issues from slow-response or high processor load messing with timing.

Apparently it had been "intermittently broken" for years, and they only decided to get it fixed now that it was completely broken.

For reference, this was a single-run application that returned machinery to a default position on-demand (usually when unloading/loading materials). Single-threaded, one operation at a time. It's possible the original coder copy/pasted the code from another more complicated package and didn't understand the context, I guess.

The Gripper fucked around with this message at 11:47 on Sep 16, 2012

Zombywuf
Mar 29, 2008

That's real time programming that is.

SavageMessiah
Jan 28, 2009

Emotionally drained and spookified

Toilet Rascal

PrBacterio posted:

Wait, Lua doesn't have an incremental GC?

I does, that sounds like it's more a problem with WoW than anything else.

Edit: vv Welp

SavageMessiah fucked around with this message at 15:41 on Sep 17, 2012

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

PrBacterio posted:

Wait, Lua doesn't have an incremental GC?
Not until Lua 5.1, which was released a year and a half after WoW.

Presto
Nov 22, 2002

Keep calm and Harry on.

DStecks posted:

The typo had no tag. This typo had been undetected and part of a program that ran every day, and somehow never caused an abort, in 20 years.
Welcome to software development. I've fixed one-in-a-million bugs you would expect to see once in a blue moon that occurred every 10 minutes; and bugs in heavily-used code that somehow hadn't been triggered in 5 years.

It's a funny business.

bucketmouse
Aug 16, 2004

we con-trol the ho-ri-zon-tal
we con-trol the verrr-ti-cal
It's time for another round of God gently caress C Forever, starring an associate who will remain nameless and a paraphrase of his code which contains some integers:

code:
int getnum()
{
   const int numbers[10] = {1,2,3,4,5,6,7,8,9,10};
   static int counter = -1;
   counter++;
   return numbers[counter];
}

int main()
{
printf("Let's count!\n");
printf("%d ", getnum());
printf("%d ", getnum());
printf("%d ", getnum());
printf("%d ", getnum());
printf("%d\n", getnum());
printf("Let's count more efficiently!\n");
printf("%d %d %d %d %d\n", getnum(),getnum(),getnum(),getnum(),getnum());
}
Can YOU guess the output?

For bonus points, what's the reasoning for the right->left evaluation?

http://codepad.org/HxSUpg3L

shrughes
Oct 11, 2008

(call/cc call/cc)
So... the coding horror is the upcoming buffer overflow?

Is it that he's using a singleton?

???

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip

quote:

For bonus points, what's the reasoning for the right->left evaluation?

Probably because the order of evaluation of parameters is undefined!

Destroyenator
Dec 27, 2004

Don't ask me lady, I live in beer
It's that order of evaluation of the arguments isn't guaranteed by the spec?
A guess at the right to left eval would be that's the order they get put on the stack for the call to printf?

Wozbo
Jul 5, 2010
Yeah, I thought order of eval isn't specified in C, so you're dealing with undefined stuff there.

E: Also I am a coding horror: I've done gone and liked node.js.

Wozbo fucked around with this message at 03:03 on Sep 17, 2012

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
I thought each of those commas was a sequence point?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Suspicious Dish posted:

I thought each of those commas was a sequence point?
The commas in a function call aren't the comma operator (if they were, the function would only get the value of the last argument...).

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

shrughes posted:

So... the coding horror is the upcoming buffer overflow?

Is it that he's using a singleton?

???
I'm going with "mutable global state".

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
The RNG from Doom was roughly

C++ code:

unsigned char rng(void) {
    static unsigned char counter;
    static const unsigned char table = {
	0, 8, 109, 220, 222, 241, 149, 107,  75, 248, 254, 140,  16,  66 ,
    	74,  21, 211,  47,  80, 242, 154,  27, 205, 128, 161,  89,  77,  36 ,
    	95, 110,  85,  48, 212, 140, 211, 249,  22,  79, 200,  50,  28, 188 ,
    	52, 140, 202, 120,  68, 145,  62,  70, 184, 190,  91, 197, 152, 224 ,
    	149, 104,  25, 178, 252, 182, 202, 182, 141, 197,   4,  81, 181, 242 ,
    	145,  42,  39, 227, 156, 198, 225, 193, 219,  93, 122, 175, 249,   0 ,
    	175, 143,  70, 239,  46, 246, 163,  53, 163, 109, 168, 135,   2, 235 ,
    	25,  92,  20, 145, 138,  77,  69, 166,  78, 176, 173, 212, 166, 113 ,
    	94, 161,  41,  50, 239,  49, 111, 164,  70,  60,   2,  37, 171,  75 ,
    	136, 156,  11,  56,  42, 146, 138, 229,  73, 146,  77,  61,  98, 196 ,
    	135, 106,  63, 197, 195,  86,  96, 203, 113, 101, 170, 247, 181, 113 ,
    	80, 250, 108,   7, 255, 237, 129, 226,  79, 107, 112, 166, 103, 241 ,
    	24, 223, 239, 120, 198,  58,  60,  82, 128,   3, 184,  66, 143, 224 ,
    	145, 224,  81, 206, 163,  45,  63,  90, 168, 114,  59,  33, 159,  95 ,
    	28, 139, 123,  98, 125, 196,  15,  70, 194, 253,  54,  14, 109, 226 ,
    	71,  17, 161,  93, 186,  87, 244, 138,  20,  52, 123, 251,  26,  36 ,
    	17,  46,  52, 231, 232,  76,  31, 221,  84,  37, 216, 165, 212, 106 ,
    	197, 242,  98,  43,  39, 175, 254, 145, 190,  84, 118, 222, 187, 136 ,
    	120, 163, 236, 249
    };

    return table[counter++];
}


e: formatting got screwed up

Blotto Skorzany fucked around with this message at 05:48 on Sep 17, 2012

Bunny Cuddlin
Dec 12, 2004
"Making assignment and declaration two different "things" is a huge mistake. It leads to the unexpected global problem in JavaScript, makes your code more verbose, is a huge source of confusion for beginners who don't understand well what the difference is, and is completely unnecessary in a language."

See if you can guess what cool language this is in a thread about.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Otto Skorzeny posted:

The RNG from Doom was roughly

A period of 256 is a bit short, but that seems fine for a non-crypto non-statistical source of psuedorandomness.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip

Jabor posted:

A period of 256 is a bit short, but that seems fine for a non-crypto non-statistical source of psuedorandomness.

I was using it to demonstrate that the concept behind what bucketmouse posted isn't itself bonkers.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Gigantic Slut Man posted:

"Making assignment and declaration two different "things" is a huge mistake. It leads to the unexpected global problem in JavaScript, makes your code more verbose, is a huge source of confusion for beginners who don't understand well what the difference is, and is completely unnecessary in a language."

See if you can guess what cool language this is in a thread about.

"It's okay that variable shadowing silently breaks things because with TDD bugs don't happen"

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Plorkyeran posted:

"It's okay that variable shadowing silently breaks things because with TDD bugs don't happen"

How does variable shadowing silently break things?

Bunny Cuddlin
Dec 12, 2004

Suspicious Dish posted:

How does variable shadowing silently break things?

code:
sys = require 'sys'
foo = 42
(() -> foo = 43)()
sys.puts foo
now pretend "foo = 42" is in some external third party library and "(() -> foo = 43)()" is your code

edit: Oh, I think he may have meant "lack of variable shadowing silently breaks things," because that's how i read it before making this reply

Xenogenesis
Nov 8, 2005

Gigantic Slut Man posted:

code:
sys = require 'sys'
foo = 42
(() -> foo = 43)()
sys.puts foo
now pretend "foo = 42" is in some external third party library and "(() -> foo = 43)()" is your code
I assume CoffeeScript, like JavaScript, is lexically scoped, so that won't break anything? Or are you saying this is a problem because an external library might do something like window.foo = 42? (In which case, the problems are... bigger...)

edit: I still agree that what you originally quoted is silly as hell.

Xenogenesis fucked around with this message at 14:30 on Sep 17, 2012

Bunny Cuddlin
Dec 12, 2004

Xenogenesis posted:

I assume CoffeeScript, like JavaScript, is lexically scoped, so that won't break anything? Or are you saying this is a problem because an external library might do something like window.foo = 42? (In which case, the problems are... bigger...)

edit: I still agree that what you originally quoted is silly as hell.

CoffeeScript is lexically scoped, but you don't have access to var, so you can't avoid changing the value of a variable from the outer scope other than by trying to make a unique variable name. If your function finds itself in a scope with foo, and you've named a variable foo, you're modifying the external foo. There's no declaration syntax available, only assignment with implicit declaration if the variable doesn't already exist.

xtal
Jan 9, 2011

by Fluffdaddy
Isn't that completely mitigated by using proper namespacing and not reusing variable names in different scopes? I'm not a JavaScript or CoffeeScript developer so that could be entirely wrong, but I think the reason nobody noticed that glaring flaw until now is that it isn't actually one.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
Javascript doesn't have namespaces. It was a recommendation for the most recent ecmascript standard but MS fought to have it removed.

xtal
Jan 9, 2011

by Fluffdaddy

Otto Skorzeny posted:

Javascript doesn't have namespaces. It was a recommendation for the most recent ecmascript standard but MS fought to have it removed.

I don't mean proper namespaces, just self-executing functions (in the browser), exports (on the server) and as few globals as possible. It doesn't matter if foo is defined by another library or your own code beforehand because it should be package.foo externally and you shouldn't reuse variable names internally.

Look Around You
Jan 19, 2009

xtal posted:

I don't mean proper namespaces, just self-executing functions (in the browser), exports (on the server) and as few globals as possible. It doesn't matter if foo is defined by another library or your own code beforehand because it should be package.foo externally and you shouldn't reuse variable names internally.

There's no standard package system in JavaScript either.

Adbot
ADBOT LOVES YOU

Bunny Cuddlin
Dec 12, 2004

xtal posted:

I don't mean proper namespaces, just self-executing functions (in the browser), exports (on the server) and as few globals as possible. It doesn't matter if foo is defined by another library or your own code beforehand because it should be package.foo externally and you shouldn't reuse variable names internally.

It seems like you're under the misapprehension that Javascript is related to Java somehow. Javascript doesn't have packages or namespaces. It's one giant namespace. You will be assigning to any variable in any scope that you are inside of if it has the same name (in CoffeeScript -- Javascript has shadowing with var)

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