• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

SC2's jass replacement (preview)

Status
Not open for further replies.
the best part of them is that:

Code:
x = x + 1;

turns into:
mov eax, _x
add eax, 1
mov _x, eax

while

x++;

turns into:
mov eax, _x
inc eax
mov _x, eax

and the opcode 'inc' is WAY faster than 'add', making them ideal for loops. Specially since Galaxy is JIT compiled; no much optimization is done while the game compiles it.

In other words, it improves performance.

Um no, a good compiler will find the +/- 1's and change those into inc and dec. Similar thing with *2 and /2: it'll change them to bit shifts.

Then again this is blizzard we're talking about, not some big language >___>
 
I dunno, java is compiled to bytecode and then JIT compiled later.

I did run a few tests using System.nanotime() a while ago, comparing using shifts and multiplication/division by 2

Code:
import java.lang.System;

class Test_Comp
{
	public static void main (String[] args) {
		int x = 8;
		int k;
		long d1, d2;
		d1 = System.nanoTime();
		for (int g = 10000; g != 0; g--)
			k = 1 << x;
		d2 = System.nanoTime();
		System.out.println("Benchmark1: " + (d2-d1));
		x = 8;
		d1 = System.nanoTime();
		for (int g = 10000; g != 0; g--)
			k = x*2;
		d2 = System.nanoTime();
		System.out.println("Benchmark2: " + (d2-d1));
	}
}

I tested it that way and second benchmark is always noticeably higher than first. Maybe it has to do with me using Java 1.4 rather than lastest.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,190
Firstly, multiplication and binary shifting are 2 different instructions.
Secondly loops themselves ruin results due to the loop having maintenence.

The reason it does not optimize multiplication by 2 to binary shifting is because the underlying mechanics are totally differently. Binary shifiting in processors use a special shift instruction. Equally multplication uses a special instruction. On top of that there is the overhead of setting the processor up for the opperation which I would guess is higher in multiplication as well (having to read 2 adresses of values as apposed to shifting which the shift is probably part of the instruction). In end the multiplication itself takes longer due to more complex instruction.

So why does it not convert all multiplication by powers of 2 into binarry shifting? Well its cause the compilers lack the programming to detect this optimization as it just sees it as a multiplication by a constant and not bit shifting. Depending on compiler and compiler settings, you can adjust the level of optimization seach and so there are some compilers which will spot that unefficency and optimize it (detect the constant and see it can be turned into a shift). Java has some basic optimizations when it comes to variables and such removing unnescescary memory interfaces with variable management but as the compiler is fast, it lacks any really deep search.

Java is not the fastest of languages as it has a lot of problem with slow memory allocation in the virtual machine and loves wasting memory. As such a lot of speed is bound to be lost interfacing with the OS for memory adress space and unnescescary RAM interactions, thus you can not rely on JAVA to do anything too fast. An easy example is trying to do a lot of floating point opperations which only need 32 bit floats, java will not only use double the RAM but as the floats are 64 bit they will also be slower (especially for 32 bit systems and hardware).

This kind of optimization is up to the programmer to preform, yes machines help but it is no excuse for sloppyness. They give us binary shift so if you use powers of 2, use binary shift.

As for loops and time measurement. Well this is a very inaccurate measurement for precise speed. It gives you which is better by a largeish number but the numbers it give are meaningless and can not be used to deduce how much faster one way is compaired to the other. Loops are basically an easy way to give a binary result, is one way faster than another as the length of execution is long enough that time splicing and variable load can be ignored. A form of benchmark basicly.

However in this case of comparision, a break down into machinecode and then look up at the cycles per instruction would probably be better. As a guess I recon there is probably 2-4 cycles slower for the multiplication opperation and 8 odd for all the variable management.

If you rely on compilers to do all the optimizations, you really are a poor programmer and eventually the computer should be programming itself while you are on benifits unemployed.
 
Level 13
Joined
Feb 28, 2007
Messages
477
If you rely on compilers to do all the optimizations, you really are a poor programmer and eventually the computer should be programming itself while you are on benifits unemployed.

