-
Type: Improvement
-
Resolution: Done
-
Priority: Minor - P4
-
Affects Version/s: 0.4
-
Component/s: None
-
Environment:Linux, Windows
I understand that the C driver has broad compatibility as a specific goal, but easy platform-specific optimizations can be very useful.
Functions like mongo_insert() currently include a call to mongo_message_create() which then calls bson_malloc(). This supports the requirement to transmit the existing bson data prefixed by the collection name in a single send() call on the socket.
Linux and Windows both support the required network semantics without the additional bson_malloc() by using vector-oriented send() equivalents.
Here is a simplified example :
int mongo_insert_bson( mongo * pMongo, const char * pCollection, bson * pBSON )
{
#if defined( linux ) || defined( _WIN32 )
mongo_header header ;
int nBSON = *( ( int32_t * ) pBSON->data ) ;
int nCollection = 1 + strlen( pCollection ) ;
header.len = sizeof( header ) + sizeof( ZERO ) + nCollection + nBSON ;
header.op = MONGO_OP_INSERT ;
header.id = rand() ;
header.responseTo = 0 ;
#if defined( _WIN32 )
{
WSABUF pSend[ 3 ] ;
int nSent ;
pSend[ 0 ].len = sizeof( header ) ;
pSend[ 0 ].buf = ( char * ) &( header ) ;
if( 0 != WSASend( pMongo->sock, pSend, 1, &( nSent ), 0, 0, 0 ) )
{ pMongo->err = MONGO_IO_ERROR ; return MONGO_ERROR ; }pSend[ 0 ].len = sizeof( ZERO ) ;
pSend[ 0 ].buf = ( char * ) &( ZERO ) ;
pSend[ 1 ].len = nCollection ;
pSend[ 1 ].buf = ( char * ) pCollection ;
pSend[ 2 ].len = nBSON ;
pSend[ 2 ].buf = ( char * ) pBSON->data ;
if( 0 != WSASend( pMongo->sock, pSend, 3, &( nSent ), 0, 0, 0 ) )
{ pMongo->err = MONGO_IO_ERROR ; return MONGO_ERROR ; }
return MONGO_OK ;
}
#endif // defined( _WIN32 )
#if defined( linux )
{
struct iovec pSend[ 3 ] ;
ssize_t nSent ;
pSend[ 0 ].iov_len = sizeof( header ) ;
pSend[ 0 ].iov_base = &( header ) ;
if( 1 == ( nSent = writev( pMongo>sock, pSend, 1 ) ) )
pSend[ 0 ].iov_len = sizeof( ZERO ) ;
pSend[ 0 ].iov_base = &( ZERO ) ;
pSend[ 1 ].iov_len = nCollection ;
pSend[ 1 ].iov_base = pCollection ;
pSend[ 2 ].iov_len = nBSON ;
pSend[ 2 ].iov_base = pBSON->data ;
if(
{ pMongo->err = MONGO_IO_ERROR ; return MONGO_ERROR ; }
return MONGO_OK ;
}
#endif // defined( _WIN32 )
#else
return mongo_insert( pMongo, pCollection, pBSON ) ;
#endif // defined( linux ) || defined( _WIN32 )
} // mongo_insert()
Incorporating this kind of optimization generically in the mongo C driver probably requires a fair amount of well-considered refactoring, so I am not just sending in a hasty patch. I am, however, more than happy to collaborate on this effort.