Tiny Crystal Language Programs

Crystal, as currently deployed on Linux, creates rather large executables.  On my system, a zero-length source file results in an executable of 1087016 bytes in size, with a instruction size of 726121 bytes,  2856 bytes of initialized data, and 1263736 bytes of filled-with-zero-on-demand data (“bss”). This is a problem for embedded use. For example, if I could cross-compile to my ESP32 (ignoring that LLVM doesn’t have its instruction set implemented) I would already be using all of the available memory.

If I was to write an operating system kernel in Crystal, I’d want to have a specially-tweaked support library, as Linux has for common C APIs.

Fortunately, it is pretty easy to build Crystal programs without their support library. This will give you a program with no garbage collection, no exception handling, and no support libraries for Crystal’s built-in classes. It is now your job to fill these in to the extent that you want or need to.

Having stripped out the support library, a minimal Crystal program will compile to an executable only a few kilobytes in size.

Before you get too deep into this, be warned: objects won’t work the way you expect, and are probably pretty broken until they get some library support. The program as I show it below leaks memory, and may not allocate memory properly. There is no garbage collection and no exception handling. I may have written bugs. All of this is left as an exercise for the reader, this is Open Source at work 🙂

Here is a simple Hello World program in Crystal, creating and using a class, and printing a message. Compile this with the command:

crystal build minimal.cr --prelude="empty" -p --release --no-debug

minimal.cr

require "lib_c"
require "lib_c/i686-linux-gnu/c/stdlib"
require "lib_c/i686-linux-gnu/c/stdio"

def free(object)
  LibC.free(pointerof(object))
end

class String
  def to_unsafe
    pointerof(@c)
  end
end

class Foo
  def bar
    LibC.printf "Hello, World!\n"
  end
end

f = Foo.new
f.bar
free(f)

The executable emitted by compiling this is only 6304 bytes in size after the symbol table has been stripped. Instructions are 2179 bytes and initialized data 600 bytes, fill-with-zero-on-demand data is only 16 bytes. It loads with three shared libraries: linux-vdso.so.1, libc.so.6, ld-linux-x86-64.so.2 . These are of course much larger than the program. Doing without these libraries is left as another exercise for the reader.

Obviously the above program is meant to build on i686. Modify “i686-linux-gnu” to be your architecture, and if you are on a different OS, the libraries required above may be different.

How should you ground your shielded Ethernet cable?

The advent of Category 7 cable, which includes four individually shielded twisted pairs, has introduced grounding to the concerns of the network engineer. The general advice of wire manufacturers, and the general configuration of pre-manufactured cables, is for both ends to be grounded. This is contrary to common knowledge in electrical engineering regarding ground loops and the potential for lightning-induced current.

Some purported electrical engineers assert that a shield grounded at only one end is “not a shield at all”, but an RF filter resonant to RF frequencies at its quarter wavelength, and will induce voltage to internal conductors at that frequency. They neglect to mention that a shield grounded at both ends also has resonant frequencies and can induce voltage to its internal conductors.

No configuration of grounding results in a shield always being a low-impedance path to ground across its entire length, for anything but DC and low frequencies. There will always be high-voltage points and null points across its length, for any frequency with a wavelength approaching or smaller than 4 times the circuit length, where the circuit includes the ground path between both ends of the shield if the shield is connected at both ends.

Grounding both ends of the shield simply increases the circuit length, creating a loop with external conductors, including conductive soil. This makes the circuit more vulnerable to lower frequencies than it would be otherwise, and admits additional possibilities for lightning currents to be introduced onto the shield. And you can’t count on the conductors being balanced such that induced currents oppose each other across the length of the circuit.

You must also consider that conductive soil is not a perfect sink to RF currents. Radio Amateurs learn that soil, unaugmented by radial wires, generally makes a poor counterpoise. The ground system in your building is anything but a theoretically perfect ground plane, and will in general present a high impedance at RF. Induced lightning voltage across the soil is a possibility with nearby strikes.

This is one reason for use of optical fiber, especially in areas where lightning-induced currents or RF interference (emitted or received) is a problem. No problems with electrostatic or magnetic induction when you use optical fiber. But we eventually transition to copper or aluminum at the ends of fiber runs. We must then consider lightning-induced currents and how to shield them.

Lightning frequencies are generally low, and energy is generally distributed across frequencies with a 1/f characteristic: more energy at lower frequencies. In this case, grounding the shield at both ends can indeed cause a shield that would be unresonant if single-point grounded to conduct significant energy. Ferrite chokes and other inductive means of increasing the external shield impedance are ineffective at blocking lightning-induced current, because they saturate.

So, I’ll be using single-ended grounding for my application, if for no other reason than that it removes so many unknowns from the equation. I suggest that those who wish to do otherwise actually attempt to model the circuit for its RF resonance and potential for induction of lightning current, using NEC or similar software.

