How to tell if Mono actually uses LLVM? - mono

Starting from version 5.14, Mono apparently enables use of LLVM by default (that's what mono --version tells me).
I also have installed the package llvm and I would like to know if there is a way to tell if Mono actually uses LLVM instead of its builtin JIT.
Actually I was thinking of two ways to detect this:
Using something in command line.
Using some code directly from a Mono application.
Edit 2018-10-12: Fun fact, starting from version 5.16, LLVM is not supported anymore.

I came to a solution. However it seems that currently Mono is very unstable on LLVM, so the C# code below is theoric (I could only check it without LLVM).
The idea
Thanks to arnt who gave me the idea to check mapped libraries.
The LLVM is loaded if the mono runtime opens a library named libmono-llvm.so.
From this, we can deduce a bash way and a C# to detect whether we're using LLVM or not.
Caution: this works only on Linux (because it uses the procfs)
Using bash
Given mono pid as $1 parameter, the following command returns 1 if LLVM is used, 0 otherwise.
find /proc/$1/map_files/ -maxdepth 1 -type l -ls | grep libmono-llvm.so | head -1 | wc -l
At runtime in C#
using System.Diagnostics;
using System.IO;
using Mono.Unix;
public static class LlvmInformation
{
private static bool? _isLlvmEnabled;
/// <summary>
/// Gets a value indicating whether Mono uses LLVM.
/// </summary>
/// <value>
/// <c>true</c> if this instance is LLVM enabled; otherwise, <c>false</c>.
/// </value>
public static bool IsLlvmEnabled
{
get
{
if (!_isLlvmEnabled.HasValue)
_isLlvmEnabled = LoadLlvmEnabled();
return _isLlvmEnabled.Value;
}
}
private static bool LoadLlvmEnabled()
{
var pid = Process.GetCurrentProcess().Id;
var mapFilesDirectory = $"/proc/{pid}/map_files";
var mapFiles = Directory.EnumerateFiles(mapFilesDirectory);
foreach (var mapFile in mapFiles)
{
var symbolicLinkInfo = new UnixSymbolicLinkInfo(mapFile);
if (symbolicLinkInfo.FileType == FileTypes.SymbolicLink
&& symbolicLinkInfo.GetContents().Name.Contains("libmono-llvm.so"))
return true;
}
return false;
}
}
Good luck with this!

Related

Jaeger Tracing not working with yaml-cpp version 0.6.x

I am trying to instrument my program with jaeger-tracing (c++).
I was able to view my traces when I compliled the program with yaml-cpp version 0.5.3, but when I changed my yaml-cpp version to 0.6.x, I am unable to view my traces.
Dont know why its happening.
JaegerProgram Source code;
#include <iostream>
#include<memory>
#include <yaml-cpp/yaml.h>
#include<jaegertracing/Tracer.h>
#include<chrono>
using namespace std;
// using namespace literals::chrono_literals;
void init(const char *FilePath)
{
auto yaml = YAML::LoadFile(FilePath);
auto config = jaegertracing::Config::parse(yaml);
auto tracer=jaegertracing::Tracer::make(
"example-service-2",
config,
jaegertracing::logging::consoleLogger()
);
opentracing::Tracer::InitGlobal(
static_pointer_cast<opentracing::Tracer>(tracer)
);
}
void ChildSpan(const unique_ptr<opentracing::Span>& parentSpan){
this_thread::sleep_for(chrono::milliseconds(2));
auto childSpan = opentracing::Tracer::Global()->StartSpan("Span2",{opentracing::ChildOf(&parentSpan->context())});
}
void FollowsSpan(const unique_ptr<opentracing::Span>& followFromspan){
this_thread::sleep_for(chrono::milliseconds(3));
auto followSpan = opentracing::Tracer::Global()->StartSpan("Span3",{opentracing::FollowsFrom(&followFromspan->context())});
}
void ParentSpan(){
auto span = opentracing::Tracer::Global()->StartSpan("Span1");
ChildSpan(span);
FollowsSpan(span);
this_thread::sleep_for(chrono::milliseconds(4));
}
int main()
{
init("./config.yaml");
ParentSpan();
cout<<"Hello World"<<endl;
opentracing::Tracer::Global()->Close();
return 0;
}
compiling command - g++ -std=c++1z test.cpp -L /usr/local/lib/libyaml-cpp.a -ljaegertracing -lyaml-cpp
Yaml file
disabled: false
reporter:
logSpans: true
sampler:
type: const
param: 1
OS : ubuntu 18.04
jaegerTracing : master branch version
UPDATE
after little digging I found some fact, When I parse the above mention config file try to print the result I get the same value as written in config file, but when I parse same file using yaml-cpp-0.6.x the sampler.type is showing 'remote' and sampler.param to be '0.001' and when I manually change this change these values to be same as in config.yaml it has started showing traces. The error is present in parsing the yaml file as I could clearly see different values is loaded as configuration.

Constructing Xaml controls on C++/WinRT UI thread

I'm not sure what I'm doing wrong, but even though I'm definitely on the UI thread, I'm consistently getting the error " 'The application called an interface that was marshalled for a different thread.'" when constructing Xaml controls in C++.
See the following basic example, which uses a stripped down version of the default C++/WinRT CoreApplication template:
#include "pch.h"
using namespace winrt;
using namespace Windows;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::Foundation::Numerics;
using namespace Windows::UI;
using namespace Windows::UI::Core;
using namespace Windows::UI::Composition;
using namespace Windows::ApplicationModel::Activation;
struct App : implements<App, IFrameworkViewSource, IFrameworkView> {
CompositionTarget m_target{nullptr};
IFrameworkView CreateView() { return *this; }
void Initialize(CoreApplicationView const &) {}
void Load(hstring const &) {}
void Uninitialize() {}
void Run() {
CoreWindow window = CoreWindow::GetForCurrentThread();
winrt::Windows::UI::Xaml::Controls::TextBox textbox; // Crashes here
CoreDispatcher dispatcher = window.Dispatcher();
dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit);
}
void SetWindow(CoreWindow const &) {
Compositor compositor;
ContainerVisual root = compositor.CreateContainerVisual();
m_target = compositor.CreateTargetForCurrentView();
m_target.Root(root);
}
};
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) { CoreApplication::Run(make<App>()); }
I've tried using window.Dispatcher().HasThreadAccess() to verify that I'm on the correct thread to be making UI calls, and it always returns true.
I've also tried calling RunAsync() from the window's Dispatcher and constructing a Xaml object in a lambda passed to this method, and it still has exactly the same result. HasThreadAccess returns true here too.
Can anyone explain to me where I'm going wrong here? Is constructing Xaml objects not supported in C++?
[edit]
Here's a sample project that reproduces the issue, again based on the default CoreWindow C++/WinRT template:
https://github.com/lyptt/CoreApp1
Turns out the CoreApplication-based template does not support anything from the Xaml namespace, as it's intended more towards providing a thin UWP layer for games, etc.
To get Xaml support you need to use the full template instead, then things magically start to work.

