Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,592
|
Comments: 51,223
Privacy Policy · Terms
filter by tags archive
time to read 1 min | 166 words

This is merely a simple observation. I had a chance to talk with a few people recently, and I heard something that really bothered me. Sadly, this is not a new thing, but it is still extremely annoying and disrespectful.

Basically, the problem is that concerns that are being brought up are dismissed as unrealistic, idealist and non workable in the real world. The people who bring up those concerns are also dismissed as radical tree huggers with no concept of how to build things in the field.

The reason that I think this is stupid, insulting and disrespectful is that a lot of the people bringing up those concerns are real world practitioners. It is more than just merely annoying to hear that.

Calling a raised problem an idealist issue or a perfectionist problem is an eventual guarantee that the feedback and concerns being brought up will dry up. And that the next feedback received will be in terms that aren’t favorable.

JAOO 2009

time to read 4 min | 664 words

I will be speaking at JAOO 2009, talking about advanced OR/M techniques and giving a tutorial about Rhino Mocks.

I spoke at JAOO 2007, and had a great time there. The content was superb and the attendees and the crew were great. I remember sitting at a session with Joe Armstrong talking about Erlang and finally getting things that were annoying just beyond my grasp, and that was one of several sessions that left me wanting more.

You can actually watch me and Hammett’s session about Active Record in JAOO 2007.

This year, there are two things that I am looking forward to in JAOO.

Probably the most important one is that JAOO is giving free tickets for women, which hopefully help us avoid the token female per conference, which seems to be the rule.

There are women in IT, I know because I have met quite a few of them (the best coworker and the best project manager that I had the pleasure of working with where women). Hopefully this will get more of them into more visible spots.

The second, of course, is the content. For a change, I actually have the time to attend most of the sessions that I want to see. I’ll probably change my mind at least a few more times, but here is my current list of session I plan to be at:

All in all, I hope to see you there.

time to read 1 min | 84 words

One common request for NH Prof is that we will support multiple session factories. This turn out to be a bit more problematic than it would seems, mostly because NHibernate doesn’t currently output this relation in any way that NH Prof can access.

But here is the first step along the way, NH Prof can now report statistics from multiple session factories.

image

time to read 2 min | 277 words

image I recently reviewed a code base. Nothing unusual about that, I do this all the time. But this is the first time that I actually had a migraine from reading a codebase.

I talked to a couple of team members about that, and the name of a previous developer came up repeatedly. That developer is no longer on the team, however, and has no input on the way it currently works. Moreover, the code base is pretty small, and the team had had sole ownership of that for months by this time.

Here is a small piece of advice, learned from my army experience, if you own something, you are also responsible for it. Now, there are some special cases, where it takes a while to turn the freighter, but after a while, that excuse is no longer valid.

It is your code, why is it so ugly that I have a migraine?!

And no, saying that X did that this way is not a valid option if it past a week from the time you got the code base. Take a look at the image to the right, what do you think is the first priority of a new captain on that ship?

And if it wasn’t your priority, then it is going to be your fault that it is still in this stage. You don’t get to blame the other guy. You own the code, you are responsible for it, period.

time to read 3 min | 418 words

This is a short reply to Ward Bell’s post, Do Not Make Every Method Virtual. More specifically, I have an issue with this statement:

My argument is with opening up the class blindly and totally by making everything virtual. Suddenly nothing in the class is truly “closed for modification.” The “virtual” keyword announces to the world “here is my extension point.” When every method is virtual, the world is invited to change every method.

I think that there is some confusion here. The original class is closed for modification. I can’t change it. I can create a new class extending the behavior. That is what OCP is all about.

Ward is giving the example of an Elevator, and overriding its Up() method:

I knew that Up() sent the elevator ascending. But I can’t stop someone from re-implementing Up() so that it descends instead. Maybe base.Up() triggers the doors to close. The developer might call base.Up() too late, sending the elevator in motion before the doors have closed. The developer could replace my base.Up with something that juggled the sequence of door closing and elevator motion methods, interleaving custom behaviors, yielding upward motion that failed to satisfy some other elevator guarantees.

