This is another John Corey novel by Nelson DeMille. What I admire about DeMille is that he’s written a couple of brilliant, one-off books set during the Cold War (The Charm School, The Talbot Odyssey) as well as this modern day series about a semi-retired NYPD detective with a sharp, though politically incorrect, sense of humour. This title has many of the signature John Corey features: struggle against the reach and might of the FBI/CIA; grapple with mortal enemy Ted Nash; call on NYPD contacts for off-the-books investigations; act like a jerk but still win the heart of the lovely Kate Mayfield. But it’s also based on a true story, the crash of flight TWA 800, and DeMille handles that with sensitivity whilst telling his own fictional story alongside the true horror of the crash.
Book Review: Night Fall, Nelson DeMille
Filed under Book Review
XPerf Trace Viewer
Bruce Dawson wrote a review of xperf and Windows Performance Analyzer.
Filed under Programming
How the robots lost
BusinessWeek published this article by Mathew Philips on high frequency trading.
He relates the rise of several HFT firms:
By 2010, HFT accounted for more than 60 percent of all U.S. equity volume and seemed positioned to swallow the rest.
Now, he predicts the end is nigh:
For the first time since its inception, high-frequency trading, the bogey machine of the markets, is in retreat.
Speed traders aren’t just trading fewer shares, they’re making less money on each trade. Average profits have fallen from about a tenth of a penny per share to a twentieth of a penny.
This could be due to increased competition and higher fees for co-location. Now there’s extra regulation:
Last fall the SEC said it would pay Tradeworx, a high-frequency trading firm, $2.5 million to use its data collection system as the basic platform for a new surveillance operation. Code-named Midas (Market Information Data Analytics System), it scours the market for data from all 13 public exchanges.
Filed under Finance
Growing demand for CFDs
TheTradeNews.com reports that buy-side firms are turning to equity derivatives, a trend that is likely to grow when the Financial Transaction Tax is in place:
Craft believes institutional investors are increasingly looking to trade CFDs, which offer the same benefits of holding equities, without the need to own them.
Under FTT, derivatives attract a lower tax levy:
Craft said the swap portfolio rules under EMIR and the current outline of the European FTT meant CFDs would offer asset managers tax efficiencies for trading the synthetic rather than the stock.
Filed under Finance
Why Mobile Web Apps are so Slow, Drew Crawford
Excellent article that covers lots of reasons why mobile web apps aren’t going to get faster anytime soon. Herb Sutter’s blog post lists some of the contents and a summary.
As a C++ guy, I appreciated the points about garbage collection. I like to be in control of the memory used by my software, and it’s good to know there are sound arguments why explicit memory management is superior in low memory environments:
In particular, when garbage collection has five times as much memory as required, its runtime performance matches or slightly exceeds that of explicit memory management. However, garbage collection’s performance degrades substantially when it must use smaller heaps. With three times as much memory, it runs 17% slower on average, and with twice as much memory, it runs 70% slower. Garbage collection also is more susceptible to paging when physical memory is scarce.
When JavaScript people or Ruby people or Python people hear “garbage collector”, they understand it to mean “silver bullet garbage collector.” They mean “garbage collector that frees me from thinking about managing memory.” But there’s no silver bullet on mobile devices. Everybody thinks about memory on mobile, whether they have a garbage collector or not. The only way to get “silver bullet” memory management is the same way we do it on the desktop–by having 10x more memory than your program really needs.
Filed under Programming
Book Review: The Big Short, Michael Lewis
Another great book by Michael Lewis. Although it might be a stretch for anyone who doesn’t already have a passing knowledge of the financial products involved, it’s a brilliant read. He manages to turn some pretty outrageous characters into unlikely heroes, and shines on a light on the murky dealings that led to the credit crunch of 2008.
Filed under Book Review
Windows Timer Resolution
RandomAscii posted an article on Windows Timer Resolution. He reckons that increasing the timer frequency affects energy efficiency and can take a performance hit.
Filed under Programming
New Concepts Lite paper (2nd revision)
The ISOCpp blogposted a link to the latest Concepts Lite paper.
Filed under C++, Programming
Runtime-sized arrays v std::dynarray in C++ 14
Interesting question on StackOverflow regarding the differences between the proposals in C++14 for std::dynarray and runtime-sized arrays.
Filed under C++, Programming
How to serialize a COM object as a Base64 byte array
A component I’m working on needs to be able to serialize its data via JSON. That’s fine for scalars, arrays and maps, but we also needed to be able to serialize COM objects (there’s a large legacy codebase underneath, much of which is deployed via COM). It turns out ATL provides API functions for Base 64 encoding (which was a surprise to me and a number of my colleagues). Here’s some code to make calling it easier (I’ve replaced the production code error handling with simple strings):
std::string to_base_64(int byte_length, const void* bytes )
{
if (bytes == 0)
throw "ToBase64 called with zero bytes";
ATL::CStringA base64;
int base64_length = ATL::Base64EncodeGetRequiredLength(byte_length);
if(!ATL::Base64Encode(static_cast<const BYTE*>(bytes),
byte_length,
base64.GetBufferSetLength(base64_length),
&base64_length))
throw "ATL::Base64Encode failed";
base64.ReleaseBufferSetLength(base64_length);
return static_cast<const char*>(CT2A(base64));
}
std::pair<size_t,std::unique_ptr<BYTE>> from_base_64( const std::string& encoded )
{
// Predict length needed for decoding
int decoded_length = Base64DecodeGetRequiredLength( encoded.size() );
std::unique_ptr<BYTE> buffer( new BYTE[decoded_length] );
// Actual decoded-length may be different to that predicted - method overwrites the value
if (!Base64Decode(encoded.c_str(), encoded.size(), buffer.get(), &decoded_length))
{
throw "ATL::Base64Decode failed";
}
return std::make_pair( decoded_length, std::move(buffer) );
}
That leaves the requirement to turn a serializable COM object into a byte array. The following code does the job provided the COM object implements IPersistStream:
std::pair<size_t, std::unique_ptr<BYTE>> object_to_bytes( IUnknown* pUnk )
{
// Create an in-memory stream, HGlobalMem will be allocated internally
HRESULT hr;
CComPtr<IStream> pIStream;
if (FAILED(hr = CreateStreamOnHGlobal(0, TRUE, &pIStream)))
throw "Could not CreateStreamOnHGlobal";
CComPtr<IPersistStream> pPersistStream;
if (FAILED(hr = pUnk->QueryInterface(IID_IPersistStream, &pPersistStream ) )
throw "Failed to QI to IPersistStream";
CLSID clsid;
if (FAILED(hr = pPersistStream->GetClassID(&clsid) )
throw "Failed to get clsid";
// Serialise CLSID into stream
if (FAILED(hr = WriteClassStm( pIStream, clsid )))
throw "WriteClassStm failed";
// Serialise object into stream
if (FAILED(hr = pPersistStream->Save( pIStream, TRUE ) )
throw "Save object into IPersistStream failed";
// Find out how big the stream is
LARGE_INTEGER liStart = {0};
if (FAILED(hr = pIStream->Seek( liStart, STREAM_SEEK_SET, NULL ) )
throw "IPersistStream::Seek failed";
STATSTG statstg;
memset( &statstg, 0, sizeof(statstg) );
if (FAILED(hr = pIStream->Stat( &statstg, STATFLAG_NONAME ) )
throw "IPersistStream::Stat failed";
// Populate a byte array from the stream
std::unique_ptr<BYTE> buffer( new BYTE[statstg.cbSize.LowPart] );
unsigned long size_read;
if (FAILED(hr = pIStream->Read( (void*)buffer.get(), statstg.cbSize.LowPart, &size_read ) )
throw "IPersistStream::Read failed";
ASSERT( size_read == statstg.cbSize.LowPart );
return std::make_pair( size_read, std::move(buffer) );
}
CComPtr<IUnknown> bytes_to_object( size_t length, void* bytes )
{
HRESULT hr;
CComPtr<IStream> pIStream;
HGLOBAL handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_NODISCARD, length );
if (FAILED(hr = CreateStreamOnHGlobal(handle, TRUE, &pIStream)))
throw "Could not CreateStreamOnHGlobal";
unsigned long size_written;
if (FAILED(hr = pIStream->Write( bytes, length, &size_written ) )
throw "Failed to write to stream";
// Reset the stream
LARGE_INTEGER liStart = {0};
if (FAILED(hr = pIStream->Seek( liStart, STREAM_SEEK_SET, NULL ) )
throw "IPersistStream::Seek failed";
// Serialise CLSID out of stream
CLSID clsid;
if (FAILED(hr = ReadClassStm( pIStream, &clsid )))
throw "ReadClassStm failed";
// Create object from the clsid and stream from IStream into the object, using IPersistStream
CComPtr<IUnknown> pUnk;
if (FAILED(hr = ::CoCreateInstance(clsid, NULL, CLSCTX_ALL, &pUnk ) )
throw "Failed to CoCreate clsid";
CComPtr<IPersistStream> pStream;
if (FAILED(hr = pUnk->QueryInterface(IID_IPersistStream, &pStream ) )
throw "Failed to QI to IPersistStream";
if (FAILED(hr = pStream->Load( pIStream ) )
throw "IPersistStream::Load failed";
return pUnk;
}
Then it’s a matter of putting the methods together to achieve a simple API:
std::string to_base64_encoded_byte_array( IUnknown* pUnk )
{
auto bytes = object_to_bytes( pUnk );
return to_base_64( bytes.first, bytes.second.get() );
}
CComPtr<IUnknown> from_base64_encoded_byte_array( const std::string& encoded)
{
auto bytes = from_base_64( encoded );
return bytes_to_object( bytes.first, bytes.second.get() );
}
Filed under C++, C++ Code, Programming