Notifications
Clear all

[Closed] dotnet xml reading taking time

Hello, here is a pretty simple script wich read from an xml.
I added some timestamps to see how much time it takes.


   (
    	st=timestamp()
    	local Iteration=0
    	local Animcount
    	------------------------------------------------------------------------------------------
    	XmlPath="C:/test.xml"
    	XmlDoc=dotNetObject "system.xml.xmlDocument"
    	if doesFileExist XmlPath then
    	(
    		XmlDoc.load XmlPath
    		DocElem = XmlDoc.documentElement
    		if DocElem!=undefined then
    		(
    			Animcount = DocElem.ChildNodes.count
    			for i=0 to Animcount-1 do 
    			(
    				Anim=DocElem.ChildNodes.itemOf[i]
    				for j=0 to 14 do (
    					Iteration+=1
    					Property=Anim.ChildNodes.itemOf[j]
    					Val=Property.ChildNodes.itemOf[0].value
    				)
    			)
    		) else messagebox "DocElem is Undefined"
    	) else messagebox "Xml File does not exist"
    	------------------------------------------------------------------------------------------	
    	et=timestamp()
    	format "Time : % ms 
" (et-st)
    	format "Anims :% 
" Animcount
    	format "Iterations : %
" Iteration
    )
    

the resulting output is :

Time : 2752 ms
Anims :392
Iterations : 5880

As you can see, the xml is pretty big, there are 392 nodes (representing animations) and each of this node has 14 sub nodes (the animation properties)…

The time was not a problem when the xml was not to big but now. only to read the info from the xml takes approximately 3seconds. wich becomes a little slow^^

The instructions wich take the most time are :

					Property=Anim.ChildNodes.itemOf[j]
    					Val=Property.ChildNodes.itemOf[0].value

if i comment this two instructions, the time to execute the script goes from 2732ms to 200 ms…
It seems that executing 5880 times this two instructions takes the most of the time.

So my question was, is there a way to optimize my code so that it will execute faster ?

I hear around that maxscript is pretty slow compared to other languages like c++…
Would it be possible to develop a specific class in c++ that could do the job much faster ?

I am pretty newbie in c++, i just begin looking in to the SDK… so my skills a very limited, could someone orient me to do the equivalent in C++ or dotnet ?

Thank you

13 Replies

I’ve found that the bottleneck in situations like these is passing data from .NET to maxscript and vice versa. Especially complex datastructures that have to be wrapped can be very slow.
If you’re looking for something specific in the xml file, I’d suggest writing all xml parsing code in C#, or C++ or anything that compiles to a .net assembly. And then use a single function call to get exactly what you want with just one expensive ‘transfer’ of data.
But whether this approach will work nicely varies from case to case of course.

 PEN

Found the same things here. The conversions are the slow part for sure. I did a test at one point of doing math with dotNet or Max script and it was way slower doing it with dotNet which really doesn’t make sense until you take into consideration the conversion from dotNet to Max script.

Ok thats interesting to hear about !
By the way, Paul, you will notice that the script is greatly inspiring from your dotnet tutorial that i found on your site. This was invaluable ressources for me! so thank you very much

I think i will give a try to what Pier Janssen says.
Creating a dotnet class in C and use a single function call that returns me an array of the data i need.
This specific problem of speed is not that important, but it gives me a good excuse to dive into this new world for me that is : “Creating a custom dotnet assembly and use it”

Does someone know good tutorials or documents to orient me in the good direction ?

  • How to create a custom dotnet assemblie ?
  • How to parse XML in C / C++ ?
  • How to transfer an array of values from C to maxscript ?

Thank you

1 Reply
(@pjanssen)
Joined: 11 months ago

Posts: 0

Using Visual Studio, just create a Class Library project. This will compile into a .dll, which is the assembly you can load in maxscript. Any public classes in it are visible to maxscript.

  • How to parse XML in C / C++ ?

I think your maxscript/dotnet sample code was doing a lot of that already. Should be more or less the same in C++ or C#. msdn provides many samples too.
I don’t know if you’re familiar with any of the languages supported by .NET, but if you’re not, I’d suggest trying C#. I find it the easiest to get started with, because you don’t have to worry too much about memory management.

  • How to transfer an array of values from C to maxscript ?