And the problem here is… ?

I am sorry, but I see some descriptions of potential bugs (or desired behaviors) listed here. I fail to see a problem.

But I write frameworks for you to use. You’ve licensed my product and you’re paying me for support. When the elevator goes down instead of up; when the doors close suddenly and injure a rider; when the elevator simply stops … you don’t say “I wonder what I did?” You say “that elevator we bought is a piece of crap.”

Well, guess what, if you switch the wires in the elevator, it will behave strangely. Nothing out of the ordinary here. And by switching the wires you accept responsibility for the actions you did.

I have several frameworks available that are nothing but huge extension points that the user can plug into at any point and at any time. More than that, I have those extension points at several layers, so they can choose at what level to interact. And no, those aren’t designed extension points, they fall out of the way I build software. And so far, based on actual evidence on the field, it is working.

time to read 3 min | 534 words

I already talked about the benchmark in general, but I want to focus for a bit on showing how you can carefully craft a benchmark to say exactly what you want.

Case in point, Alex Yakunin has claimed that NHibernate is:

NH runs a simple query fetching 1 instance 100+ times slower when ~ 10K instances are already fetched into the Session

I am assuming that he is basing his numbers of this test:

image

And you know what, he is right. NHibernate will get progressively slower as more items are loaded. This is by design.

Huh? NHibernate is slower by design? WTF?!

Well, it is all related to the way you build the test. And this test appears specifically designed NHibernate looks bad. Let me go back a bit and explain. NHibernate underlying premise is that you live in OO world, and we take care of everything we can in the RDBMS world.  One of the ways we are doing that is by automatically flushing the session if a query is performed that may be affected changes in memory.

Huh? That still doesn’t make sense. It is much simpler to understand in code.

using(tx = s.BeginTransaction())
{
	foo = s.Get<Foo>(1);
	foo.Name = "ayende";
	var list = s.CreateQuery("from Foo f where f.Name = 'ayende'").List<Foo>();
	Assert.Contains(list, foo);
	tx.Commit();
}

The following test will pass. When the times come to execute this query, NHibernate will check all the loaded instance that may be affected by this query, and flush any changes to the database.

NHibernate is smart enough to check only the loaded instances that may be affected, so in general, this is a very quick operation, and it means that you don’t have to worry about the current state of operations. NHibernate manages everything for you.

However, in the case of the QueryTest above, this is using this feature of NHibernate to show that it is slow. All queries are made against the same class, which forces NHibernate to perform a dirty check on every single loaded object. With more objects loaded into memory, that dirty check is going to take longer.

Now, there is no real world scenario where code like that would ever be written (except maybe as a bug), but the result of the “test” are being used to say that NHibernate is slow.

Of course you can show that NHibernate is slow if you build a test specifically for that.

Oh, and a hint, session.FlushMode = FlushMode.Commit; will make NHibernate skip the automatic flush on query, meaning that we will not perform any dirty checks on queries.

But that is not really relevant. Tight loop benchmarks for frameworks as complex as OR/Ms are always going to lie. The only way to really create a benchmark is to create a full blown application with several backend implementations. That is still a bad idea, as there are still plenty of ways to cheat. All you have to do is to look at the PetShop issues from 2002/3 to figure that one out.

time to read 3 min | 452 words

When talking about RIA applications, we usually have the following physical architecture:

image

That is, we have the application actually running on the client’s machine, we access the host server in order to perform operations that cannot be made locally and we save to some persistent storage, usually an RDBMS.

The great advantage that in a RIA application, we have a real platform at the client side, and not the hack that is HTML + JavaScript. That make it a much more pleasant experience to actually work with them. However, we then encounter a very interesting choice. Where are we going to put the weight?

image

