Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid unnecessary copies of Payload data when not using ipc channel #1041

Merged
merged 1 commit into from Mar 31, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use byteorder::{LittleEndian, ReadBytesExt};
use frame::Frame;
use frame_builder::FrameBuilderConfig;
use internal_types::{FontTemplate, SourceTexture, ResultMsg, RendererFrame};
@@ -11,7 +10,6 @@ use record::ApiRecordingReceiver;
use resource_cache::ResourceCache;
use scene::Scene;
use std::collections::HashMap;
use std::io::{Cursor, Read};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Sender;
use texture_cache::TextureCache;
@@ -21,7 +19,7 @@ use webgl_types::{GLContextHandleWrapper, GLContextWrapper};
use webrender_traits::{DeviceIntPoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize, LayerPoint};
use webrender_traits::{ApiMsg, AuxiliaryLists, BuiltDisplayList, IdNamespace, ImageData};
use webrender_traits::{PipelineId, RenderNotifier, RenderDispatcher, WebGLCommand, WebGLContextId};
use webrender_traits::channel::{PayloadHelperMethods, PayloadReceiver, PayloadSender, MsgReceiver};
use webrender_traits::channel::{PayloadSenderHelperMethods, PayloadReceiverHelperMethods, PayloadReceiver, PayloadSender, MsgReceiver};
use webrender_traits::{BlobImageRenderer, VRCompositorCommand, VRCompositorHandler};
#[cfg(feature = "webgl")]
use offscreen_gl_context::GLContextDispatcher;
@@ -188,36 +186,26 @@ impl RenderBackend {
let mut leftover_auxiliary_data = vec![];
let mut auxiliary_data;
loop {
auxiliary_data = self.payload_rx.recv().unwrap();
auxiliary_data = self.payload_rx.recv_payload().unwrap();
{
let mut payload_reader = Cursor::new(&auxiliary_data[..]);
let payload_epoch =
payload_reader.read_u32::<LittleEndian>().unwrap();
if payload_epoch == epoch.0 {
if auxiliary_data.epoch == epoch {
break
}
}
leftover_auxiliary_data.push(auxiliary_data)
}
for leftover_auxiliary_data in leftover_auxiliary_data {
self.payload_tx.send_vec(leftover_auxiliary_data).unwrap()
self.payload_tx.send_payload(leftover_auxiliary_data).unwrap()
}
if let Some(ref mut r) = self.recorder {
r.write_payload(frame_counter, &auxiliary_data);
r.write_payload(frame_counter, &auxiliary_data.to_data());
}

let mut auxiliary_data = Cursor::new(&mut auxiliary_data[4..]);
let mut built_display_list_data =
vec![0; display_list_descriptor.size()];
auxiliary_data.read_exact(&mut built_display_list_data[..]).unwrap();
let built_display_list =
BuiltDisplayList::from_data(built_display_list_data,
BuiltDisplayList::from_data(auxiliary_data.display_list_data,
display_list_descriptor);
let mut auxiliary_lists_data =
vec![0; auxiliary_lists_descriptor.size()];
auxiliary_data.read_exact(&mut auxiliary_lists_data[..]).unwrap();
let auxiliary_lists =
AuxiliaryLists::from_data(auxiliary_lists_data,
AuxiliaryLists::from_data(auxiliary_data.auxiliary_lists_data,
auxiliary_lists_descriptor);

if !preserve_frame_state {
@@ -2,8 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use byteorder::{LittleEndian, WriteBytesExt};
use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender};
use channel::{self, MsgSender, Payload, PayloadSenderHelperMethods, PayloadSender};
#[cfg(feature = "webgl")]
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
@@ -305,20 +304,18 @@ impl RenderApi {
viewport_size: LayoutSize,
(pipeline_id, display_list, auxiliary_lists): (PipelineId, BuiltDisplayList, AuxiliaryLists),
preserve_frame_state: bool) {
let (dl_data, dl_desc) = display_list.into_data();
let (aux_data, aux_desc) = auxiliary_lists.into_data();
let msg = ApiMsg::SetRootDisplayList(background_color,
epoch,
pipeline_id,
viewport_size,
display_list.descriptor().clone(),
*auxiliary_lists.descriptor(),
dl_desc,
aux_desc,
preserve_frame_state);
self.api_sender.send(msg).unwrap();

let mut payload = vec![];
payload.write_u32::<LittleEndian>(epoch.0).unwrap();
payload.extend_from_slice(display_list.data());
payload.extend_from_slice(auxiliary_lists.data());
self.payload_sender.send_vec(payload).unwrap();
self.payload_sender.send_payload(Payload{epoch: epoch, display_list_data: dl_data, auxiliary_lists_data: aux_data}).unwrap();
}

/// Scrolls the scrolling layer under the `cursor`
@@ -2,10 +2,57 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use byteorder::{LittleEndian, WriteBytesExt, ReadBytesExt};
use std::io::{Cursor, Read};
use api::Epoch;
use std::mem;

#[derive(Clone)]
pub struct Payload {
pub epoch: Epoch,
pub display_list_data: Vec<u8>,
pub auxiliary_lists_data: Vec<u8>
}

impl Payload {
pub fn to_data(&self) -> Vec<u8> {

This comment has been minimized.

@kvark

kvark Mar 31, 2017

Member

nit: consider using From/Into traits. Not really helping anything, just seems to be more idiomatic

let mut data = Vec::with_capacity(mem::size_of::<u32>() +
mem::size_of::<u64>() +
self.display_list_data.len() +
mem::size_of::<u64>() +
self.auxiliary_lists_data.len());
data.write_u32::<LittleEndian>(self.epoch.0).unwrap();
data.write_u64::<LittleEndian>(self.display_list_data.len() as u64).unwrap();
data.extend_from_slice(&self.display_list_data);
data.write_u64::<LittleEndian>(self.auxiliary_lists_data.len() as u64).unwrap();
data.extend_from_slice(&self.auxiliary_lists_data);
data
}
pub fn from_data(data: Vec<u8>) -> Payload {
let mut payload_reader = Cursor::new(&data[..]);
let epoch = Epoch(payload_reader.read_u32::<LittleEndian>().unwrap());

let dl_size = payload_reader.read_u64::<LittleEndian>().unwrap() as usize;
let mut built_display_list_data = vec![0; dl_size];
payload_reader.read_exact(&mut built_display_list_data[..]).unwrap();

let aux_size = payload_reader.read_u64::<LittleEndian>().unwrap() as usize;
let mut auxiliary_lists_data = vec![0; aux_size];
payload_reader.read_exact(&mut auxiliary_lists_data[..]).unwrap();

Payload{ epoch: epoch, display_list_data: built_display_list_data,
auxiliary_lists_data: auxiliary_lists_data }
}
}


// A helper to handle the interface difference between
// IpcBytesSender and Sender<Vec<u8>>
pub trait PayloadHelperMethods {
fn send_vec(&self, data: Vec<u8>) -> Result<(), Error>;
pub trait PayloadSenderHelperMethods {
fn send_payload(&self, data: Payload) -> Result<(), Error>;
}
pub trait PayloadReceiverHelperMethods {
fn recv_payload(&self) -> Result<Payload, Error>;
}

#[cfg(not(feature = "ipc"))]
@@ -3,7 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use serde::{Deserialize, Serialize};
use std::io::Error;
use std::io::{Error, ErrorKind};
use std::io;
use std::error;

use ipc_channel::ipc::{self, IpcSender, IpcReceiver, IpcBytesSender, IpcBytesReceiver};

@@ -19,9 +21,16 @@ pub type PayloadSender = IpcBytesSender;

pub type PayloadReceiver = IpcBytesReceiver;

impl PayloadHelperMethods for PayloadSender {
fn send_vec(&self, data: Vec<u8>) -> Result<(), Error> {
self.send(&data)
impl PayloadSenderHelperMethods for PayloadSender {
fn send_payload(&self, data: Payload) -> Result<(), Error> {
self.send(&data.to_data())
}
}

impl PayloadReceiverHelperMethods for PayloadReceiver {
fn recv_payload(&self) -> Result<Payload, Error> {
self.recv().map(|data| Payload::from_data(data) )
.map_err(|e| io::Error::new(ErrorKind::Other, error::Error::description(&e)))
}
}

@@ -4,7 +4,6 @@

use serde::{Deserialize, Serialize};
use std::io::{Error, ErrorKind};

use serde::{Deserializer, Serializer};

use std::sync::mpsc;
@@ -13,13 +12,19 @@ use std::sync::mpsc;
/// Handles the channel implementation when in process channels are enabled.
///

pub type PayloadSender = MsgSender<Vec<u8>>;
pub type PayloadSender = MsgSender<Payload>;

pub type PayloadReceiver = MsgReceiver<Payload>;

pub type PayloadReceiver = MsgReceiver<Vec<u8>>;
impl PayloadSenderHelperMethods for PayloadSender {
fn send_payload(&self, payload: Payload) -> Result<(), Error> {
self.send(payload)
}
}

impl PayloadHelperMethods for PayloadSender {
fn send_vec(&self, data: Vec<u8>) -> Result<(), Error> {
self.send(data)
impl PayloadReceiverHelperMethods for PayloadReceiver {
fn recv_payload(&self) -> Result<Payload, Error> {
self.recv()
}
}

@@ -12,6 +12,7 @@ use std::path::{Path, PathBuf};
use std::{mem, process};
use webrender::WEBRENDER_RECORDING_HEADER;
use webrender_traits::ApiMsg;
use webrender_traits::channel::{Payload, PayloadSenderHelperMethods};
use wrench::{Wrench, WrenchThing};

#[derive(Clone)]
@@ -166,7 +167,7 @@ impl WrenchThing for BinaryFrameReader {
}
}
Item::Data(buf) => {
wrench.api.payload_sender.send(buf).unwrap();
wrench.api.payload_sender.send_payload(Payload::from_data(buf)).unwrap();
}
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.