Arrays are automatically converted to maxscript arrays. So for example String[] becomes a #() containing strings. This works for any object type.
If you use a generic List<T> in .NET, because it’s so much easier, you can use .ToArray() in your return statement.

okay…
so to begin with all that stuff… as a total noob i decided to try making an assembly wich would return me a simple integer when i call it.

       So i opened VisualStudio, select Visual C++ and create a new "class library" project :
       this is the initial code  
// ParseXML.h
           
           #pragma once
           
           using namespace System;
           
           namespace ParseXML {
         
           	public ref class Class1
           	{
           		// TODO: Add your methods for this class here.
           	};
           }
           
       I compile this into a Dll wich i can load in max : 
 
           	dotnet.loadassembly "C:\ParseXML.dll"
           	dotnetclass "ParseXML.Class1"
       and this returns me in the listener :
       dotNetClass:ParseXML.Class1
       
       Nice!
       So next step is to add some methods i guess ^^
       
       I tried different things, by reading some c++ class documentation, and ended with this (no moquery please ^^)
#pragma once
  
  using namespace System;
  
  namespace ParseXML {
  
  	class Class1 {
  		public :
  			int getInteger() { return 5;};
  	};
  }

Then in max i load the new assembly, but when i do this :

showmethods (dotnetclass "ParseXML.Class1")

i get only this, and i have no getInteger method :s

  .[static]<System.Boolean>Equals objA objB
    .[static]<System.Boolean>ReferenceEquals objA objB
   I am a bit lost, What should i do to get an assembly that returns me an integer.
       
       For example in maxscript : 
C  = dotnetclass "ParseXML.Class1"
      C.GetInteger()
      5
       5 is the integer that the class should return to me ;)
 
 If i can get this, i get the basic !

The way you’re calling the getInteger() function is through the class, not through an object. You can only call functions that are declared static in this fashion. For member functions, you’ll need an object first:

(
   dotnet.loadassembly "C:\ParseXML.dll"
   local classInstance = dotnetObject "ParseXML.Class1"
   print classInstance.getInteger()
)

i get this error :s
– Runtime error: No constructor found which matched argument list: ParseXML.Class1
i guess i have something wrong in my C++ code…

Ah hm apparently a default constructor isn’t synthesized automatically. So add it to the Class1 class:


class Class1 {
  		public :
			Class1(); //constructor can be empty here.
  			int getInteger() { return 5;};
  	};

Well i keep getting the same error, with the constructor declared explicitly.
I tryed to change the c++ source code but i can’t find where the problem is.

Do you know a link to source code of a custom dotnet class in c++ or another language ?

Thank you:)

Hmm that’s odd… I’ve tried it on my pc, and it works just fine, without having to explicitly define a default constructor. Here’s the code I’m using:
C++

#pragma once

using namespace System;

namespace mxs_cpp_test {

	public ref class Class1
	{
	public:
		int getInteger() { return 5; }
		static int multiply(int i, int f) { return i * f; }
	};
}

mxs

(
	dotnet.loadAssembly @"C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\mxs_cpp_test\Release\mxs_cpp_test.dll"
	local class1 = dotnetclass "mxs_cpp_test.Class1"
	showmethods class1
	print (class1.multiply 2 4)
	local inst1 = dotnetobject "mxs_cpp_test.Class1"
	showmethods inst1
	print (inst1.getInteger())
)

result:

  .[static]<System.Boolean>Equals <System.Object>objA <System.Object>objB
  .[static]<System.Int32>multiply <System.Int32>i <System.Int32>f
  .[static]<System.Boolean>ReferenceEquals <System.Object>objA <System.Object>objB
8
  .<System.Boolean>Equals <System.Object>obj
  .[static]<System.Boolean>Equals <System.Object>objA <System.Object>objB
  .<System.Int32>GetHashCode()
  .<System.Int32>getInteger()
  .<System.Type>GetType()
  .[static]<System.Int32>multiply <System.Int32>i <System.Int32>f
  .[static]<System.Boolean>ReferenceEquals <System.Object>objA <System.Object>objB
  .<System.String>ToString()
5
Page 1 / 2