We have two choices, server side and client side. On the server side, we would need to develop a real service layer. This is usually called if the RIA app is making use of services that will also be consumed elsewhere. It is an old, traditional, approach. It is also more costly than the alternative, assuming that we need the server side only to support the application itself, which is quite common.

In many cases, the application itself is the only reason for development, and in that case, spending time in the server side is probably a waste of our time for a lot of tasks. It is easier and cheaper to perform tasks completely on the client. And at that point, the server side functionality is limited to “let us just expose the data the application needed” . It is no longer a real independent piece, it has became merely a data transfer tier, with no additional responsibilities.

Note: you still may want to keep some minor validation logic on the server side, but that is about the extent of server side functionality in this case.  Well, that and authorization :-)

RIA Services are supposed to make building that part in RIA applications as simple as possible, making the data transfer side (which we are usually almost totally unconcerned with) as simple and idiot proof as possible.

This is why this post it titled taking advantage of. If you are aware that your server side functionality isn’t important, you can deal with it in as brutal a manner as possible, because that is not where you want to spend your time. You want to spend you time actually doing something useful, and that is probably going to happen all on the client side.

time to read 2 min | 300 words

Damien Guard asked me an interesting question:

Is SessionFactory.OpenSession() very lightweight because you call it on every request even if you have pages that don't need it.
I would have thought the lazy construction in CurrentSession get would have been a little safer.

The answer is that it is literally not worth your time to write the lazy construction. Here is what is happening when you opening a session:

public ISession OpenSession(IDbConnection connection, bool flushBeforeCompletionEnabled, bool autoCloseSessionEnabled,
							ConnectionReleaseMode connectionReleaseMode)
{
	return
		new SessionImpl(connection, this, true, settings.CacheProvider.NextTimestamp(), interceptor,
						settings.DefaultEntityMode, flushBeforeCompletionEnabled, autoCloseSessionEnabled,
						connectionReleaseMode);
}

We new up a SessionImpl, which in turn:

internal SessionImpl(
	IDbConnection connection,
	SessionFactoryImpl factory,
	bool autoclose,
	long timestamp,
	IInterceptor interceptor,
	EntityMode entityMode,
	bool flushBeforeCompletionEnabled,
	bool autoCloseSessionEnabled,
	ConnectionReleaseMode connectionReleaseMode)
	: base(factory)
{
	using (new SessionIdLoggingContext(SessionId))
	{
		if (interceptor == null)
			throw new AssertionFailure("The interceptor can not be null.");

		rootSession = null;
		this.timestamp = timestamp;
		this.entityMode = entityMode;
		this.interceptor = interceptor;
		listeners = factory.EventListeners;
		actionQueue = new ActionQueue(this);
		persistenceContext = new StatefulPersistenceContext(this);
		this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
		this.autoCloseSessionEnabled = autoCloseSessionEnabled;
		this.connectionReleaseMode = connectionReleaseMode;
		connectionManager = new ConnectionManager(this, connection, connectionReleaseMode, interceptor);

		if (factory.Statistics.IsStatisticsEnabled)
		{
			factory.StatisticsImplementor.OpenSession();
		}

		if (log.IsDebugEnabled)
		{
			log.Debug(string.Format("[session-id={0}] opened session at timestamp:{1}", SessionId, timestamp));
		}

		CheckAndUpdateSessionStatus();
	}
}

Is going to setup its fields and new up some additional stuff as well. All the work that is being done is merely newing up a few objects, and that is lightning fast. There is no database involved, NHibernate will manage the database connection to ensure minimal time spent with an open database connection automatically.

time to read 4 min | 691 words

I was informed about ORMBattle.NET existence a few minutes ago. This is a site that:

ORMBattle.NET is devoted to direct ORM comparison. We compare quality of essential features of well-known ORM products for .NET framework, so this site might help you to:

    1. Compare the performance of your own solution (based on a particular ORM listed here) with peak its performance that can be reached on this ORM, and thus, likely, to improve it.
    2. Choose the ORM for your next project taking its performance and LINQ implementation quality into account.

