{"action":"created","issue":{"url":"https://api.github.com/repos/PerfDotNet/BenchmarkDotNet/issues/87","repository_url":"https://api.github.com/repos/PerfDotNet/BenchmarkDotNet","labels_url":"https://api.github.com/repos/PerfDotNet/BenchmarkDotNet/issues/87/labels{/name}","comments_url":"https://api.github.com/repos/PerfDotNet/BenchmarkDotNet/issues/87/comments","events_url":"https://api.github.com/repos/PerfDotNet/BenchmarkDotNet/issues/87/events","html_url":"https://github.com/PerfDotNet/BenchmarkDotNet/pull/87","id":130048711,"number":87,"title":"DNX451 support","user":{"login":"adamsitnik","id":6011991,"avatar_url":"https://avatars.githubusercontent.com/u/6011991?v=3","gravatar_id":"","url":"https://api.github.com/users/adamsitnik","html_url":"https://github.com/adamsitnik","followers_url":"https://api.github.com/users/adamsitnik/followers","following_url":"https://api.github.com/users/adamsitnik/following{/other_user}","gists_url":"https://api.github.com/users/adamsitnik/gists{/gist_id}","starred_url":"https://api.github.com/users/adamsitnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamsitnik/subscriptions","organizations_url":"https://api.github.com/users/adamsitnik/orgs","repos_url":"https://api.github.com/users/adamsitnik/repos","events_url":"https://api.github.com/users/adamsitnik/events{/privacy}","received_events_url":"https://api.github.com/users/adamsitnik/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":10,"created_at":"2016-01-30T23:00:04Z","updated_at":"2016-02-12T00:31:54Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/PerfDotNet/BenchmarkDotNet/pulls/87","html_url":"https://github.com/PerfDotNet/BenchmarkDotNet/pull/87","diff_url":"https://github.com/PerfDotNet/BenchmarkDotNet/pull/87.diff","patch_url":"https://github.com/PerfDotNet/BenchmarkDotNet/pull/87.patch"},"body":"## Introduction to DNX\r\n\r\nI start with some short introduction since the idea of Cross-Platform .NET is quite fresh.\r\n\r\n<del>DNX stands for Dot Net eXecution environment. It lets us restore Nuget packages, compile the code and execute it with native CLR Host. Some good introduction can be found [here](https://www.simple-talk.com/dotnet/.net-framework/what-is-dnx/).</del>  All that aims at cross-platform .NET. A very modularized .NET to be honest!\r\n\r\nDNX451 is a DNX SDK running on .Net 4.5.1 (Desktop CLR / Full BCL and FCL). So it is not Cross-Platform yet, which NETCORE aka DNXCORE50 is. \r\n\r\nTo me DNX451 support is just a huge step forward for NETCORE support, which it the cool thing we aim for ;) \r\n\r\nChanges in .NET applications development:\r\n*\t<del>We need DNX toolchain to be installed [link](http://docs.asp.net/en/latest/getting-started/index.html). It contains of . NET Version Manager (DNVM) and DNX. Once installed, we can get our hands on latest runtime with simple „dnvm upgrade” command. „dnvm update-self” is also worth to mention.</del>\r\n*      We need .NET Core command-line (CLI) [link](https://github.com/dotnet/cli) to be installed.\r\n*\t.csproj and package.config files have been replaced with .xproj and project.json files. .xproj automatically references all .cs files so you don’t have to update it with every new class/interface/enum added (number of git conflicts has just dropped) Project.json allows us to target multiple frameworks with one file and manage all dependencies in single place. Simplicity over complexity! Project.json.lock tells the compiler exactly where to look for our dependencies. You can produce it with „~~dnu~~ dotnet restore”. Sometimes VS will do this for you (currently VS is still using dnu), sometimes you will have to do this on your own. <del>Dnu is just an alias for a part of Dnx.</del>\r\n*\tForget about .exe files, now you get .dll files with entrypoints that can be nonstatic and async methods! Moreover VS does not produce output files by default, it preffers to do this in memory. But of course there is an option in VS to get these files. Alt + F4 -> Build tab -> „Produce output on build” checkbox\r\n*\tTo start program you need to start it with „~~dnx~~ dotnet run”. Run is just a command in your project.json file.\r\n*\t<del>Program’s startup seems to be longer to me now. If you set DNX_TRACE to 1 then you get detailed status updates from DNX. That explains a lot! (I created dedicated VS profile for BDN for this to make troubleshooting easier)</del>\r\n*\tAll applications put nuget packages to the same folder now. It is „%USERPROFILE%/.dnx/packages”. MS plans to replace „dnx” with „nuget” in this path\r\n*\tAssembly.Location is just an empty string now. That is because the way of loading assemblies has changed.\r\n*\tIn NECORE some of the APIs has changed. To make System.Object independent from System.Reflection, Object.GetType() returns a simple object that have only ONE field: Name. If you want to get more, you need to call other method: Object.GetType().GetTypeInfo()\r\n*\t& more. Yet to discover, at least for me.\r\n\r\n## Failed PoC:\r\n*\tI tried to use Nuget.Client v3 to get the dnu restore working, but it did not create project.json file I needed. \r\n*\tI tried to use Microsoft.Dnx.Compilation to compile, but I have failed to make it work. Dnx tool itself is using this, but it does so much configuration that I was unable to reproduce it.\r\n*\tI tried to use „dnu publish” to produce the dll first, and then run it with dnx run but it had one huge disadvantage: it was generating a lot of nested folders, which names I could not control, which caused a lot of „path too long exceptions”. I had to keep my benchmarks very close to drive’s root, like C:\\bdn.\r\n*     I succeded with dnx toolchain and it got retired by Microsoft. I had to switch to dotnet cli which also reduced the number of tricky things!\r\n\r\n## How it works\r\nI have built a new toolchain that relies on the classic one. In order to reuse as much code as possible, most of the new classes just inherit from the existing ones.\r\n*\tCHANGE: Instead of generating .csproj file with references to .dlls, new project.json file that defines the dependencies is being generated.\r\n*\tNEW: To get all required dependencies ~~dnu~~ dotnet restore command is being executed. It is just a new „nuget restore”. It produces project.lock.json file.\r\n*\t<del>CHANGE: Instead of compiling code and emitting assembly and then running it, a dnx run command is being executed. It does all that with single command and in memory (no .dll file). The disadvantage of doing it in memory is that we have to compile it with each iteration.</del>\r\n*\tCHANGE: I have changed the way how console output is being read. Instead of while(output.ReadLine() != null) I used events. I have also added reading of error output. This might give us more detailed informations on errors.\r\n\r\n## Tricky things\r\n*\tTo get „~~dnu~~ dotnet restore” working when executing in VS/xUnit runner I had to put the auto-generated project.json file closer to VS solution folder root (DnxGenerator. GetDirectoryPath).\r\n*\t<del>The other thing to get it running was to switch between dependency to BenchmarkDotNet project and package. When developing, we want our auto-generated program to get code from project, but when we are at production, then we want to it from the official nuget( BenchmarkDnxGenerator.GetTargetType()). I have relied it on the existing convention of AssemblyTitleAttribute ending with „-Dev”. </del>\r\n*       I had also to increment the package version, otherwise I could not test the production part, because the nuget was restoring existing version.\r\n*\t<del>To get „dnx run” working I had to define the compiler in project.json in explicit way (roslyn). When it was using the default compiler (DesignTime) it had differnt configuration and was unable to resolve dependencies.</del>\r\n*\t<del>To get the x86/x64 working I had to tell dnvm to use exact processor architecture (BenchmarkDnxExecutor. BuildParameters)</del>\r\n*\tTo ensure the high priority and right affinity in scenario where instead of starting single process I start cmd.exe that starts dnx.exe that starts the program I set these at Program.Main of the autogenerated program. This is because HIGH_PRIORITY is not inherited by child processes in Windows [link](http://stackoverflow.com/questions/619543/process-priority-inheritance)\r\n\r\n## How to test\r\n\r\n\tTesting from VS/xUnit runner requires no configuration.\r\n\tTesting as a standalone application requires more effort:\r\n\r\n*\tGo to AssemblyInfo.cs and remove „-Dev” from it.\r\n*\tBuild solution in Release\r\n*\tCreate three new folders:  SomeName\\BenchmarkDotNet\\0.8.3\r\n*\tGo to „artifacts\\bin\\BenchmarkDotNet\\Release” folder\r\n*\tUnzip BenchmarkDotNet.0.8.3.nupkg to the previously created folder\r\n![image](https://cloud.githubusercontent.com/assets/6011991/12699003/bb8ddabc-c7ac-11e5-8b32-64bc62575029.png)\r\n\r\n*\tAdd this folder as a nuget’s local feed [link]( https://github.com/aspnet/Home/wiki/Configuring-the-feed-used-by-dnu-to-restore-packages)\r\n*\tCreate new VS solution with new project „Console Application (package)” (or add it to your existing solution)\r\n*\tRemove NETCORE target from it’s project.json\r\n*\tInstall BenchmarkDotNet.0.8.3 package from your local feed\r\n*\tWrite some benchmarks like you used to do before.\r\n*\tGo to the project’s root folder and run „dnu publish --no-source --configuration Release”\r\n*\tCD to „bin\\output\\approot\\packages\\$YourProjectName\\1.0.0\\app” and run „dnu restore”. You can see that nuget has used your local feed now\r\n*\tExecute „dnx run” and ENJOY\r\n\r\nIt all seems crazy, but faking the nuget repo needs to be done only now, for testing the solution before official nuget package release. And the whole dnu/dnx thing is just the new way of executing .NET apps so the rest will be no suprise to the users. \r\n\r\n## How to debug:\r\n*\tDNX451: simply press F5\r\n*\tNET40: Configure VS to start executable on debugging, for our purposes I have already done this for Samples project\r\n![image](https://cloud.githubusercontent.com/assets/6011991/12699000/9203404c-c7ac-11e5-9bd8-a856e26bda8c.png)\r\n\r\n\r\nPlease start testing, and do not hesitate to ask. I think that if you accept this this PR I will remove existing .csprojs and old solution. I can also squash the commits if you want. I left it this way just to keep the history."},"comment":{"url":"https://api.github.com/repos/PerfDotNet/BenchmarkDotNet/issues/comments/183125809","html_url":"https://github.com/PerfDotNet/BenchmarkDotNet/pull/87#issuecomment-183125809","issue_url":"https://api.github.com/repos/PerfDotNet/BenchmarkDotNet/issues/87","id":183125809,"user":{"login":"redknightlois","id":1045411,"avatar_url":"https://avatars.githubusercontent.com/u/1045411?v=3","gravatar_id":"","url":"https://api.github.com/users/redknightlois","html_url":"https://github.com/redknightlois","followers_url":"https://api.github.com/users/redknightlois/followers","following_url":"https://api.github.com/users/redknightlois/following{/other_user}","gists_url":"https://api.github.com/users/redknightlois/gists{/gist_id}","starred_url":"https://api.github.com/users/redknightlois/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/redknightlois/subscriptions","organizations_url":"https://api.github.com/users/redknightlois/orgs","repos_url":"https://api.github.com/users/redknightlois/repos","events_url":"https://api.github.com/users/redknightlois/events{/privacy}","received_events_url":"https://api.github.com/users/redknightlois/received_events","type":"User","site_admin":false},"created_at":"2016-02-12T00:31:54Z","updated_at":"2016-02-12T00:31:54Z","body":"Awesome. Have a few things to test on .NET CORE :)"}}