Dynamic Linking of Shared Libraries Doesn’t Make Sense for Modern Languages Like Crystal

We’re all used to having dynamically-loaded shared libraries for C and C++ programs. The effectiveness of shared libraries depends on having an API with well-defined types. This is good for C, which allows only one type per argument, and C++, which allows some type flexibility based on abstract types and inheritance.

Crystal, however, is not like this (see my introduction to Crystal). The duck-typing in Crystal is somewhat similar to C++ templates, but without the ugly syntax. A function like this:

def add(a, b)
  a + b
end

… can take any type for and b, as long as they implement the + method. The code compiled and the return value will be different depending on the types provided. Because Crystal has global type inference, you need to compile the entire program, including the library, every time. That allows types to be inferred through the library code and its return to the caller.

So, shared libraries don’t make much sense in this context. They work because they have a tightly-typed API, which normal Crystal programs wouldn’t, and they assume that modules are independent of each other, which breaks down with modern language features like duck typing and type inference.

The cost is that we have somewhat more memory usage than we might for the equivalent C program. The benefit is that we use less programmer time on development and debugging, and we get increased code correctness because any incompatible type (including nil) is flagged as an error. Ultimately, memory is much cheaper than programmers.

There is also a potential performance increase over C, because there will be less need for the automatic type conversion with which C math operations are liberally salted, and code will be optimized for the type. But any real speed advantage over C has not yet been demonstrated.

Where optimization beyond what Crystal can provide is necessary, we can turn to assembly and Crystal’s foreign function interface. In general, the need for this would be rare.

Is Entrepreneurial Networking Really Being Entrepreneurial?

Over time, it’s struck me that want-to-be-entrepreneurs who spend a lot of time on networking before they have a product to sell are kidding themselves about being entrepreneurial.

The supposition is that you can meet other prospective entrepreneurs who can be of help in establishing and running your own business. I think the reality is that you have to spend a lot of solitary hours on making your product, and the time for networking is when you have something to sell.

The defining moment for me came with my momentary participation in an electronic entrepreneurs Meetup group. Actually, I never attended the first meet-up, but my participation leading into it was educational.

The prospective event was a tour of a local PCB manufacturer. The group leader first scheduled it as an hours-long “networking event” followed by the tour. I protested that I didn’t have time for the networking, and could I just join the group to tour the PCB manufacturer? The group leader allowed this.

I then emailed the PCB manufacturer asking for more information, saying I was a local electronics manufacturer and might like to use their business, and that I’d heard of them through the meetup group.

This is where things started to go wrong. The PCB manufacturer informed the meetup group leader that I’d contacted them independently. Perhaps he was just expressing his gratitude for the publicity, but in general as a business person I’d not give un-involved people details about customer inquiries. It would have been sufficient for him to tell the group leader that he’d had an inquiry, without mentioning my name. I resolved not to do business with this PCB manufacturer after all.

Then, the meetup group leader contacted me, upset that I had contacted the PCB manufacturer without going through him! Obviously, I am a business person and can not allow random people to decide who I do and don’t do business with. So, it seemed this “entrepreneurial meet-up” leader didn’t really have the first idea about what it meant to actually be in business.

I cancelled my reservation for the meetup and exited the group. To this day, I don’t understand the motivations of the people involved.

On Speaking and Reimbursement

A lot of conference speakers are able to have their employer pay their way. Since I own my own small company, that is not possible for me and I make it clear on my site that if you want me to speak, you have to pay for my flight, hotel, and other expenses. Unfortunately there are conferences that act as if they have a hard time understanding this.

There are even conferences that stick me with the bill. For a conference in Russia a few years ago, I had to get a visa, which meant around $200 in expense and half a day sitting around the Russian embassy instead of consulting (a lot more than $200 lost). The for-profit company operating that conference cancelled their event (supposedly because of the Icelandic volcano and its effect upon air travel) and stopped responding to emails regarding their reimbursement of what I’d spent for a visa.

More recently a conference in a far-away place asked for me to help to pay for my own flight and lodging. I politely ended the discussion with that conference, explaining that I felt that my appearance would be a financial hardship to the conference and that it would not be fair to either of us to continue.

When I speak at a conference in a far-away place, I am generally losing at least a week of time in which I could be consulting and operating my own business. Between travel, jet-lag, and the speaking day at least 5 business days are used up. So, you can consider that my personal expense for time not spent on work is quite high, even if you pay all of my travel and lodging expenses.

It is also the case that speaking events hardly ever result in consulting employment. So, the opportunity to “network” and publicize my business seems to have very little value.

So, I am doing all of my speaking to promote the causes I am interested in, at significant cost to me even if you reimburse me for my expenses. And it is the rare speaking opportunity indeed that is able to offer an honorarium sufficient to compensate me for my time.