NHibernate is faring rather poorly in the tests there, and I thought that I might respond to that.

First, I want to point out that the company behind the website is Xtensive, which makes another ORM Product. This is not to discredit them, they make it very clear who is behind the site and that they have an ORM product in the benchmark. And they were the one who contacted me about it.

The problem with benchmarks, especially when you are trying to compare a wide variety of products that have different feature sets and different capabilities, is that they are essentially useless. The problem is that in order to be able to measure anything useful, you have to resort to the common denominators, and they are pretty bad.

In the case of the benchmark scenarios used for NHibernate, it shows the problem rather clearly.

image

I don’t even need to think about anything to know that this is going to perform badly. There are several reasons for that. First, NHibernate was never intended to be a batch processing tool. It is an OLTP tool. The benchmark (all the tests in the benchmark) are aimed specifically at measuring batch processing. That is problem number one.

Second, NHibernate actually contains a lot of features that are aimed to give us great performance in many scenarios, including batch processing. For example, in this case, using a stateless session alone would generate a significant performance boost, not to mention that there is no use of batching whatsoever.

image image

This two tests are also showing examples of “this isn’t how we do things”. For one thing, calling the database in a loop is a bug. For another, I would generate the same result, which greatly improved performance using Executable DML:

session.CreateQuery("update Simplest s set s.Value = s.Value + 1").ExecuteUpdate();

session.CreateQuery("delete Simplest").ExecuteUpdate();

And so on, and so forth.

To summarize, because I have talked about this before. Trying to compare different products without taking into account their differences is a flawed approach. Moreover, this benchmark is intentionally trying to measure something that NHibernate was never meant to perform. We don’t need to try to optimize those things, because they are meaningless, we have much better ways to resolve things.

And you know what? The problem is that even if you did put those in, they would still be invalid. Benchmarks tend to ignore such things as the impact of the builtin caching features, or the optimization options that are available in the mapping.

In short, if you want me to “admit” that NHibernate isn’t a batch processing tool, I will do so gladly, it was never meant to be. And benchmarks that try to show how it is in batch processing are going to show it being slow. For real world application development, however, NHibernate is a great fit, and show excellent performance.

Oh, and because management told me that I must, if you find perf problems with NHibernate, that is why we have the NHibernate Profiler for you :-)

time to read 1 min | 198 words

How do you make this code legal?

var foo = new IFoo(1);

And yes, IFoo is an interfacae.

The answer is quite simple, actually. It was there since C# 1.0, I am told, and I just stumbled upon it. Take a look at this code:

class Program
{
	static void Main(string[] args)
	{
		var foo = new IFoo(1);
		foo.Do();
	}
}

[
	ComImport, 
	Guid("C906C002-B214-40d7-8941-F223868B39A5"), 
	CoClass(typeof(FooImpl))
]
public interface IFoo
{
	void Do();
}

public class FooImpl : IFoo
{
	private readonly int i;

	public FooImpl(int i)
	{
		this.i = i;
	}

	public void Do()
	{
		Console.WriteLine(i);	
	}
}

We have an interface, and we specify the co class that implements it and is the default implementation. The rest is just required to make the compiler happy about it.

What it means, in turn, is that you can instantiate an interface and have a default implementation selected. You can even use constructor parameters. It has quite a lot of implications, if you think about it right.

Not sure it is a wise feature to use, but it is certainly an interesting tidbit.

FUTURE POSTS

  1. Semantic image search in RavenDB - about one day from now

There are posts all the way to Jul 28, 2025

RECENT SERIES

  1. RavenDB 7.1 (7):
    11 Jul 2025 - The Gen AI release
  2. Production postmorterm (2):
    11 Jun 2025 - The rookie server's untimely promotion
  3. Webinar (7):
    05 Jun 2025 - Think inside the database
  4. Recording (16):
    29 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  5. RavenDB News (2):
    02 May 2025 - May 2025
View all series

Syndication

Main feed ... ...
Comments feed   ... ...
}