A computer that programmed things for you would be a breakthrough for mankind. Sure, it would put people out of jobs, but it would be more important than even the shift from vacuum tube to transistor.

On topic, what did you really expect from Blizzard? I'm just glad that they improved the JASS standard to some extent, and optimized it to some degree. I'm sure multi-threading will improve performance greatly, as well.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,190
The garbage collector will be more smart. Meaning that nulling of locals should not happen as it will be done automatically. On top of that it should remove unused strings (why the hell did WC3 fail at doing this) and destroy hidden objects with no references to them (like locations).

Most object types will need manual removal like units and such. Also you will still need to null global variables inorder for their contense to be automatically destroyed and the index recycled (present in all garbage recycler languages).
 
Level 9
Joined
Nov 28, 2008
Messages
704
Somehow I can't see Blizzard succeeding at making their garbage system that well designed, DSG.

They couldn't even finish trackables. And as far as I know, some hashtable stuff crashes GUI users.

I'm just hoping for auto nulling. Auto destruction is too much to hope for.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,190
You are forgetting SC2 has had a lot more testing, effort and skill behind it than WC3. On top of that 2 expansions will mean that any unfinished work will have a lot of opitunity to be finished.

The hashtable GUI problem is the fault of poor design when making GUI. The programmer obviouly was not the one maintaining it (patching it) so along came some good programmers and inserted code which should logically work. They however forgot that GUI lacked some of the types they referenced and as such it crashes when they are selected. In the end it is partly poor maintenence work but most of the blame was on the poor and useless design of GUI.

Unlike WC3, SC2 is actually being made with modding in mind as was shown in blizzcon. Thus such features will be much better designed.
 
Level 9
Joined
Nov 28, 2008
Messages
704
Who wrote that article? o_O

Also, structs seem pretty much next to useless in this manner. No methods, cant return them from functions...

What the hell was Blizzard smoking?

Pointers are nice though, if incredibly limited.

Edit: Although, it seems like a vJass equivilent could definitely work on this.
 
Level 9
Joined
Nov 28, 2008
Messages
704
In C structs don't have methods. In fact, structs should never have methods - they're just data structures. If it has methods it's a class IMO. A struct with no methods is better than no structs at all, right?

EDIT: Wait, you can't return them from functions? Can you at least return pointers to structs?

Doesnt matter - why provide structs when you can provide classes? My god, the idiots.

And no you cant return them. Read that article the one guy linked above. It was really well done. The auto garbage collection system seems to be responsible for this stupid limitation. You can pass them (as pointers) into functions though.

Well, I guess I should get working on making my own vJass attempt since I know the limits of most everything now :O.
 
Who wrote that article? o_O

Also, structs seem pretty much next to useless in this manner. No methods, cant return them from functions...

What the hell was Blizzard smoking?

Pointers are nice though, if incredibly limited.

Edit: Although, it seems like a vJass equivilent could definitely work on this.

why the hell would you return an struct directly!? if it's big enough, you would fill the CPU's stack. I think it's quite smart to force people to return and insert struct pointers rather than the struct itself. After all, JAVA classes work that way and every good programmer knows that blocks bigger than a 'double word' should be referenced when passed. Plus, wc3 types were actually pointers/handles rather than the object itself.

About methods:

a method is nothing more than a function which takes the reference to the class and does some action. They can be easily implemented.

here's an example of a C list object header:

