0

PseudoTcp to expose settings of nagling and ACK delay

Changes are as follows:
1. PseudoTcp to expose whether Nagle's algo is turned on.
2. PseudoTcp to expose setting of ACK delay.
3. JingleSession to disable Nagle's algo.
4. Set ACK delay to 10 milliseconds.
5. Unit tests for testing jingle session latency.

BUG=None
TEST=None

Review URL: http://codereview.chromium.org/7275024

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@91057 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
hclam@chromium.org
2011-06-30 00:06:20 +00:00
parent dbae6b00f7
commit e3280d6ced
4 changed files with 129 additions and 16 deletions

@ -46,6 +46,10 @@ class PseudoTcpAdapter::Core : public cricket::IPseudoTcpNotify,
// This is triggered by NotifyClock, NotifyPacket, Recv and Send.
virtual WriteResult TcpWritePacket(cricket::PseudoTcp* tcp,
const char* buffer, size_t len) OVERRIDE;
void SetAckDelay(int delay_ms);
void SetNoDelay(bool no_delay);
private:
// These are invoked by the underlying Socket, and may trigger callbacks.
// They hold a reference to |this| while running, to protect from deletion.
@ -269,6 +273,14 @@ void PseudoTcpAdapter::Core::OnTcpClosed(PseudoTcp* tcp, uint32 error) {
}
}
void PseudoTcpAdapter::Core::SetAckDelay(int delay_ms) {
pseudo_tcp_.SetOption(cricket::PseudoTcp::OPT_ACKDELAY, delay_ms);
}
void PseudoTcpAdapter::Core::SetNoDelay(bool no_delay) {
pseudo_tcp_.SetOption(cricket::PseudoTcp::OPT_NODELAY, no_delay ? 1 : 0);
}
cricket::IPseudoTcpNotify::WriteResult PseudoTcpAdapter::Core::TcpWritePacket(
PseudoTcp* tcp,
const char* buffer,
@ -473,4 +485,14 @@ base::TimeDelta PseudoTcpAdapter::GetConnectTimeMicros() const {
return base::TimeDelta::FromMicroseconds(-1);
}
void PseudoTcpAdapter::SetAckDelay(int delay_ms) {
DCHECK(CalledOnValidThread());
core_->SetAckDelay(delay_ms);
}
void PseudoTcpAdapter::SetNoDelay(bool no_delay) {
DCHECK(CalledOnValidThread());
core_->SetNoDelay(no_delay);
}
} // namespace jingle_glue

