robotdotnet / WPILib

DotNet implementation of WPILib for FIRST Robotics Competition (FRC)
27 stars 8 forks source link

Embed libraries on build #45

Closed ThadHouse closed 8 years ago

ThadHouse commented 8 years ago

With Network Tables switching to a native library, we are starting to have a lot of DLL's for this. Would it be a good idea to embed all the DLLs into the WPILib DLL? Also looking around, it might be a good idea to dynamically load the native libraries, and attach the pinvoke methods to delegate manually. This would allow us to gain performance. In addition, with the simulator going to use a native library as well, we are going to need to dynamically load to check the difference between 32 and 64 bit os's.

jkoritzinsky commented 8 years ago

One thing I was thinking of is we could do a modification on the PCL "Bait-and-switch" technique for our P/Invoke DLLs since .NET binds by name and not by address. That way we can still use P/Invoke but bind dynamically.

ThadHouse commented 8 years ago

I was starting to use some of the ideas based on this. http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_.aspx

It seemed to be speeding up boot type quite a lot, and ends up binding by address, and skips alot of the type checking since its not directly P/Invoke, so it could end up being faster for normal code too.

One thing we can not do is recompile the HAL. I really don't want to keep a seperate version of the HAL, because then any updates FIRST does takes alot more time.

jkoritzinsky commented 8 years ago

That is a good way of doing it. The way I was thinking was something similar to this: http://log.paulbetts.org/the-bait-and-switch-pcl-trick/.
Here's the design I am thinking of:

We would be able to use P/Invoke and not need to do anything with Delegate types. This would also get rid of a bug that I think I noticed a while ago (don't know if it's still in the code) that causes the HAL to load the native HAL binding if it is on anything but Windows. With this design, we would only distribute each HAL implementation to where it needs to be (P/Invoke to HAL goes to RoboRIO, HAL Simluator dll is always distributed to the simulator).

ThadHouse commented 8 years ago

That bug is gone now. It checks for a specific file to see if its a RoboRIO. NetworkTables does the same thing as well.

I tried doing both the simulator and HAL using the same DLL name. However, that caused a lot of issues. Intellisense hated it. In addition, nuget seemed to require more work to get it to work. Also, are interfaces better then delegates? To me, it seemed delegates were easier to do, because it didnt require circular dependencies, which when I tried to do interfaces did require that. Thats why I had switched to reflection in the first place.

jkoritzinsky commented 8 years ago

If you already tried that and it screwed up everything then it's not worth it. Also, by interface I was meaning the general concept, not the .Net construct. If you've got the other way working, lets just go with that.

ThadHouse commented 8 years ago

I'm gonna try and write a script to do it for me, since I really don't want to convert 300+ types. Luckily since we already have the delegate types, this should be fairly easy to do.

ThadHouse commented 8 years ago

Another reason to do the delegate way is that they are now providing a native library for connecting a simulator to the official driver station. The same code we use to load the HAL can be used to load the new DS library even on the sim side.

jkoritzinsky commented 8 years ago

Awesome! And I definitely agree, this needs to be scripted. Using Roslyn maybe?

ThadHouse commented 8 years ago

Well it only needs to be done once. I was probably just going to do it in python. They won't make any breaking changes to the HAL for a while, especially considering it hasn't changed much since 2009, other then new classes.

I want to do a rewrite of the simulator some time this fall, and make it much less pythonic, cause the current one was copied straight from python just to get it working. Thats going to be a fairly large project though. However being able to use an offical driver station will help alot. That was the hardest part to get right, and is also why the unit testing fails every so often. I tried adding locks around all the sim code, and it slowed my 4790K down to a crawl.

ThadHouse commented 8 years ago

Got the first part of this done. Then realized that I am going to have to do manual marshalling. I still think its worth it, and there are not a lot of functions that need to be marshalled, so its still worth it. Just going to take longer.

ThadHouse commented 8 years ago

1 other thing I just realized this does is make it alot less error prone. If a function declaration in HAL Base changes, the simulator will actually throw a compiler error. I'm changing it so the delegates in HAL-Base are actually assigned in HAL-Simulator. This will speed up startup time alot, and since its a direct assignment and not reflection based, it will fail at compile time. Also on the rio side, if a function is missing from the HAL native library that C# expect, it will throw an exception at boot, instead of waiting for the function to be called. It will also enable much better unit testing, since we can just check that the delegates are assigned.

ThadHouse commented 8 years ago

I got this entirely done for the RoboRIO side. I submitted it in #46 if you would like to take a look before I commit it.

ThadHouse commented 8 years ago

Merged