Code:
#ifndef LISTINT_H_INCLUDED
#define LISTINT_H_INCLUDED
        //Note: I tried translating most, however I left some hoare
        //triplets on spanish. I'll translate them if requested.
	typedef struct ListInt * ListInt;
	//Pre there's space in memory;
	//Post resultado != NULL && resultado->inic == NULL;
	ListInt ListIntCreate();
	//Pre l != NULL;
	//Post all the space taken by the list has been freed;
	void ListIntDestroy(ListInt l);
	//Pre l != NULL;
	/*Post The resulting list it's the old(list) with one more node at the end
	* which has the value a;
	*/
	void ListInt_add(ListInt l, const int a);
	//Pre l != NULL;
	/*Post la lista resultante es la misma que la de entrada excepto a que
	* carece del primer nodo en la lista que tenia el valor a.
	*/
	void ListInt_eliminateVal(ListInt l, const int a);
	//Pre l != NULL && 0 <= p;
	/*Post la lista resultante es la misma que la de entrada excepto a que
	* carece nodo en la p-esima posicion.
	*/
	void ListInt_eliminatePos(ListInt l, const int p);
	//Pre l != NULL;
	//Post 1 == a esta en lista, 0 == a no esta en lista;
	int  ListInt_search(ListInt l, const int a);
	//Pre l != NULL;
	/*Post la lista resultante posee todos los elementos de la lista de entrada
	* y ademas estos se encuentran en orden inverso.
	*/
	void ListInt_revert(ListInt l);
	//Pre l != NULL;
	//Post se han imprimido todos los elementos de la lista l.
	void ListInt_print(ListInt l);

#endif

As of now only 3 things are for granted which bother me:
  • We can't make recursive types unless we can typecast pointers.
  • Apparently we "can't" allocate memory (Obviously if we haven't a natives list yet).
  • Adding a garbage collector. As nice as it is, a serious programmer should always clean his own mess.
 
Level 9
Joined
Nov 28, 2008
Messages
704
why the hell would you return an struct directly!? if it's big enough, you would fill the CPU's stack. I think it's quite smart to force people to return and insert struct pointers rather than the struct itself.

I agree. Except you cant even return a structs pointer because the struct is destroyed when the function ends by the garbage collector, which is what I was referring to. I apologise for not making that clear.

This means that making a PERSISTANT struct which you can get with a hashtable or something suddenly becomes impossible. Which brings us back to vJass.
 
I agree. Except you cant even return a structs pointer because the struct is destroyed when the function ends by the garbage collector, which is what I was referring to. I apologise for not making that clear.

This means that making a PERSISTANT struct which you can get with a hashtable or something suddenly becomes impossible. Which brings us back to vJass.

yeah that's called "dynamic allocation" you must wait for the main native API to be revealed before we can deduce if it's possible or not. I imagine that they atleast implemented some sort of function for memory allocation. I think we will have to wait until release before making any assumptions.
 
Has anyone actually checked the bytecode of the game for any possible native list imbeded in them? For example from the game.dll in WC3 you can get all native lists, both AI and main as well as or all order strings.

Zoxc already made a native injecting plugin for his personal 'launcher', but I doubt he has dissambled the game and looked for the native subroutines, that would indeed be a tedious work and a waste, specially since thlly e editor will be released before the end of April.

here's the list of all known natives:

http://www.sc2mapster.com/api-docs/functions/

It includes some natives discovered by trial and error like IntToFixed and StringWord.
 
Level 3
Joined
Dec 16, 2003
Messages
19
here's the list of all known natives:

http://www.sc2mapster.com/api-docs/functions/

It includes some natives discovered by trial and error like IntToFixed and StringWord.

Those are all natives exported by the game at the moment. There is no trial and error in their findings but disassembling the sc2.exe file :)

As you can see, a lot of functions are missing, they will be added when Galaxy Editor comes out!
 
Those are all natives exported by the game at the moment. There is no trial and error in their findings but disassembling the sc2.exe file :)

As you can see, a lot of functions are missing, they will be added when Galaxy Editor comes out!

wow so you really did dissamble the exe? well nice, keep up the great work. I just hope blizzard adds the rest soon.
 
Its not hard, you just seach for strings inside the dlls/exes.

Anyway, that list was largly exposed by my searching through the script files someone sent me a few pages pack or maybe in another thread.

nope, just try using a hex editor with all the PE files that make Sc2, you won't find natives that way. Plus he admitted that he dissambled the code, it would be logical. If it would be me, I would start searching for all the subroutines which are runned when galaxy is read and from there on I would keep going.
 
Status
Not open for further replies.
Top