@ -52,6 +52,12 @@ class PseudoTcpAdapter : public net::StreamSocket, base::NonThreadSafe {
virtual int64 NumBytesRead() const OVERRIDE;
virtual base::TimeDelta GetConnectTimeMicros() const OVERRIDE;
// Set the delay for sending ACK.
void SetAckDelay(int delay_ms);
// Set whether Nagle's algorithm is enabled.
void SetNoDelay(bool nagling);
private:
class Core;

@ -45,6 +45,10 @@ const char kVideoRtcpChannelName[] = "videortcp";
const int kMasterKeyLength = 16;
const int kChannelKeyLength = 16;
// Value is choosen to balance the extra latency against the reduced
// load due to ACK traffic.
const int kTcpAckDelayMilliseconds = 10;
// Helper method to create a SSL client socket.
net::SSLClientSocket* CreateSSLClientSocket(
net::StreamSocket* socket, scoped_refptr<net::X509Certificate> cert,
@ -451,7 +455,12 @@ void JingleSession::OnInitiate() {
bool JingleSession::EstablishPseudoTcp(
net::Socket* channel,
scoped_ptr<net::StreamSocket>* stream) {
stream->reset(new jingle_glue::PseudoTcpAdapter(channel));
jingle_glue::PseudoTcpAdapter* adapter =
new jingle_glue::PseudoTcpAdapter(channel);
adapter->SetAckDelay(kTcpAckDelayMilliseconds);
adapter->SetNoDelay(true);
stream->reset(adapter);
int result = (*stream)->Connect(&connect_callback_);
return (result == net::OK) || (result == net::ERR_IO_PENDING);
}

@ -344,14 +344,18 @@ class TCPChannelTester : public ChannelTesterBase {
public:
TCPChannelTester(MessageLoop* message_loop,
Session* host_session,
Session* client_session)
Session* client_session,
int message_size, int message_count)
: ChannelTesterBase(message_loop, host_session, client_session),
ALLOW_THIS_IN_INITIALIZER_LIST(
write_cb_(this, &TCPChannelTester::OnWritten)),
ALLOW_THIS_IN_INITIALIZER_LIST(
read_cb_(this, &TCPChannelTester::OnRead)),
write_errors_(0),
read_errors_(0) {
read_errors_(0),
message_size_(message_size),
message_count_(message_count),
test_data_size_(message_size * message_count) {
}
virtual ~TCPChannelTester() { }
@ -360,20 +364,21 @@ class TCPChannelTester : public ChannelTesterBase {
EXPECT_EQ(0, write_errors_);
EXPECT_EQ(0, read_errors_);
ASSERT_EQ(kTestDataSize, input_buffer_->offset());
ASSERT_EQ(test_data_size_, input_buffer_->offset());
output_buffer_->SetOffset(0);
ASSERT_EQ(kTestDataSize, output_buffer_->size());
ASSERT_EQ(test_data_size_, output_buffer_->size());
EXPECT_EQ(0, memcmp(output_buffer_->data(),
input_buffer_->StartOfBuffer(), kTestDataSize));
input_buffer_->StartOfBuffer(), test_data_size_));
}
protected:
virtual void InitBuffers() {
output_buffer_ = new net::DrainableIOBuffer(
new net::IOBuffer(kTestDataSize), kTestDataSize);
memset(output_buffer_->data(), 123, kTestDataSize);
new net::IOBuffer(test_data_size_), test_data_size_);
memset(output_buffer_->data(), 123, test_data_size_);
input_buffer_ = new net::GrowableIOBuffer();
}
@ -383,7 +388,7 @@ class TCPChannelTester : public ChannelTesterBase {
if (output_buffer_->BytesRemaining() == 0)
break;
int bytes_to_write = std::min(output_buffer_->BytesRemaining(),
kMessageSize);
message_size_);
result = socket_1_->Write(output_buffer_, bytes_to_write, &write_cb_);
HandleWriteResult(result);
};
@ -407,8 +412,8 @@ class TCPChannelTester : public ChannelTesterBase {
virtual void DoRead() {
int result = 1;
while (result > 0) {
input_buffer_->SetCapacity(input_buffer_->offset() + kMessageSize);
result = socket_2_->Read(input_buffer_, kMessageSize, &read_cb_);
input_buffer_->SetCapacity(input_buffer_->offset() + message_size_);
result = socket_2_->Read(input_buffer_, message_size_, &read_cb_);
HandleReadResult(result);
};
}
@ -429,12 +434,11 @@ class TCPChannelTester : public ChannelTesterBase {
} else if (result > 0) {
// Allocate memory for the next read.
input_buffer_->set_offset(input_buffer_->offset() + result);
if (input_buffer_->offset() == kTestDataSize)
if (input_buffer_->offset() == test_data_size_)
done_event_.Signal();
}
}
private:
scoped_refptr<net::DrainableIOBuffer> output_buffer_;
scoped_refptr<net::GrowableIOBuffer> input_buffer_;
@ -442,6 +446,39 @@ class TCPChannelTester : public ChannelTesterBase {
net::CompletionCallbackImpl<TCPChannelTester> read_cb_;
int write_errors_;
int read_errors_;
int message_size_;
int message_count_;
int test_data_size_;
};
class ChannelSpeedTester : public TCPChannelTester {
public:
ChannelSpeedTester(MessageLoop* message_loop,
Session* host_session,
Session* client_session,
int message_size)
: TCPChannelTester(message_loop, host_session,
client_session, message_size, 1) {
CHECK(message_size >= 8);
}
virtual ~ChannelSpeedTester() { }
virtual void CheckResults() {
}
base::TimeDelta GetElapsedTime() {
return base::Time::Now() - start_time_;
}
protected:
virtual void InitBuffers() {
TCPChannelTester::InitBuffers();
start_time_ = base::Time::Now();
}
base::Time start_time_;
};
class UDPChannelTester : public ChannelTesterBase {
@ -620,7 +657,7 @@ TEST_F(JingleSessionTest, DISABLED_TestControlChannel) {
ASSERT_TRUE(InitiateConnection());
scoped_refptr<TCPChannelTester> tester(
new TCPChannelTester(thread_.message_loop(), host_session_,
client_session_));
client_session_, kMessageSize, kMessages));
tester->Start(ChannelTesterBase::CONTROL);
ASSERT_TRUE(tester->WaitFinished());
tester->CheckResults();
@ -635,7 +672,7 @@ TEST_F(JingleSessionTest, DISABLED_TestVideoChannel) {
ASSERT_TRUE(InitiateConnection());
scoped_refptr<TCPChannelTester> tester(
new TCPChannelTester(thread_.message_loop(), host_session_,
client_session_));
client_session_, kMessageSize, kMessageSize));
tester->Start(ChannelTesterBase::VIDEO);
ASSERT_TRUE(tester->WaitFinished());
tester->CheckResults();
@ -650,7 +687,7 @@ TEST_F(JingleSessionTest, DISABLED_TestEventChannel) {
ASSERT_TRUE(InitiateConnection());
scoped_refptr<TCPChannelTester> tester(
new TCPChannelTester(thread_.message_loop(), host_session_,
client_session_));
client_session_, kMessageSize, kMessageSize));
tester->Start(ChannelTesterBase::EVENT);
ASSERT_TRUE(tester->WaitFinished());
tester->CheckResults();
@ -674,6 +711,45 @@ TEST_F(JingleSessionTest, DISABLED_TestVideoRtpChannel) {
CloseSessions();
}
// Send packets of different size to get the latency for sending data
// using sockets from JingleSession.
TEST_F(JingleSessionTest, DISABLED_TestSpeed) {
CreateServerPair();
ASSERT_TRUE(InitiateConnection());
scoped_refptr<ChannelSpeedTester> tester;
tester = new ChannelSpeedTester(thread_.message_loop(), host_session_,
client_session_, 512);
tester->Start(ChannelTesterBase::VIDEO);
ASSERT_TRUE(tester->WaitFinished());
LOG(INFO) << "Time for 512 bytes "
<< tester->GetElapsedTime().InMilliseconds() << " ms.";
tester = new ChannelSpeedTester(thread_.message_loop(), host_session_,
client_session_, 1024);
tester->Start(ChannelTesterBase::VIDEO);
ASSERT_TRUE(tester->WaitFinished());
LOG(INFO) << "Time for 1024 bytes "
<< tester->GetElapsedTime().InMilliseconds() << " ms.";
tester = new ChannelSpeedTester(thread_.message_loop(), host_session_,
client_session_, 51200);
tester->Start(ChannelTesterBase::VIDEO);
ASSERT_TRUE(tester->WaitFinished());
LOG(INFO) << "Time for 50k bytes "
<< tester->GetElapsedTime().InMilliseconds() << " ms.";
tester = new ChannelSpeedTester(thread_.message_loop(), host_session_,
client_session_, 512000);
tester->Start(ChannelTesterBase::VIDEO);
ASSERT_TRUE(tester->WaitFinished());
LOG(INFO) << "Time for 500k bytes "
<< tester->GetElapsedTime().InMilliseconds() << " ms.";
// Connections must be closed while |tester| still exists.
CloseSessions();
}
#endif
} // namespace protocol