How to include code excerpts using tags in asciidoc?

I can include the full Greet.java file
public class Greet {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
from within the asciidoc file
== Hello Java
This is how one greets in Java:
[source,java]
.Greet.java
----
include::Greet.java
----
producing the documentation
But suppose that I only want to include an excerpt from the code delimited by tags. In the code above, suppose I only want to include the main function.
I don't see symbolic tags in the documentation, but this page suggests that it's sufficient to write
public class Greet {
// tag::helloMethod[]
public static void main(String[] args) {
System.out.println("Hello World!");
}
// end::helloMethod[]
}
and
== Hello Java
This is how one greets in Java:
[source,java]
.Greet.java
----
include::Greet.java[tags=helloMethod]
----
That just produces:
Can you suggest a method that would include just the excerpt? I'm using asciidoc 8.6.9.
What you're doing should work fine in Asciidoctor (the Ruby implementation of AsciiDoc), but not AsciiDoc (the Python implementation).
Notice though the different mechanism for obtaining syntax highlighting.
To get syntax highlighting with asciidoc one uses a command-line switch asciidoc -a source-highlighter=pygments file.adoc.
No command-line switch is needed (or possible) with Asciidoctor. With AsciiDoctor syntax highlighting is obtained by:
Inserting :source-highlighter: pygments at the top of each source file, and
Running sudo gem install pygments.rb to install pygments.
The Asciidoctor tags option can include multiple tags as well;
[tags="tag 1, tag 2, …"]
Bringing in more code excerpts in one go…

Rename "params" parameter in Java Bindings Library with Mono for Android?

I'm trying to create a Java Binding Library for BugSense, but one of the methods has a parameter named "params" which is a reserved word in C#. I've tried to use the Metadata.xml file to rename it, but I can't figure out how to access the class, let alone the method or it's parameter.
Here is the problem code it's generating:
namespace Com.Bugsense.Trace {
[global::Android.Runtime.Register ("com/bugsense/trace/ActivityAsyncTask", DoNotGenerateAcw=true)]
internal partial class ActivityAsyncTaskInvoker : ActivityAsyncTask {
static IntPtr id_doInBackground_arrayLjava_lang_Object_;
[Register ("doInBackground", "([Ljava/lang/Object;)Ljava/lang/Object;", "GetDoInBackground_arrayLjava_lang_Object_Handler")]
protected override global::Java.Lang.Object DoInBackground (global::Java.Lang.Object[] params)
{
if (id_doInBackground_arrayLjava_lang_Object_ == IntPtr.Zero)
id_doInBackground_arrayLjava_lang_Object_ = JNIEnv.GetMethodID (class_ref, "doInBackground", "([Ljava/lang/Object;)Ljava/lang/Object;");
IntPtr native_params = JNIEnv.NewArray (params);
global::Java.Lang.Object __ret = Java.Lang.Object.GetObject<global::Java.Lang.Object> (JNIEnv.CallObjectMethod (Handle, id_doInBackground_arrayLjava_lang_Object_, new JValue (native_params)), JniHandleOwnership.TransferLocalRef);
if (params != null) {
JNIEnv.CopyArray (native_params, params);
JNIEnv.DeleteLocalRef (native_params);
}
return __ret;
}
}
}
Here is my mapping, which I feel should work, but just refuses to.
<attr path="/api/package[#name='com.bugsense.trace']/class[#name='ActivityAsyncTaskInvoker']/method[#name='doInBackground']/parameter[#name='params']" name="managedName">#params</attr>
I've tried everything I can think of. Please, HELP!
So, turns out it's just a bug in the current version of Mono for Android. If you update to the 4.2.4 build, which is in beta, everything compiles fine.

Install ClickOnce without running

When you install a ClickOnce application, the program runs after the install. Is it possible to install without running?
I know I can use a setup and deployment project and create an installer, but I'd prefer to use ClickOnce.
I guess you could fake it. Introduce an "IsInstalled" boolean property, defaulted to false. Then in Program.cs, change your Main() method to look like this:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (!Properties.Settings.Default.IsInstalled)
{
Properties.Settings.Default.IsInstalled = true;
Properties.Settings.Default.Save();
MessageBox.Show("Install Complete");
return;
}
Application.Run(new Form1());
}
So now when the app is first installed, it checks that property and simply displays a message to the user and then quits.
If you wanted to get tricky then you could look at parsing the Activation URI for the deployment and have a URI parameter which specifies whether the program should run when it's first installed or just close silently.
You can do this by editing the application manifest in Mage. There is a checkbox to stop the application running after installation.
If you are not comfortable editing a manifest manually or with Mage then you can use the built-in deployment class to check whether this is the first time the application has run.
using System.Deployment.Application
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (ApplicationDeployment.CurrentDeployment.IsFirstRun)
{
MessageBox.Show("Install Complete");
return;
}
Application.Run(new Form1());
}
After trying all the suggested solutions and still running into the same problems, I fiddled with this for a while and combined several solutions to one that actually works.
The problem with just setting an "isInstalled" property is the value is retained after upgrades, so every time you install the new version, it runs the app again. But using an application manifest file and Mage is just too much work and too complicated just to solve this little problem.
So what I did was acquire the current build # of the running version of the app, save that to a property, then check the property against the running version each time. This works because each publish increments the version #.
1) Change your Assembly version to use wildcards in AssemblyInfo.cs:
[assembly: AssemblyVersion("1.0.*")]
2) If that throws a "Deterministic" error on Build, open your .csproj file and set Deterministic to false in the PropertyGroup section
<Deterministic>false</Deterministic>
3) Add this fool-proof function to acquire the running assembly version:
private Version GetRunningVersion()
{
try
{
return System.Deployment.Application.ApplicationDeployment.CurrentDeployment.CurrentVersion;
}
catch
{
return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
}
}
4) In your project's properties, open the Settings tab, and add a setting named lastVersion (String, User). Leave the Value empty.
5) Add this property to use to determine whether this is the first time the application is running after installation.
private bool isFirstRun
{
get { return Properties.Settings.Default.lastVersion != GetRunningVersion().ToString(); }
}
6) Then in your code, add this after you check for isFirstRun:
if (isFirstRun)
{
Properties.Settings.Default.lastVersion = GetRunningVersion().ToString();
Properties.Settings.Default.Save();
}