High PerformanceNano aims to promote high-performance development, both at run-time and during the development process. It does this by making it easy to write simple, yet efficient, code. Simpler CodeNano aims to minimise and simplify the code needed for common tasks. This example compares some simple string manipulation with the equivalent Objective-C: void CObject::SomeMethod(const NString &theString)
{ NString otherString;
otherString = theString;
otherString += " World!";
if (theString == "Hello")
CFShowStr(ToCF(otherString));
}
- (void) someMessage:(const NSString *) theString { NSMutableString *otherString = nil; otherString = [theString mutableCopyWithZone:nil]; [otherString appendString:@" World!"]; if ([theString isEqualToString:@"Hello"]) CFShowStr((CFStringRef) otherString); [otherString release]; } As well as being less verbose, notable differences are:
Simpler MultithreadingNano provides a cross-platform interface to the native thread API, and a set of synchronization primitives such as locks (mutex, read-write, and spin) and atomic operations (integers, lists, or arithmetic). NThreadPool manages a thread pool for NThreadTask objects, and automatically distributes tasks across the available CPUs. Tasks are normally scheduled by priority, but NThreadPool can also use FIFO, LIFO, or custom schedulers. Individual functors can be spun off onto threads, and threads can pass functors back to the main thread if they need to access to non-thread-safe APIs. Simpler SocketsNano provides a cross-platform interface to the native sockets API, and a set of tools for building network applications (such as a key-value based message system, or ZeroConf discovery). NSocket is a thin wrapper around the most efficient network layer for each platform, and abstracts the differences in behaviour between notify-on-ready (CFSocket) and notify-on-completion (IOCP) APIs. NMessageClient and NMessageServer allow multiple clients to connect to a server, and communicate using compressed key-value messages (with comparable performance to Protocol Buffers). Copy-On-WriteMany of Nano's core types derive from NSharedValue, which provides lock-free copy-on-write behaviour. This allows objects such as strings or dictionaries to be copied extremely efficiently. NSharedValue allows objects to be passed around with very little overhead, as even objects passed by value are effectively passed as const references until they are actually modified. This approach also allows Nano to provide a single object of each type (e.g., NString), rather than two classes for the same concept (such as separate classes for mutable vs immutable strings). Immutable objects are "copied" simply by incrementing their reference count, and are converted to a mutable form automatically as required. Inline FunctionsBy judicious use of inline functions, Nano allows performance-critical code to preserve type safety while removing any function call overhead: NIndex CountBits(const NBitVector &theBits)
{ NIndex n, numBits, numSet;
numBits = theBits.GetSize();
numSet = 0;
for (n = 0; n < numBits; n++)
{
if (theBits.GetBit(n))
numSet++;
}
return(numSet);
}
Since GetBit is an inline function, the inner loop can obtain direct access to the bits in the vector without going through a real function call. However since GetBits is declared as a function, it can still ensure const-correctness and be stepped into for debugging. |