<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Baeastwo</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Baeastwo"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Baeastwo"/>
	<updated>2026-09-28T03:46:33Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116801</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116801"/>
		<updated>2018-04-24T12:41:52Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Rust only has structs and traits, which are very different from classes and interfaces in terms of usage. Inheritance is effectively nonexistent in Rust, so GoF patterns are nearly always impossible to implement in Rust. &lt;br /&gt;
&lt;br /&gt;
However, the GRASP pattern of Information Expert appears in the Subsequent Steps. CanvasPaintThread is no longer aware of the details of actual canvases, so it delegates the responsibility of actually painting on canvases to CanvasData.&lt;br /&gt;
&lt;br /&gt;
Part of the goal of the Subsequent Steps was to increase the compliance to the Separation of Responsibilities principle. It took an object that previously both processed messages and painted canvases and converted it into an object that processes messages and another object that paints canvases.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. They did little to nothing to change the actual functionality of Servo, instead setting the Subsequent Steps up to have a smooth transition by finding all of the users of CanvasPaintThread and making them send CanvasIds, which can then be used to change CanvasPaintThread to the single-threaded design desired without having to touch the users again.&lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project. It builds off of what the Initial Steps lay down. Since the Initial Steps set up all of the users of CanvasPaintThread (even indirect users) to send CanvasIds with their messages, the conversion to use CanvasIds to identify individual canvases was seamless and invisible to the users.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
Previously, a CanvasPaintThread was made for every Canvas, which was very slow when there are many Canvases. To fix this, a single CanvasPaintThread was made that manages all the canvases. The data previously stored in CanvasPaintThread unique to each Canvas was moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Previously, communication channels were opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. Now, there is a single channel that's repeatedly cloned which instead connects the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
These changes involved moving nearly the entire contents of &amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt; into the new file &amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There were slight changes to &amp;lt;code&amp;gt;servo/components/constellation/constellation.rs&amp;lt;/code&amp;gt; so that it doesn't try to create multiple CanvasPaintThreads, but those changes were minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
There were also changes to &amp;lt;code&amp;gt;servo/components/canvas_traits/canvas.rs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;servo/components/script/dom/canvasrenderingcontext2d.rs&amp;lt;/code&amp;gt; because of the removed parts of Canvas2dMsg::DrawImageInOther&lt;br /&gt;
&lt;br /&gt;
===Initial Form of CanvasPaintThread===&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CanvasPaintThread initially stored all the information about a particular canvas. This includes both information used to represent the pixels actually on the canvas and information used to support drawing on the canvas. &lt;br /&gt;
&lt;br /&gt;
There were many, many functions in the previous form of CanvasPaintThread because all the actual painting was done there. &lt;br /&gt;
&lt;br /&gt;
CanvasIds were not usefully used. They were simply added in the initial steps so that the grunt work for the subsequent steps were simpler to implement and more focused.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===New Form of CanvasPaintThread===&lt;br /&gt;
====CanvasPaintThread====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread &amp;lt;'a&amp;gt; {&lt;br /&gt;
        canvases: HashMap&amp;lt;CanvasId, CanvasData&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        next_canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new CanvasPaintThread is much leaner. A single CanvasPaintThread exists with nothing but a HashMap of CanvasId-&amp;gt;CanvasData structures and a CanvasId to represent what the next CanvasId will be.&lt;br /&gt;
&lt;br /&gt;
The only functions it has are start (for initially starting it and also the thread itself, which passes CanvasMsg enums it receives around), create_canvas (for generating a new CanvasData structure), canvas (which is just a wrapper for the canvases hashmap to hide some ugliness in Rust's syntax), and process_canvas_2d_message (which exists solely because there are a lot of Canvas2dMsg enum variants and making the thread itself pass them around makes the code very hard to read).&lt;br /&gt;
&lt;br /&gt;
Below is a snippet from process_canvas_2d_message, to give an idea as to what CanvasPaintThread does in general. There are far too many variants of the Canvas2dMsg enum to be reasonably put in this space, but the following snippet should give a rather good idea what it does in general.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    match message {&lt;br /&gt;
        Canvas2dMsg::FillText(text, x, y, max_width) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).fill_text(text, x, y, max_width)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::FillRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).fill_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::StrokeRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).stroke_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::ClearRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).clear_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
    ...&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In each Canvas2dMsg enum variant's &amp;quot;match&amp;quot; (think of it like a case statement for a switch but fancier), CanvasPaintThread simply takes the values out of the enum then calls the appropriate function on the appropriate CanvasData structure with those values. It does no checking of those values or otherwise processing them, simply passing them along.&lt;br /&gt;
&lt;br /&gt;
There is one exception to this rule, but the message forces itself to act that way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    Canvas2dMsg::DrawImageInOther(&lt;br /&gt;
            other_canvas_id,&lt;br /&gt;
            image_size,&lt;br /&gt;
            dest_rect,&lt;br /&gt;
            source_rect,&lt;br /&gt;
            smoothing&lt;br /&gt;
        ) =&amp;gt; {&lt;br /&gt;
            let mut image_data = self.canvas(canvas_id).read_pixels(&lt;br /&gt;
                        source_rect.to_i32(),&lt;br /&gt;
                        image_size);&lt;br /&gt;
            // TODO: avoid double byte_swap.&lt;br /&gt;
            byte_swap(&amp;amp;mut image_data);&lt;br /&gt;
            self.canvas(other_canvas_id).draw_image(&lt;br /&gt;
                image_data.into(),&lt;br /&gt;
                source_rect.size,&lt;br /&gt;
                dest_rect,&lt;br /&gt;
                source_rect,&lt;br /&gt;
                smoothing,&lt;br /&gt;
            );&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It pulls some data out of one CanvasData and then calls a method on the other CanvasData. For this message to be handled, a decision had to be made. Should CanvasData be aware of the existence of ''other'' CanvasData objects or should CanvasPaintThread do some processing to avoid that? There is the third option of making another object to handle it, but seeing as it's only a single message, that option was considered overkill at best, likely far worse. In the end, it was considered a smaller violation of proper design principles to let CanvasPaintThread move data from one CanvasData to another than to inform CanvasData structures about each other.&lt;br /&gt;
&lt;br /&gt;
====CanvasData====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasData&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice the similarities between CanvasData and the old form of CanvasPaintThread! Now CanvasData does all the things CanvasPaintThread used to do for the purposes of painting on the canvases (for example, bezier_curve_to, arc, and set_line_cap among many others). &lt;br /&gt;
&lt;br /&gt;
There's nothing particularly ''new'' in CanvasData. It's all just moved from CanvasPaintThread. &lt;br /&gt;
&lt;br /&gt;
It is a very focused class now, though. All it does is paint on canvases. There's no processing of messages, only painting. Moreover, the draw_image_in_other function is nowhere to be found, instead replaced by a small amount of processing done by CanvasPaintThread, which just calls draw_image on the one that was originally considered &amp;quot;other&amp;quot; so there's no communication between the CanvasData structures ''at all''. &lt;br /&gt;
&lt;br /&gt;
===New Form's Improvements===&lt;br /&gt;
====Design====&lt;br /&gt;
The new form keeps the responsibilities of converting CanvasMsg enums into their contents and using those contents to paint canvases separate, which improves the overall adherence to the Single Responsibility Principle of Servo. There was also a lot of odd indentation and otherwise messy code in the old form of CanvasPaintThread, which, in the process of preparing the pull request for these changes, were cleaned up, making the overall tidyness of Servo improve.&lt;br /&gt;
&lt;br /&gt;
====Performance====&lt;br /&gt;
The new implementation is also much faster when multiple canvases are involved because there's no need for threading delay to send messages back and forth, waiting for those messages to be sent and received. There's less room for usage of multiple cores to speed up processing, but Servo is already so ''very'' parallel that there will be ''something'' to keep the other cores busy when CanvasPaintThread is stuck on one thread. &lt;br /&gt;
&lt;br /&gt;
Slither.io doesn't run properly on my machine either before or after the changes, which makes reporting on the success of the changes with respect to Slither.io difficult at best. The framerate improved dramatically, even if it looks like... well... this still. I can't imagine that a website with over 3500 canvases could be made to run more slowly with this change, though. &lt;br /&gt;
&lt;br /&gt;
[[File:Slither.png]]&lt;br /&gt;
&lt;br /&gt;
Using our timed drawimage test, the performance improvement is... well... not really there. On the development build, the drawing time was cut nearly in half from around 19ms to around 9ms, but on the release build, the drawing time is effectively identical, varying between 1.3ms and 1.7ms for both versions. This isn't too surprising, seeing as only two canvases are made and the cost of communicating between two threads isn't very expensive compared to the thousands that the change was made to address.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The rendering of 2D canvases has been entirely moved to a single thread with each canvas identified by a CanvasId. The pull request for the final project is [https://github.com/servo/servo/pull/20680 here]. On 4/24/2018, our final project was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116800</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116800"/>
		<updated>2018-04-24T03:07:47Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Rust only has structs and traits, which are very different from classes and interfaces in terms of usage. Inheritance is effectively nonexistent in Rust, so GoF patterns are nearly always impossible to implement in Rust. &lt;br /&gt;
&lt;br /&gt;
However, the GRASP pattern of Information Expert appears in the Subsequent Steps. CanvasPaintThread is no longer aware of the details of actual canvases, so it delegates the responsibility of actually painting on canvases to CanvasData.&lt;br /&gt;
&lt;br /&gt;
Part of the goal of the Subsequent Steps was to increase the compliance to the Separation of Responsibilities principle. It took an object that previously both processed messages and painted canvases and converted it into an object that processes messages and another object that paints canvases.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. They did little to nothing to change the actual functionality of Servo, instead setting the Subsequent Steps up to have a smooth transition by finding all of the users of CanvasPaintThread and making them send CanvasIds, which can then be used to change CanvasPaintThread to the single-threaded design desired without having to touch the users again.&lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project. It builds off of what the Initial Steps lay down. Since the Initial Steps set up all of the users of CanvasPaintThread (even indirect users) to send CanvasIds with their messages, the conversion to use CanvasIds to identify individual canvases was seamless and invisible to the users.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
Previously, a CanvasPaintThread was made for every Canvas, which was very slow when there are many Canvases. To fix this, a single CanvasPaintThread was made that manages all the canvases. The data previously stored in CanvasPaintThread unique to each Canvas was moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Previously, communication channels were opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. Now, there is a single channel that's repeatedly cloned which instead connects the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
These changes involved moving nearly the entire contents of &amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt; into the new file &amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There were slight changes to &amp;lt;code&amp;gt;servo/components/constellation/constellation.rs&amp;lt;/code&amp;gt; so that it doesn't try to create multiple CanvasPaintThreads, but those changes were minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
There were also changes to &amp;lt;code&amp;gt;servo/components/canvas_traits/canvas.rs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;servo/components/script/dom/canvasrenderingcontext2d.rs&amp;lt;/code&amp;gt; because of the removed parts of Canvas2dMsg::DrawImageInOther&lt;br /&gt;
&lt;br /&gt;
===Initial Form of CanvasPaintThread===&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CanvasPaintThread initially stored all the information about a particular canvas. This includes both information used to represent the pixels actually on the canvas and information used to support drawing on the canvas. &lt;br /&gt;
&lt;br /&gt;
There were many, many functions in the previous form of CanvasPaintThread because all the actual painting was done there. &lt;br /&gt;
&lt;br /&gt;
CanvasIds were not usefully used. They were simply added in the initial steps so that the grunt work for the subsequent steps were simpler to implement and more focused.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===New Form of CanvasPaintThread===&lt;br /&gt;
====CanvasPaintThread====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread &amp;lt;'a&amp;gt; {&lt;br /&gt;
        canvases: HashMap&amp;lt;CanvasId, CanvasData&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        next_canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new CanvasPaintThread is much leaner. A single CanvasPaintThread exists with nothing but a HashMap of CanvasId-&amp;gt;CanvasData structures and a CanvasId to represent what the next CanvasId will be.&lt;br /&gt;
&lt;br /&gt;
The only functions it has are start (for initially starting it and also the thread itself, which passes CanvasMsg enums it receives around), create_canvas (for generating a new CanvasData structure), canvas (which is just a wrapper for the canvases hashmap to hide some ugliness in Rust's syntax), and process_canvas_2d_message (which exists solely because there are a lot of Canvas2dMsg enum variants and making the thread itself pass them around makes the code very hard to read).&lt;br /&gt;
&lt;br /&gt;
Below is a snippet from process_canvas_2d_message, to give an idea as to what CanvasPaintThread does in general. There are far too many variants of the Canvas2dMsg enum to be reasonably put in this space, but the following snippet should give a rather good idea what it does in general.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    match message {&lt;br /&gt;
        Canvas2dMsg::FillText(text, x, y, max_width) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).fill_text(text, x, y, max_width)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::FillRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).fill_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::StrokeRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).stroke_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::ClearRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).clear_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
    ...&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In each Canvas2dMsg enum variant's &amp;quot;match&amp;quot; (think of it like a case statement for a switch but fancier), CanvasPaintThread simply takes the values out of the enum then calls the appropriate function on the appropriate CanvasData structure with those values. It does no checking of those values or otherwise processing them, simply passing them along.&lt;br /&gt;
&lt;br /&gt;
There is one exception to this rule, but the message forces itself to act that way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    Canvas2dMsg::DrawImageInOther(&lt;br /&gt;
            other_canvas_id,&lt;br /&gt;
            image_size,&lt;br /&gt;
            dest_rect,&lt;br /&gt;
            source_rect,&lt;br /&gt;
            smoothing&lt;br /&gt;
        ) =&amp;gt; {&lt;br /&gt;
            let mut image_data = self.canvas(canvas_id).read_pixels(&lt;br /&gt;
                        source_rect.to_i32(),&lt;br /&gt;
                        image_size);&lt;br /&gt;
            // TODO: avoid double byte_swap.&lt;br /&gt;
            byte_swap(&amp;amp;mut image_data);&lt;br /&gt;
            self.canvas(other_canvas_id).draw_image(&lt;br /&gt;
                image_data.into(),&lt;br /&gt;
                source_rect.size,&lt;br /&gt;
                dest_rect,&lt;br /&gt;
                source_rect,&lt;br /&gt;
                smoothing,&lt;br /&gt;
            );&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It pulls some data out of one CanvasData and then calls a method on the other CanvasData. For this message to be handled, a decision had to be made. Should CanvasData be aware of the existence of ''other'' CanvasData objects or should CanvasPaintThread do some processing to avoid that? There is the third option of making another object to handle it, but seeing as it's only a single message, that option was considered overkill at best, likely far worse. In the end, it was considered a smaller violation of proper design principles to let CanvasPaintThread move data from one CanvasData to another than to inform CanvasData structures about each other.&lt;br /&gt;
&lt;br /&gt;
====CanvasData====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasData&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice the similarities between CanvasData and the old form of CanvasPaintThread! Now CanvasData does all the things CanvasPaintThread used to do for the purposes of painting on the canvases (for example, bezier_curve_to, arc, and set_line_cap among many others). &lt;br /&gt;
&lt;br /&gt;
There's nothing particularly ''new'' in CanvasData. It's all just moved from CanvasPaintThread. &lt;br /&gt;
&lt;br /&gt;
It is a very focused class now, though. All it does is paint on canvases. There's no processing of messages, only painting. Moreover, the draw_image_in_other function is nowhere to be found, instead replaced by a small amount of processing done by CanvasPaintThread, which just calls draw_image on the one that was originally considered &amp;quot;other&amp;quot; so there's no communication between the CanvasData structures ''at all''. &lt;br /&gt;
&lt;br /&gt;
===New Form's Improvements===&lt;br /&gt;
====Design====&lt;br /&gt;
The new form keeps the responsibilities of converting CanvasMsg enums into their contents and using those contents to paint canvases separate, which improves the overall adherence to the Single Responsibility Principle of Servo. There was also a lot of odd indentation and otherwise messy code in the old form of CanvasPaintThread, which, in the process of preparing the pull request for these changes, were cleaned up, making the overall tidyness of Servo improve.&lt;br /&gt;
&lt;br /&gt;
====Performance====&lt;br /&gt;
The new implementation is also much faster when multiple canvases are involved because there's no need for threading delay to send messages back and forth, waiting for those messages to be sent and received. There's less room for usage of multiple cores to speed up processing, but Servo is already so ''very'' parallel that there will be ''something'' to keep the other cores busy when CanvasPaintThread is stuck on one thread. &lt;br /&gt;
&lt;br /&gt;
Slither.io doesn't run properly on my machine either before or after the changes, which makes reporting on the success of the changes with respect to Slither.io difficult at best. The framerate improved dramatically, even if it looks like... well... this still. I can't imagine that a website with over 3500 canvases could be made to run more slowly with this change, though. &lt;br /&gt;
&lt;br /&gt;
[[File:Slither.png]]&lt;br /&gt;
&lt;br /&gt;
Using our timed drawimage test, the performance improvement is... well... not really there. On the development build, the drawing time was cut nearly in half from around 19ms to around 9ms, but on the release build, the drawing time is effectively identical, varying between 1.3ms and 1.7ms for both versions. This isn't too surprising, seeing as only two canvases are made and the cost of communicating between two threads isn't very expensive compared to the thousands that the change was made to address.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The rendering of 2D canvases has been entirely moved to a single thread with each canvas identified by a CanvasId. The pull request for the final project is [https://github.com/servo/servo/pull/20680 here]. As of 4/23/2018, the tests are passing and only various &amp;quot;nit&amp;quot;s are being worked through. A merge is expected very soon.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116799</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116799"/>
		<updated>2018-04-24T03:05:48Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* CanvasPaintThread */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed. Also, Rust only has structs and traits, which are very different from classes and interfaces in terms of usage. Inheritance is effectively nonexistent in Rust, so GoF patterns are nearly always impossible to implement in Rust. &lt;br /&gt;
&lt;br /&gt;
Part of the goal of the Subsequent Steps was to increase the compliance to the Separation of Responsibilities principle, though. It took an object that previously both processed messages and painted canvases and converted it into an object that processes messages and another object that paints canvases.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. They did little to nothing to change the actual functionality of Servo, instead setting the Subsequent Steps up to have a smooth transition by finding all of the users of CanvasPaintThread and making them send CanvasIds, which can then be used to change CanvasPaintThread to the single-threaded design desired without having to touch the users again.&lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project. It builds off of what the Initial Steps lay down. Since the Initial Steps set up all of the users of CanvasPaintThread (even indirect users) to send CanvasIds with their messages, the conversion to use CanvasIds to identify individual canvases was seamless and invisible to the users.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
Previously, a CanvasPaintThread was made for every Canvas, which was very slow when there are many Canvases. To fix this, a single CanvasPaintThread was made that manages all the canvases. The data previously stored in CanvasPaintThread unique to each Canvas was moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Previously, communication channels were opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. Now, there is a single channel that's repeatedly cloned which instead connects the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
These changes involved moving nearly the entire contents of &amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt; into the new file &amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There were slight changes to &amp;lt;code&amp;gt;servo/components/constellation/constellation.rs&amp;lt;/code&amp;gt; so that it doesn't try to create multiple CanvasPaintThreads, but those changes were minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
There were also changes to &amp;lt;code&amp;gt;servo/components/canvas_traits/canvas.rs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;servo/components/script/dom/canvasrenderingcontext2d.rs&amp;lt;/code&amp;gt; because of the removed parts of Canvas2dMsg::DrawImageInOther&lt;br /&gt;
&lt;br /&gt;
===Initial Form of CanvasPaintThread===&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CanvasPaintThread initially stored all the information about a particular canvas. This includes both information used to represent the pixels actually on the canvas and information used to support drawing on the canvas. &lt;br /&gt;
&lt;br /&gt;
There were many, many functions in the previous form of CanvasPaintThread because all the actual painting was done there. &lt;br /&gt;
&lt;br /&gt;
CanvasIds were not usefully used. They were simply added in the initial steps so that the grunt work for the subsequent steps were simpler to implement and more focused.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===New Form of CanvasPaintThread===&lt;br /&gt;
====CanvasPaintThread====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread &amp;lt;'a&amp;gt; {&lt;br /&gt;
        canvases: HashMap&amp;lt;CanvasId, CanvasData&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        next_canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new CanvasPaintThread is much leaner. A single CanvasPaintThread exists with nothing but a HashMap of CanvasId-&amp;gt;CanvasData structures and a CanvasId to represent what the next CanvasId will be.&lt;br /&gt;
&lt;br /&gt;
The only functions it has are start (for initially starting it and also the thread itself, which passes CanvasMsg enums it receives around), create_canvas (for generating a new CanvasData structure), canvas (which is just a wrapper for the canvases hashmap to hide some ugliness in Rust's syntax), and process_canvas_2d_message (which exists solely because there are a lot of Canvas2dMsg enum variants and making the thread itself pass them around makes the code very hard to read).&lt;br /&gt;
&lt;br /&gt;
Below is a snippet from process_canvas_2d_message, to give an idea as to what CanvasPaintThread does in general. There are far too many variants of the Canvas2dMsg enum to be reasonably put in this space, but the following snippet should give a rather good idea what it does in general.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    match message {&lt;br /&gt;
        Canvas2dMsg::FillText(text, x, y, max_width) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).fill_text(text, x, y, max_width)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::FillRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).fill_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::StrokeRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).stroke_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::ClearRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).clear_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
    ...&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In each Canvas2dMsg enum variant's &amp;quot;match&amp;quot; (think of it like a case statement for a switch but fancier), CanvasPaintThread simply takes the values out of the enum then calls the appropriate function on the appropriate CanvasData structure with those values. It does no checking of those values or otherwise processing them, simply passing them along.&lt;br /&gt;
&lt;br /&gt;
There is one exception to this rule, but the message forces itself to act that way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    Canvas2dMsg::DrawImageInOther(&lt;br /&gt;
            other_canvas_id,&lt;br /&gt;
            image_size,&lt;br /&gt;
            dest_rect,&lt;br /&gt;
            source_rect,&lt;br /&gt;
            smoothing&lt;br /&gt;
        ) =&amp;gt; {&lt;br /&gt;
            let mut image_data = self.canvas(canvas_id).read_pixels(&lt;br /&gt;
                        source_rect.to_i32(),&lt;br /&gt;
                        image_size);&lt;br /&gt;
            // TODO: avoid double byte_swap.&lt;br /&gt;
            byte_swap(&amp;amp;mut image_data);&lt;br /&gt;
            self.canvas(other_canvas_id).draw_image(&lt;br /&gt;
                image_data.into(),&lt;br /&gt;
                source_rect.size,&lt;br /&gt;
                dest_rect,&lt;br /&gt;
                source_rect,&lt;br /&gt;
                smoothing,&lt;br /&gt;
            );&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It pulls some data out of one CanvasData and then calls a method on the other CanvasData. For this message to be handled, a decision had to be made. Should CanvasData be aware of the existence of ''other'' CanvasData objects or should CanvasPaintThread do some processing to avoid that? There is the third option of making another object to handle it, but seeing as it's only a single message, that option was considered overkill at best, likely far worse. In the end, it was considered a smaller violation of proper design principles to let CanvasPaintThread move data from one CanvasData to another than to inform CanvasData structures about each other.&lt;br /&gt;
&lt;br /&gt;
====CanvasData====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasData&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice the similarities between CanvasData and the old form of CanvasPaintThread! Now CanvasData does all the things CanvasPaintThread used to do for the purposes of painting on the canvases (for example, bezier_curve_to, arc, and set_line_cap among many others). &lt;br /&gt;
&lt;br /&gt;
There's nothing particularly ''new'' in CanvasData. It's all just moved from CanvasPaintThread. &lt;br /&gt;
&lt;br /&gt;
It is a very focused class now, though. All it does is paint on canvases. There's no processing of messages, only painting. Moreover, the draw_image_in_other function is nowhere to be found, instead replaced by a small amount of processing done by CanvasPaintThread, which just calls draw_image on the one that was originally considered &amp;quot;other&amp;quot; so there's no communication between the CanvasData structures ''at all''. &lt;br /&gt;
&lt;br /&gt;
===New Form's Improvements===&lt;br /&gt;
====Design====&lt;br /&gt;
The new form keeps the responsibilities of converting CanvasMsg enums into their contents and using those contents to paint canvases separate, which improves the overall adherence to the Single Responsibility Principle of Servo. There was also a lot of odd indentation and otherwise messy code in the old form of CanvasPaintThread, which, in the process of preparing the pull request for these changes, were cleaned up, making the overall tidyness of Servo improve.&lt;br /&gt;
&lt;br /&gt;
====Performance====&lt;br /&gt;
The new implementation is also much faster when multiple canvases are involved because there's no need for threading delay to send messages back and forth, waiting for those messages to be sent and received. There's less room for usage of multiple cores to speed up processing, but Servo is already so ''very'' parallel that there will be ''something'' to keep the other cores busy when CanvasPaintThread is stuck on one thread. &lt;br /&gt;
&lt;br /&gt;
Slither.io doesn't run properly on my machine either before or after the changes, which makes reporting on the success of the changes with respect to Slither.io difficult at best. The framerate improved dramatically, even if it looks like... well... this still. I can't imagine that a website with over 3500 canvases could be made to run more slowly with this change, though. &lt;br /&gt;
&lt;br /&gt;
[[File:Slither.png]]&lt;br /&gt;
&lt;br /&gt;
Using our timed drawimage test, the performance improvement is... well... not really there. On the development build, the drawing time was cut nearly in half from around 19ms to around 9ms, but on the release build, the drawing time is effectively identical, varying between 1.3ms and 1.7ms for both versions. This isn't too surprising, seeing as only two canvases are made and the cost of communicating between two threads isn't very expensive compared to the thousands that the change was made to address.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The rendering of 2D canvases has been entirely moved to a single thread with each canvas identified by a CanvasId. The pull request for the final project is [https://github.com/servo/servo/pull/20680 here]. As of 4/23/2018, the tests are passing and only various &amp;quot;nit&amp;quot;s are being worked through. A merge is expected very soon.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116798</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116798"/>
		<updated>2018-04-24T03:05:35Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* CanvasPaintThread */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed. Also, Rust only has structs and traits, which are very different from classes and interfaces in terms of usage. Inheritance is effectively nonexistent in Rust, so GoF patterns are nearly always impossible to implement in Rust. &lt;br /&gt;
&lt;br /&gt;
Part of the goal of the Subsequent Steps was to increase the compliance to the Separation of Responsibilities principle, though. It took an object that previously both processed messages and painted canvases and converted it into an object that processes messages and another object that paints canvases.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. They did little to nothing to change the actual functionality of Servo, instead setting the Subsequent Steps up to have a smooth transition by finding all of the users of CanvasPaintThread and making them send CanvasIds, which can then be used to change CanvasPaintThread to the single-threaded design desired without having to touch the users again.&lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project. It builds off of what the Initial Steps lay down. Since the Initial Steps set up all of the users of CanvasPaintThread (even indirect users) to send CanvasIds with their messages, the conversion to use CanvasIds to identify individual canvases was seamless and invisible to the users.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
Previously, a CanvasPaintThread was made for every Canvas, which was very slow when there are many Canvases. To fix this, a single CanvasPaintThread was made that manages all the canvases. The data previously stored in CanvasPaintThread unique to each Canvas was moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Previously, communication channels were opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. Now, there is a single channel that's repeatedly cloned which instead connects the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
These changes involved moving nearly the entire contents of &amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt; into the new file &amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There were slight changes to &amp;lt;code&amp;gt;servo/components/constellation/constellation.rs&amp;lt;/code&amp;gt; so that it doesn't try to create multiple CanvasPaintThreads, but those changes were minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
There were also changes to &amp;lt;code&amp;gt;servo/components/canvas_traits/canvas.rs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;servo/components/script/dom/canvasrenderingcontext2d.rs&amp;lt;/code&amp;gt; because of the removed parts of Canvas2dMsg::DrawImageInOther&lt;br /&gt;
&lt;br /&gt;
===Initial Form of CanvasPaintThread===&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CanvasPaintThread initially stored all the information about a particular canvas. This includes both information used to represent the pixels actually on the canvas and information used to support drawing on the canvas. &lt;br /&gt;
&lt;br /&gt;
There were many, many functions in the previous form of CanvasPaintThread because all the actual painting was done there. &lt;br /&gt;
&lt;br /&gt;
CanvasIds were not usefully used. They were simply added in the initial steps so that the grunt work for the subsequent steps were simpler to implement and more focused.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===New Form of CanvasPaintThread===&lt;br /&gt;
====CanvasPaintThread====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread &amp;lt;'a&amp;gt; {&lt;br /&gt;
        canvases: HashMap&amp;lt;CanvasId, CanvasData&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        next_canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new CanvasPaintThread is much leaner. A single CanvasPaintThread exists with nothing but a HashMap of CanvasId-&amp;gt;CanvasData structures and a CanvasId to represent what the next CanvasId will be.&lt;br /&gt;
&lt;br /&gt;
The only functions it has are start (for initially starting it and also the thread itself, which passes CanvasMsg enums it receives around), create_canvas (for generating a new CanvasData structure), canvas (which is just a wrapper for the canvases hashmap to hide some ugliness in Rust's syntax), and process_canvas_2d_message (which exists solely because there are a lot of Canvas2dMsg enum variants and making the thread itself pass them around makes the code very hard to read).&lt;br /&gt;
&lt;br /&gt;
Below is a snippet from process_canvas_2d_message, to give an idea as to what CanvasPaintThread does in general. There are far too many variants of the Canvas2dMsg enum to be reasonably put in this space, but the following snippet should give a rather good idea what it does in general.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    match message {&lt;br /&gt;
        Canvas2dMsg::FillText(text, x, y, max_width) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).fill_text(text, x, y, max_width)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::FillRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).fill_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::StrokeRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).stroke_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
        Canvas2dMsg::ClearRect(ref rect) =&amp;gt; {&lt;br /&gt;
            self.canvas(canvas_id).clear_rect(rect)&lt;br /&gt;
        },&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In each Canvas2dMsg enum variant's &amp;quot;match&amp;quot; (think of it like a case statement for a switch but fancier), CanvasPaintThread simply takes the values out of the enum then calls the appropriate function on the appropriate CanvasData structure with those values. It does no checking of those values or otherwise processing them, simply passing them along.&lt;br /&gt;
&lt;br /&gt;
There is one exception to this rule, but the message forces itself to act that way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    Canvas2dMsg::DrawImageInOther(&lt;br /&gt;
            other_canvas_id,&lt;br /&gt;
            image_size,&lt;br /&gt;
            dest_rect,&lt;br /&gt;
            source_rect,&lt;br /&gt;
            smoothing&lt;br /&gt;
        ) =&amp;gt; {&lt;br /&gt;
            let mut image_data = self.canvas(canvas_id).read_pixels(&lt;br /&gt;
                        source_rect.to_i32(),&lt;br /&gt;
                        image_size);&lt;br /&gt;
            // TODO: avoid double byte_swap.&lt;br /&gt;
            byte_swap(&amp;amp;mut image_data);&lt;br /&gt;
            self.canvas(other_canvas_id).draw_image(&lt;br /&gt;
                image_data.into(),&lt;br /&gt;
                source_rect.size,&lt;br /&gt;
                dest_rect,&lt;br /&gt;
                source_rect,&lt;br /&gt;
                smoothing,&lt;br /&gt;
            );&lt;br /&gt;
        },&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It pulls some data out of one CanvasData and then calls a method on the other CanvasData. For this message to be handled, a decision had to be made. Should CanvasData be aware of the existence of ''other'' CanvasData objects or should CanvasPaintThread do some processing to avoid that? There is the third option of making another object to handle it, but seeing as it's only a single message, that option was considered overkill at best, likely far worse. In the end, it was considered a smaller violation of proper design principles to let CanvasPaintThread move data from one CanvasData to another than to inform CanvasData structures about each other.&lt;br /&gt;
&lt;br /&gt;
====CanvasData====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasData&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice the similarities between CanvasData and the old form of CanvasPaintThread! Now CanvasData does all the things CanvasPaintThread used to do for the purposes of painting on the canvases (for example, bezier_curve_to, arc, and set_line_cap among many others). &lt;br /&gt;
&lt;br /&gt;
There's nothing particularly ''new'' in CanvasData. It's all just moved from CanvasPaintThread. &lt;br /&gt;
&lt;br /&gt;
It is a very focused class now, though. All it does is paint on canvases. There's no processing of messages, only painting. Moreover, the draw_image_in_other function is nowhere to be found, instead replaced by a small amount of processing done by CanvasPaintThread, which just calls draw_image on the one that was originally considered &amp;quot;other&amp;quot; so there's no communication between the CanvasData structures ''at all''. &lt;br /&gt;
&lt;br /&gt;
===New Form's Improvements===&lt;br /&gt;
====Design====&lt;br /&gt;
The new form keeps the responsibilities of converting CanvasMsg enums into their contents and using those contents to paint canvases separate, which improves the overall adherence to the Single Responsibility Principle of Servo. There was also a lot of odd indentation and otherwise messy code in the old form of CanvasPaintThread, which, in the process of preparing the pull request for these changes, were cleaned up, making the overall tidyness of Servo improve.&lt;br /&gt;
&lt;br /&gt;
====Performance====&lt;br /&gt;
The new implementation is also much faster when multiple canvases are involved because there's no need for threading delay to send messages back and forth, waiting for those messages to be sent and received. There's less room for usage of multiple cores to speed up processing, but Servo is already so ''very'' parallel that there will be ''something'' to keep the other cores busy when CanvasPaintThread is stuck on one thread. &lt;br /&gt;
&lt;br /&gt;
Slither.io doesn't run properly on my machine either before or after the changes, which makes reporting on the success of the changes with respect to Slither.io difficult at best. The framerate improved dramatically, even if it looks like... well... this still. I can't imagine that a website with over 3500 canvases could be made to run more slowly with this change, though. &lt;br /&gt;
&lt;br /&gt;
[[File:Slither.png]]&lt;br /&gt;
&lt;br /&gt;
Using our timed drawimage test, the performance improvement is... well... not really there. On the development build, the drawing time was cut nearly in half from around 19ms to around 9ms, but on the release build, the drawing time is effectively identical, varying between 1.3ms and 1.7ms for both versions. This isn't too surprising, seeing as only two canvases are made and the cost of communicating between two threads isn't very expensive compared to the thousands that the change was made to address.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The rendering of 2D canvases has been entirely moved to a single thread with each canvas identified by a CanvasId. The pull request for the final project is [https://github.com/servo/servo/pull/20680 here]. As of 4/23/2018, the tests are passing and only various &amp;quot;nit&amp;quot;s are being worked through. A merge is expected very soon.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116797</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116797"/>
		<updated>2018-04-24T02:50:04Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Initial Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed. Also, Rust only has structs and traits, which are very different from classes and interfaces in terms of usage. Inheritance is effectively nonexistent in Rust, so GoF patterns are nearly always impossible to implement in Rust. &lt;br /&gt;
&lt;br /&gt;
Part of the goal of the Subsequent Steps was to increase the compliance to the Separation of Responsibilities principle, though. It took an object that previously both processed messages and painted canvases and converted it into an object that processes messages and another object that paints canvases.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. They did little to nothing to change the actual functionality of Servo, instead setting the Subsequent Steps up to have a smooth transition by finding all of the users of CanvasPaintThread and making them send CanvasIds, which can then be used to change CanvasPaintThread to the single-threaded design desired without having to touch the users again.&lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project. It builds off of what the Initial Steps lay down. Since the Initial Steps set up all of the users of CanvasPaintThread (even indirect users) to send CanvasIds with their messages, the conversion to use CanvasIds to identify individual canvases was seamless and invisible to the users.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
Previously, a CanvasPaintThread was made for every Canvas, which was very slow when there are many Canvases. To fix this, a single CanvasPaintThread was made that manages all the canvases. The data previously stored in CanvasPaintThread unique to each Canvas was moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Previously, communication channels were opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. Now, there is a single channel that's repeatedly cloned which instead connects the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
These changes involved moving nearly the entire contents of &amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt; into the new file &amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There were slight changes to &amp;lt;code&amp;gt;servo/components/constellation/constellation.rs&amp;lt;/code&amp;gt; so that it doesn't try to create multiple CanvasPaintThreads, but those changes were minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
There were also changes to &amp;lt;code&amp;gt;servo/components/canvas_traits/canvas.rs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;servo/components/script/dom/canvasrenderingcontext2d.rs&amp;lt;/code&amp;gt; because of the removed parts of Canvas2dMsg::DrawImageInOther&lt;br /&gt;
&lt;br /&gt;
===Initial Form of CanvasPaintThread===&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CanvasPaintThread initially stored all the information about a particular canvas. This includes both information used to represent the pixels actually on the canvas and information used to support drawing on the canvas. &lt;br /&gt;
&lt;br /&gt;
There were many, many functions in the previous form of CanvasPaintThread because all the actual painting was done there. &lt;br /&gt;
&lt;br /&gt;
CanvasIds were not usefully used. They were simply added in the initial steps so that the grunt work for the subsequent steps were simpler to implement and more focused.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===New Form of CanvasPaintThread===&lt;br /&gt;
====CanvasPaintThread====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread &amp;lt;'a&amp;gt; {&lt;br /&gt;
        canvases: HashMap&amp;lt;CanvasId, CanvasData&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        next_canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new CanvasPaintThread is much leaner. A single CanvasPaintThread exists with nothing but a HashMap of CanvasId-&amp;gt;CanvasData structures and a CanvasId to represent what the next CanvasId will be.&lt;br /&gt;
&lt;br /&gt;
The only functions it has are start (for initially starting it and also the thread itself, which passes CanvasMsg enums it receives around), create_canvas (for generating a new CanvasData structure), and process_canvas_2d_message (which exists solely because there are a lot of Canvas2dMsg enum variants and making the thread itself pass them around makes the code very hard to read).&lt;br /&gt;
&lt;br /&gt;
====CanvasData====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasData&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice the similarities between CanvasData and the old form of CanvasPaintThread! Now CanvasData does all the things CanvasPaintThread used to do for the purposes of painting on the canvases (for example, bezier_curve_to, arc, and set_line_cap among many others). &lt;br /&gt;
&lt;br /&gt;
There's nothing particularly ''new'' in CanvasData. It's all just moved from CanvasPaintThread. &lt;br /&gt;
&lt;br /&gt;
It is a very focused class now, though. All it does is paint on canvases. There's no processing of messages, only painting. Moreover, the draw_image_in_other function is nowhere to be found, instead replaced by a small amount of processing done by CanvasPaintThread, which just calls draw_image on the one that was originally considered &amp;quot;other&amp;quot; so there's no communication between the CanvasData structures ''at all''. &lt;br /&gt;
&lt;br /&gt;
===New Form's Improvements===&lt;br /&gt;
====Design====&lt;br /&gt;
The new form keeps the responsibilities of converting CanvasMsg enums into their contents and using those contents to paint canvases separate, which improves the overall adherence to the Single Responsibility Principle of Servo. There was also a lot of odd indentation and otherwise messy code in the old form of CanvasPaintThread, which, in the process of preparing the pull request for these changes, were cleaned up, making the overall tidyness of Servo improve.&lt;br /&gt;
&lt;br /&gt;
====Performance====&lt;br /&gt;
The new implementation is also much faster when multiple canvases are involved because there's no need for threading delay to send messages back and forth, waiting for those messages to be sent and received. There's less room for usage of multiple cores to speed up processing, but Servo is already so ''very'' parallel that there will be ''something'' to keep the other cores busy when CanvasPaintThread is stuck on one thread. &lt;br /&gt;
&lt;br /&gt;
Slither.io doesn't run properly on my machine either before or after the changes, which makes reporting on the success of the changes with respect to Slither.io difficult at best. The framerate improved dramatically, even if it looks like... well... this still. I can't imagine that a website with over 3500 canvases could be made to run more slowly with this change, though. &lt;br /&gt;
&lt;br /&gt;
[[File:Slither.png]]&lt;br /&gt;
&lt;br /&gt;
Using our timed drawimage test, the performance improvement is... well... not really there. On the development build, the drawing time was cut nearly in half from around 19ms to around 9ms, but on the release build, the drawing time is effectively identical, varying between 1.3ms and 1.7ms for both versions. This isn't too surprising, seeing as only two canvases are made and the cost of communicating between two threads isn't very expensive compared to the thousands that the change was made to address.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The rendering of 2D canvases has been entirely moved to a single thread with each canvas identified by a CanvasId. The pull request for the final project is [https://github.com/servo/servo/pull/20680 here]. As of 4/23/2018, the tests are passing and only various &amp;quot;nit&amp;quot;s are being worked through. A merge is expected very soon.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116796</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116796"/>
		<updated>2018-04-24T02:47:22Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Design Pattern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed. Also, Rust only has structs and traits, which are very different from classes and interfaces in terms of usage. Inheritance is effectively nonexistent in Rust, so GoF patterns are nearly always impossible to implement in Rust. &lt;br /&gt;
&lt;br /&gt;
Part of the goal of the Subsequent Steps was to increase the compliance to the Separation of Responsibilities principle, though. It took an object that previously both processed messages and painted canvases and converted it into an object that processes messages and another object that paints canvases.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. &lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project. It builds off of what the Initial Steps lay down. Since the Initial Steps set up all of the users of CanvasPaintThread (even indirect users) to send CanvasIds with their messages, the conversion to use CanvasIds to identify individual canvases was seamless and invisible to the users.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
Previously, a CanvasPaintThread was made for every Canvas, which was very slow when there are many Canvases. To fix this, a single CanvasPaintThread was made that manages all the canvases. The data previously stored in CanvasPaintThread unique to each Canvas was moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Previously, communication channels were opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. Now, there is a single channel that's repeatedly cloned which instead connects the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
These changes involved moving nearly the entire contents of &amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt; into the new file &amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There were slight changes to &amp;lt;code&amp;gt;servo/components/constellation/constellation.rs&amp;lt;/code&amp;gt; so that it doesn't try to create multiple CanvasPaintThreads, but those changes were minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
There were also changes to &amp;lt;code&amp;gt;servo/components/canvas_traits/canvas.rs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;servo/components/script/dom/canvasrenderingcontext2d.rs&amp;lt;/code&amp;gt; because of the removed parts of Canvas2dMsg::DrawImageInOther&lt;br /&gt;
&lt;br /&gt;
===Initial Form of CanvasPaintThread===&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CanvasPaintThread initially stored all the information about a particular canvas. This includes both information used to represent the pixels actually on the canvas and information used to support drawing on the canvas. &lt;br /&gt;
&lt;br /&gt;
There were many, many functions in the previous form of CanvasPaintThread because all the actual painting was done there. &lt;br /&gt;
&lt;br /&gt;
CanvasIds were not usefully used. They were simply added in the initial steps so that the grunt work for the subsequent steps were simpler to implement and more focused.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===New Form of CanvasPaintThread===&lt;br /&gt;
====CanvasPaintThread====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread &amp;lt;'a&amp;gt; {&lt;br /&gt;
        canvases: HashMap&amp;lt;CanvasId, CanvasData&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        next_canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new CanvasPaintThread is much leaner. A single CanvasPaintThread exists with nothing but a HashMap of CanvasId-&amp;gt;CanvasData structures and a CanvasId to represent what the next CanvasId will be.&lt;br /&gt;
&lt;br /&gt;
The only functions it has are start (for initially starting it and also the thread itself, which passes CanvasMsg enums it receives around), create_canvas (for generating a new CanvasData structure), and process_canvas_2d_message (which exists solely because there are a lot of Canvas2dMsg enum variants and making the thread itself pass them around makes the code very hard to read).&lt;br /&gt;
&lt;br /&gt;
====CanvasData====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasData&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice the similarities between CanvasData and the old form of CanvasPaintThread! Now CanvasData does all the things CanvasPaintThread used to do for the purposes of painting on the canvases (for example, bezier_curve_to, arc, and set_line_cap among many others). &lt;br /&gt;
&lt;br /&gt;
There's nothing particularly ''new'' in CanvasData. It's all just moved from CanvasPaintThread. &lt;br /&gt;
&lt;br /&gt;
It is a very focused class now, though. All it does is paint on canvases. There's no processing of messages, only painting. Moreover, the draw_image_in_other function is nowhere to be found, instead replaced by a small amount of processing done by CanvasPaintThread, which just calls draw_image on the one that was originally considered &amp;quot;other&amp;quot; so there's no communication between the CanvasData structures ''at all''. &lt;br /&gt;
&lt;br /&gt;
===New Form's Improvements===&lt;br /&gt;
====Design====&lt;br /&gt;
The new form keeps the responsibilities of converting CanvasMsg enums into their contents and using those contents to paint canvases separate, which improves the overall adherence to the Single Responsibility Principle of Servo. There was also a lot of odd indentation and otherwise messy code in the old form of CanvasPaintThread, which, in the process of preparing the pull request for these changes, were cleaned up, making the overall tidyness of Servo improve.&lt;br /&gt;
&lt;br /&gt;
====Performance====&lt;br /&gt;
The new implementation is also much faster when multiple canvases are involved because there's no need for threading delay to send messages back and forth, waiting for those messages to be sent and received. There's less room for usage of multiple cores to speed up processing, but Servo is already so ''very'' parallel that there will be ''something'' to keep the other cores busy when CanvasPaintThread is stuck on one thread. &lt;br /&gt;
&lt;br /&gt;
Slither.io doesn't run properly on my machine either before or after the changes, which makes reporting on the success of the changes with respect to Slither.io difficult at best. The framerate improved dramatically, even if it looks like... well... this still. I can't imagine that a website with over 3500 canvases could be made to run more slowly with this change, though. &lt;br /&gt;
&lt;br /&gt;
[[File:Slither.png]]&lt;br /&gt;
&lt;br /&gt;
Using our timed drawimage test, the performance improvement is... well... not really there. On the development build, the drawing time was cut nearly in half from around 19ms to around 9ms, but on the release build, the drawing time is effectively identical, varying between 1.3ms and 1.7ms for both versions. This isn't too surprising, seeing as only two canvases are made and the cost of communicating between two threads isn't very expensive compared to the thousands that the change was made to address.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The rendering of 2D canvases has been entirely moved to a single thread with each canvas identified by a CanvasId. The pull request for the final project is [https://github.com/servo/servo/pull/20680 here]. As of 4/23/2018, the tests are passing and only various &amp;quot;nit&amp;quot;s are being worked through. A merge is expected very soon.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116795</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116795"/>
		<updated>2018-04-24T02:43:56Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. &lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project. It builds off of what the Initial Steps lay down. Since the Initial Steps set up all of the users of CanvasPaintThread (even indirect users) to send CanvasIds with their messages, the conversion to use CanvasIds to identify individual canvases was seamless and invisible to the users.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
Previously, a CanvasPaintThread was made for every Canvas, which was very slow when there are many Canvases. To fix this, a single CanvasPaintThread was made that manages all the canvases. The data previously stored in CanvasPaintThread unique to each Canvas was moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Previously, communication channels were opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. Now, there is a single channel that's repeatedly cloned which instead connects the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
These changes involved moving nearly the entire contents of &amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt; into the new file &amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There were slight changes to &amp;lt;code&amp;gt;servo/components/constellation/constellation.rs&amp;lt;/code&amp;gt; so that it doesn't try to create multiple CanvasPaintThreads, but those changes were minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
There were also changes to &amp;lt;code&amp;gt;servo/components/canvas_traits/canvas.rs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;servo/components/script/dom/canvasrenderingcontext2d.rs&amp;lt;/code&amp;gt; because of the removed parts of Canvas2dMsg::DrawImageInOther&lt;br /&gt;
&lt;br /&gt;
===Initial Form of CanvasPaintThread===&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CanvasPaintThread initially stored all the information about a particular canvas. This includes both information used to represent the pixels actually on the canvas and information used to support drawing on the canvas. &lt;br /&gt;
&lt;br /&gt;
There were many, many functions in the previous form of CanvasPaintThread because all the actual painting was done there. &lt;br /&gt;
&lt;br /&gt;
CanvasIds were not usefully used. They were simply added in the initial steps so that the grunt work for the subsequent steps were simpler to implement and more focused.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===New Form of CanvasPaintThread===&lt;br /&gt;
====CanvasPaintThread====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread &amp;lt;'a&amp;gt; {&lt;br /&gt;
        canvases: HashMap&amp;lt;CanvasId, CanvasData&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        next_canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new CanvasPaintThread is much leaner. A single CanvasPaintThread exists with nothing but a HashMap of CanvasId-&amp;gt;CanvasData structures and a CanvasId to represent what the next CanvasId will be.&lt;br /&gt;
&lt;br /&gt;
The only functions it has are start (for initially starting it and also the thread itself, which passes CanvasMsg enums it receives around), create_canvas (for generating a new CanvasData structure), and process_canvas_2d_message (which exists solely because there are a lot of Canvas2dMsg enum variants and making the thread itself pass them around makes the code very hard to read).&lt;br /&gt;
&lt;br /&gt;
====CanvasData====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasData&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice the similarities between CanvasData and the old form of CanvasPaintThread! Now CanvasData does all the things CanvasPaintThread used to do for the purposes of painting on the canvases (for example, bezier_curve_to, arc, and set_line_cap among many others). &lt;br /&gt;
&lt;br /&gt;
There's nothing particularly ''new'' in CanvasData. It's all just moved from CanvasPaintThread. &lt;br /&gt;
&lt;br /&gt;
It is a very focused class now, though. All it does is paint on canvases. There's no processing of messages, only painting. Moreover, the draw_image_in_other function is nowhere to be found, instead replaced by a small amount of processing done by CanvasPaintThread, which just calls draw_image on the one that was originally considered &amp;quot;other&amp;quot; so there's no communication between the CanvasData structures ''at all''. &lt;br /&gt;
&lt;br /&gt;
===New Form's Improvements===&lt;br /&gt;
====Design====&lt;br /&gt;
The new form keeps the responsibilities of converting CanvasMsg enums into their contents and using those contents to paint canvases separate, which improves the overall adherence to the Single Responsibility Principle of Servo. There was also a lot of odd indentation and otherwise messy code in the old form of CanvasPaintThread, which, in the process of preparing the pull request for these changes, were cleaned up, making the overall tidyness of Servo improve.&lt;br /&gt;
&lt;br /&gt;
====Performance====&lt;br /&gt;
The new implementation is also much faster when multiple canvases are involved because there's no need for threading delay to send messages back and forth, waiting for those messages to be sent and received. There's less room for usage of multiple cores to speed up processing, but Servo is already so ''very'' parallel that there will be ''something'' to keep the other cores busy when CanvasPaintThread is stuck on one thread. &lt;br /&gt;
&lt;br /&gt;
Slither.io doesn't run properly on my machine either before or after the changes, which makes reporting on the success of the changes with respect to Slither.io difficult at best. The framerate improved dramatically, even if it looks like... well... this still. I can't imagine that a website with over 3500 canvases could be made to run more slowly with this change, though. &lt;br /&gt;
&lt;br /&gt;
[[File:Slither.png]]&lt;br /&gt;
&lt;br /&gt;
Using our timed drawimage test, the performance improvement is... well... not really there. On the development build, the drawing time was cut nearly in half from around 19ms to around 9ms, but on the release build, the drawing time is effectively identical, varying between 1.3ms and 1.7ms for both versions. This isn't too surprising, seeing as only two canvases are made and the cost of communicating between two threads isn't very expensive compared to the thousands that the change was made to address.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The rendering of 2D canvases has been entirely moved to a single thread with each canvas identified by a CanvasId. The pull request for the final project is [https://github.com/servo/servo/pull/20680 here]. As of 4/23/2018, the tests are passing and only various &amp;quot;nit&amp;quot;s are being worked through. A merge is expected very soon.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:Slither.png&amp;diff=116794</id>
		<title>File:Slither.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:Slither.png&amp;diff=116794"/>
		<updated>2018-04-24T02:40:56Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116793</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116793"/>
		<updated>2018-04-24T02:39:44Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Subsequent Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. &lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project. It builds off of what the Initial Steps lay down. Since the Initial Steps set up all of the users of CanvasPaintThread (even indirect users) to send CanvasIds with their messages, the conversion to use CanvasIds to identify individual canvases was seamless and invisible to the users.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
Previously, a CanvasPaintThread was made for every Canvas, which was very slow when there are many Canvases. To fix this, a single CanvasPaintThread was made that manages all the canvases. The data previously stored in CanvasPaintThread unique to each Canvas was moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Previously, communication channels were opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. Now, there is a single channel that's repeatedly cloned which instead connects the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
These changes involved moving nearly the entire contents of &amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt; into the new file &amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
There were slight changes to &amp;lt;code&amp;gt;servo/components/constellation/constellation.rs&amp;lt;/code&amp;gt; so that it doesn't try to create multiple CanvasPaintThreads, but those changes were minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
There were also changes to &amp;lt;code&amp;gt;servo/components/canvas_traits/canvas.rs&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;servo/components/script/dom/canvasrenderingcontext2d.rs&amp;lt;/code&amp;gt; because of the removed parts of Canvas2dMsg::DrawImageInOther&lt;br /&gt;
&lt;br /&gt;
===Initial Form of CanvasPaintThread===&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CanvasPaintThread initially stored all the information about a particular canvas. This includes both information used to represent the pixels actually on the canvas and information used to support drawing on the canvas. &lt;br /&gt;
&lt;br /&gt;
There were many, many functions in the previous form of CanvasPaintThread because all the actual painting was done there. &lt;br /&gt;
&lt;br /&gt;
CanvasIds were not usefully used. They were simply added in the initial steps so that the grunt work for the subsequent steps were simpler to implement and more focused.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===New Form of CanvasPaintThread===&lt;br /&gt;
====CanvasPaintThread====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_paint_thread.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasPaintThread &amp;lt;'a&amp;gt; {&lt;br /&gt;
        canvases: HashMap&amp;lt;CanvasId, CanvasData&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        next_canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The new CanvasPaintThread is much leaner. A single CanvasPaintThread exists with nothing but a HashMap of CanvasId-&amp;gt;CanvasData structures and a CanvasId to represent what the next CanvasId will be.&lt;br /&gt;
&lt;br /&gt;
The only functions it has are start (for initially starting it and also the thread itself, which passes CanvasMsg enums it receives around), create_canvas (for generating a new CanvasData structure), and process_canvas_2d_message (which exists solely because there are a lot of Canvas2dMsg enum variants and making the thread itself pass them around makes the code very hard to read).&lt;br /&gt;
&lt;br /&gt;
====CanvasData====&lt;br /&gt;
From:&lt;br /&gt;
&amp;lt;code&amp;gt;servo/components/canvas/canvas_data.rs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    pub struct CanvasData&amp;lt;'a&amp;gt; {&lt;br /&gt;
        drawtarget: DrawTarget,&lt;br /&gt;
        /// TODO(pcwalton): Support multiple paths.&lt;br /&gt;
        path_builder: PathBuilder,&lt;br /&gt;
        state: CanvasPaintState&amp;lt;'a&amp;gt;,&lt;br /&gt;
        saved_states: Vec&amp;lt;CanvasPaintState&amp;lt;'a&amp;gt;&amp;gt;,&lt;br /&gt;
        webrender_api: webrender_api::RenderApi,&lt;br /&gt;
        image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the next epoch ends.&lt;br /&gt;
        old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        /// An old webrender image key that can be deleted when the current epoch ends.&lt;br /&gt;
        very_old_image_key: Option&amp;lt;webrender_api::ImageKey&amp;gt;,&lt;br /&gt;
        canvas_id: CanvasId,&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may notice the similarities between CanvasData and the old form of CanvasPaintThread! Now CanvasData does all the things CanvasPaintThread used to do for the purposes of painting on the canvases (for example, bezier_curve_to, arc, and set_line_cap among many others). &lt;br /&gt;
&lt;br /&gt;
There's nothing particularly ''new'' in CanvasData. It's all just moved from CanvasPaintThread. &lt;br /&gt;
&lt;br /&gt;
It is a very focused class now, though. All it does is paint on canvases. There's no processing of messages, only painting. Moreover, the draw_image_in_other function is nowhere to be found, instead replaced by a small amount of processing done by CanvasPaintThread, which just calls draw_image on the one that was originally considered &amp;quot;other&amp;quot; so there's no communication between the CanvasData structures ''at all''. &lt;br /&gt;
&lt;br /&gt;
===New Form's Improvements===&lt;br /&gt;
====Design====&lt;br /&gt;
The new form keeps the responsibilities of converting CanvasMsg enums into their contents and using those contents to paint canvases separate, which improves the overall adherence to the Single Responsibility Principle of Servo. There was also a lot of odd indentation and otherwise messy code in the old form of CanvasPaintThread, which, in the process of preparing the pull request for these changes, were cleaned up, making the overall tidyness of Servo improve.&lt;br /&gt;
&lt;br /&gt;
====Performance====&lt;br /&gt;
The new implementation is also much faster when multiple canvases are involved because there's no need for threading delay to send messages back and forth, waiting for those messages to be sent and received. There's less room for usage of multiple cores to speed up processing, but Servo is already so ''very'' parallel that there will be ''something'' to keep the other cores busy when CanvasPaintThread is stuck on one thread. &lt;br /&gt;
&lt;br /&gt;
Slither.io doesn't run properly on my machine either before or after the changes, which makes reporting on the success of the changes with respect to Slither.io difficult at best. The framerate improved dramatically, even if it looks like... well... this still. I can't imagine that a website with over 3500 canvases could be made to run more slowly with this change, though. &lt;br /&gt;
&lt;br /&gt;
[[File:Slither.png]]&lt;br /&gt;
&lt;br /&gt;
Using our timed drawimage test, the performance improvement is... well... not really there. On the development build, the drawing time was cut nearly in half from around 19ms to around 9ms, but on the release build, the drawing time is effectively identical, varying between 1.3ms and 1.7ms for both versions. This isn't too surprising, seeing as only two canvases are made and the cost of communicating between two threads isn't very expensive compared to the thousands that the change was made to address.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps should be able to be completed similarly. The instructions are similarly clear, and the team understands how to work on Servo much more clearly, so the difficulty of initially getting set up will not need to be done again.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116792</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116792"/>
		<updated>2018-04-24T01:15:28Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Subsequent Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. &lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps were the final project.&lt;br /&gt;
&lt;br /&gt;
===Drawing Canvases with one CanvasPaintThread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
There will be slight changes to Constellation so that it doesn't try to create multiple CanvasPaintThreads, but those changes are minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps should be able to be completed similarly. The instructions are similarly clear, and the team understands how to work on Servo much more clearly, so the difficulty of initially getting set up will not need to be done again.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116791</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116791"/>
		<updated>2018-04-24T01:15:02Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Initial Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId (u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
&lt;br /&gt;
The initial steps were the first OSS project. &lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps).&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
===Drawing Canvases with one CanvasPaintThread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
There will be slight changes to Constellation so that it doesn't try to create multiple CanvasPaintThreads, but those changes are minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps should be able to be completed similarly. The instructions are similarly clear, and the team understands how to work on Servo much more clearly, so the difficulty of initially getting set up will not need to be done again.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=MainPage&amp;diff=116583</id>
		<title>MainPage</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=MainPage&amp;diff=116583"/>
		<updated>2018-04-14T01:09:55Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Expertiza */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Expertiza==&lt;br /&gt;
* [[Expertiza documentation]]&lt;br /&gt;
&lt;br /&gt;
* [[CSC/ECE 517 Summer 2008]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2010]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2011]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2012]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2013]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2014]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2015]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2016]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2014]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2015]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2016]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2017]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2017]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project Juniper:Bookmark Enhancements]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1803: Introducing a Student View for Instructors]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1804: OSS project Yellow: Topic management]]&lt;br /&gt;
* [[CSC/ECE_517_Spring_2018- Project E1805: Convolutional data extraction from Github]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1808: Refactor review_mapping_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1810: Show sample submissions and reviews]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018/E1814 Write unit tests for collusion cycle.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018 - E1800: Add past-due assignments to task list]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1812: on the fly calc.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1803: Implement a web page fuzzer to find rendering mismatches ]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project M1803: Implement a web page fuzzer to find rendering mismatches (Part 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018/E1813 Test Menu Items Model]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1816: Visualization for Instructors]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1817: Adding Student-generated Questions to Rubric]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1818:  Role-based reviewing]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1822: Extend the functionality of badging]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1815: Improvements to review grader]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1824: Let course staff as well as students do reviews]]&lt;br /&gt;
* [[CSC/ECE 517 Spring 2018- Project E1819: Improve self review, link self and peer review to derive grades]]&lt;br /&gt;
* [[CSC 456 Spring 2011|CSC 456 Spring 2012]]&lt;br /&gt;
* [[ECE 633]]&lt;br /&gt;
* [[KCU]]&lt;br /&gt;
* [[Progress reports]]&lt;br /&gt;
&lt;br /&gt;
==Application Behavior==&lt;br /&gt;
* [[Grading]]&lt;br /&gt;
&lt;br /&gt;
==Metaprogramming==&lt;br /&gt;
* [[CSC/ECE_517_Spring_2013/ch1b_1k_hf|Lecture on Metaprogramming]]&lt;br /&gt;
&lt;br /&gt;
==Development==&lt;br /&gt;
&lt;br /&gt;
''Expertiza now has a Java dependency, so the machine you are using to develop Expertiza on should have the JVM installed.''&lt;br /&gt;
&lt;br /&gt;
* [[Setting Up a Development Machine]]&lt;br /&gt;
* [[Creating a Linux Development Environment for Expertiza - Installation Guide]]&lt;br /&gt;
* [[Using git and github for projects]]&lt;br /&gt;
* [[Using heroku to deploy your projects]]&lt;br /&gt;
* [[How to Begin a Project from the Current Expertiza Repository]]&lt;br /&gt;
* [[Git]]&lt;br /&gt;
* [[How to Change a User's Password on a Development Machine]]&lt;br /&gt;
* [[Debugging Rails]]&lt;br /&gt;
* [http://rajanalwan.com/ui_guidelines/ Design Template]&lt;br /&gt;
&lt;br /&gt;
==Production==&lt;br /&gt;
* [[Deploying to Production]]&lt;br /&gt;
* [[Downloading Production Data]]&lt;br /&gt;
* [[Accessing the Production Server]]&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
* [[Using Cucumber with Expertiza]]&lt;br /&gt;
* [[Rails Testing Overview]]&lt;br /&gt;
* [[Expertiza Continuous Integration]]&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [[Object-Oriented Design and Programming]]&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116582</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116582"/>
		<updated>2018-04-14T01:09:09Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* HTML Canvas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId(u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
===Drawing Canvases with one CanvasPaintThread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
There will be slight changes to Constellation so that it doesn't try to create multiple CanvasPaintThreads, but those changes are minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps should be able to be completed similarly. The instructions are similarly clear, and the team understands how to work on Servo much more clearly, so the difficulty of initially getting set up will not need to be done again.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116581</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116581"/>
		<updated>2018-04-14T01:08:40Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* HTML Canvas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
[[File:DrawImage.PNG|thumb|An example of several canvases from servo's tests.]]&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId(u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
===Drawing Canvases with one CanvasPaintThread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
There will be slight changes to Constellation so that it doesn't try to create multiple CanvasPaintThreads, but those changes are minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps should be able to be completed similarly. The instructions are similarly clear, and the team understands how to work on Servo much more clearly, so the difficulty of initially getting set up will not need to be done again.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116580</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116580"/>
		<updated>2018-04-14T01:06:42Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId(u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:TimedDrawImage.png]]&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas.&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
===Drawing Canvases with one CanvasPaintThread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
There will be slight changes to Constellation so that it doesn't try to create multiple CanvasPaintThreads, but those changes are minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps should be able to be completed similarly. The instructions are similarly clear, and the team understands how to work on Servo much more clearly, so the difficulty of initially getting set up will not need to be done again.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:DrawImage.PNG&amp;diff=116579</id>
		<title>File:DrawImage.PNG</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:DrawImage.PNG&amp;diff=116579"/>
		<updated>2018-04-14T01:06:13Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: DrawImage for Canvases&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DrawImage for Canvases&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:TimedDrawImage.png&amp;diff=116577</id>
		<title>File:TimedDrawImage.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:TimedDrawImage.png&amp;diff=116577"/>
		<updated>2018-04-14T01:05:48Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: Timed DrawImage for Canvases&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Timed DrawImage for Canvases&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116569</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116569"/>
		<updated>2018-04-14T00:38:26Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Conclusion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId(u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas. &lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
===Drawing Canvases with one CanvasPaintThread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
There will be slight changes to Constellation so that it doesn't try to create multiple CanvasPaintThreads, but those changes are minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
The Subsequent Steps should be able to be completed similarly. The instructions are similarly clear, and the team understands how to work on Servo much more clearly, so the difficulty of initially getting set up will not need to be done again.&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116564</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116564"/>
		<updated>2018-04-14T00:32:10Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Drawing Canvases with one Thread */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId(u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas. &lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
===Drawing Canvases with one CanvasPaintThread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
There will be slight changes to Constellation so that it doesn't try to create multiple CanvasPaintThreads, but those changes are minor and well described in the spec.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116560</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116560"/>
		<updated>2018-04-14T00:29:16Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
==Servo==&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
==Rust==&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
==HTML Canvas==&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Project Description=&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
==Initial Steps:==&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId(u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps:==&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Design Pattern=&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas. &lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
===Drawing Canvases with one Thread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
=Conclusion=&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
=References=&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116559</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116559"/>
		<updated>2018-04-14T00:27:13Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: /* Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
===HTML Canvas===&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
===Initial Steps:===&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId(u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Subsequent Steps:===&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Implementation=&lt;br /&gt;
==General Information==&lt;br /&gt;
&lt;br /&gt;
Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This was/will be used to measure the performance when drawing a single canvas. &lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Steps==&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Subsequent Steps==&lt;br /&gt;
===Drawing Canvases with one Thread===&lt;br /&gt;
As it stands, a CanvasPaintThread is made for every Canvas, which is very slow when there are many Canvases. To fix this, a single CanvasPaintThread will be made that does all the work for all the canvases. The data currently stored in CanvasPaintThread unique to each Canvas will be moved to a new data structure known as CanvasData.&lt;br /&gt;
&lt;br /&gt;
Currently, communication channels are opened up between each CanvasPaintThread and what uses it and those channels send the CanvasIds established above alongside their messages. After completing the Subsequent Steps, these channels will instead connect the single CanvasPaintThread and those same users. The users will be unable to tell the difference between the current implementation and the new implementation. The CanvasPaintThread will redirect those existing channels into painting using the appropriate CanvasData structure.  &lt;br /&gt;
&lt;br /&gt;
The majority of changes will be entirely contained within components/canvas/canvas_paint_thread.rs. The changes to other files were largely done in the initial steps. The changes made to CanvasPaintThread should end up being invisible to its clients.&lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116467</id>
		<title>CSC/ECE 517 Spring 2018- Project M1802: 2D Canvas Rendering (Part 2)</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2018-_Project_M1802:_2D_Canvas_Rendering_(Part_2)&amp;diff=116467"/>
		<updated>2018-04-10T01:39:03Z</updated>

		<summary type="html">&lt;p&gt;Baeastwo: Created page with &amp;quot;'''“M1802: Simplify the 2d Canvas Rendering”'''  As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''“M1802: Simplify the 2d Canvas Rendering”'''&lt;br /&gt;
&lt;br /&gt;
As robust and fast Servo is, Servo’s implementation of its HTML 2D/3D  “&amp;lt;canvas&amp;gt;” has several inefficiencies that make some websites perform slowly or run out of memory when performing complex canvas operations. The goal of this project was to make these websites perform better when loaded in Servo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
This section briefly describes the main parts of this project: [https://en.wikipedia.org/wiki/Servo_(layout_engine) Servo], [https://www.rust-lang.org/en-US/ Rust], and [https://www.w3schools.com/graphics/canvas_intro.asp HTML Canvas].&lt;br /&gt;
&lt;br /&gt;
===Servo===&lt;br /&gt;
Named after a robot from the show Mystery Science Theater 3000, Servo is an experimental web browser layout engine developed by Mozilla. It is currently being developed for 64-bit OS X, 64-bit Linux, 64-bit Windows, and Android. While working with Samsung, Mozilla seeks to create a highly parallel environment where the many things in a web browser like rendering, image decoding, and HTML parsing are handled by isolated tasks. [https://www.youtube.com/watch?v=Ry_RktGLKq4 Here] is a demo on how Servo performs against Firefox.&lt;br /&gt;
&lt;br /&gt;
===Rust===&lt;br /&gt;
Since existing languages like C++ did not provide a direct way to achieve a parallel environment, Mozilla developed and uses a programming language called Rust to further develop Servo.&lt;br /&gt;
&lt;br /&gt;
===HTML Canvas===&lt;br /&gt;
A &amp;lt;canvas&amp;gt; in HTML is a container for graphics that is used to draw graphics “on the fly” by using Javascript. However, the &amp;lt;canvas&amp;gt; element has no drawing abilities of its own since it only acts as a container for graphics. A script to actually draw the graphics. By using scripts, the HTML &amp;lt;canvas&amp;gt; can:&lt;br /&gt;
*Be animated&lt;br /&gt;
*Be interactive&lt;br /&gt;
*Draw text&lt;br /&gt;
*Be used in games&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Project Description==&lt;br /&gt;
The goal of this project was to remove the inefficiencies of Servo’s implemetation of the 2D/3D canvas. As reported with issue [https://github.com/servo/servo/issues/10381 #10381], a gaming website called http://slither.io/ was performing extremely slowly as of Apr 3, 2016. As of Oct 21, 2016, it was reported with issue [https://github.com/servo/servo/issues/13879 #13879] that http://slither.io/ was, in fact, crashing when loaded onto Servo. The suggestion to these issues was to, first, create a test case that measured the amount of time that Servo spends under “drawImage” while doing operations related to a canvas. Another suggestion was to change Servo’s implementation from using one thread per canvas to one thread for all canvases. The [https://github.com/servo/servo/wiki/Canvas-rendering-project steps] laid out for this project by [https://www.mozilla.org/en-US/ Mozilla] (both the initial setup steps and optimizing the canvas implementation) are shown below.&lt;br /&gt;
&lt;br /&gt;
===Initial Steps:===&lt;br /&gt;
*create a testcase that contains two canvases and uses the drawImage API to draw the contents of one canvas onto the other. Programmatically measure the time this operation takes.&lt;br /&gt;
&lt;br /&gt;
*To prepare for the big switch from 1 threads per canvas to 1 thread for all canvases, add a struct CanvasId(u64) type to components/canvas_traits/canvas.rs and add a CanvasId member to each variant of the CanvasMsg enum.&lt;br /&gt;
&lt;br /&gt;
*add a CanvasId member to Constellation in components/constellation/constellation.rs which is initialized to 0 and increased by 1 each time handle_create_canvas_paint_thread is called.&lt;br /&gt;
&lt;br /&gt;
*make the response_sender argument of handle_create_canvas_paint_thread also include the new CanvasId value, and pass it as an argument to CanvasPaintThread::start. Store the id when it is received for use in all canvas messages.&lt;br /&gt;
&lt;br /&gt;
*For each CanvasMsg that is processed by CanvasPaintThread, verify that the id received matches the id that was provided to CanvasPaintThread::start&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Subsequent Steps:===&lt;br /&gt;
*extract the innards of CanvasPaintThread into a CanvasData structure,&lt;br /&gt;
&lt;br /&gt;
*make CanvasPaintThread store a hashtable of CanvasId-&amp;gt;CanvasData&lt;br /&gt;
&lt;br /&gt;
*as part of Constellation::start, create a canvas paint thread and store the channel to communicate with it as a member of Constellation. Remove the initial canvas id from the API of Constellation::start.&lt;br /&gt;
&lt;br /&gt;
*when handle_create_canvas_paint_thread is invoked, communicate with the canvas thread and have it create a new entry in the hashtable.&lt;br /&gt;
&lt;br /&gt;
*when the canvas thread receives a message, perform the operation on the appropriate canvas according to the provided id&lt;br /&gt;
&lt;br /&gt;
*optimize the DrawImageInOther operation by drawing on the destination canvas directly, rather than relying on sending a message to another canvas thread. Remove the now-unnecessary IpcSender from the DrawImageInOther enum variant. Verify that the earlier test case demonstrates a performance improvement.&lt;br /&gt;
&lt;br /&gt;
*report on how slither.io performs in Servo after all these changes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Design Pattern==&lt;br /&gt;
Design patterns were not applicable since our task was to add a few parts to code that already existed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
This section covers the implementation of the initial steps for this project.&lt;br /&gt;
&lt;br /&gt;
===Building===&lt;br /&gt;
After setting up the environment required to develop for Servo, we built and compiled Servo as per the instructions on Servo’s Github [https://github.com/servo/servo repo]. We used Mozilla’s mach tools to build Servo with Cargo, which is the rust package manager.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/servo/servo&lt;br /&gt;
cd servo&lt;br /&gt;
./mach build --dev&lt;br /&gt;
./mach run tests/html/about-mozilla.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
After successfully building servo, we proceeded to test the amount of time spent under “drawImage” as shown below. The function &amp;quot;drawImage&amp;quot; copies the contents of one canvas in a view to another canvas in the same view. During the &amp;quot;Initial Steps,&amp;quot; this test was created to test the initial performance of Servo with regards to canvas rendering.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var t0 = performance.now();&lt;br /&gt;
drawImage(25, 25);&lt;br /&gt;
var t1 = performance.now();&lt;br /&gt;
document.getElementById('Test Result').innerHTML = &amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;;&lt;br /&gt;
console.log(&amp;quot;DrawImage took &amp;quot; + (t1 - t0) + &amp;quot; milliseconds.&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Adding an Id to Canvas Communications===&lt;br /&gt;
As shown below, we then associated a CanvasId with each variant of a canvas message; these messages are passed around various parts of the Servo implementation such as the 2D canvas struct, view layout, and various scripts. This required us to make other changed to allow a CanvasId to be sent with each message, as shown below.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before&lt;br /&gt;
! After&lt;br /&gt;
|-&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg),&lt;br /&gt;
    FromLayout(FromLayoutMsg),&lt;br /&gt;
    FromScript(FromScriptMsg),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;),&lt;br /&gt;
    Close(),&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
| pub enum CanvasMsg {&lt;br /&gt;
    Canvas2d(Canvas2dMsg, CanvasId),&lt;br /&gt;
    FromLayout(FromLayoutMsg, CanvasId),&lt;br /&gt;
    FromScript(FromScriptMsg, CanvasId),&lt;br /&gt;
    Recreate(Size2D&amp;lt;i32&amp;gt;, CanvasId),&lt;br /&gt;
    Close(CanvasId),&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then, we made the necessary changed to the constellation and the canvas paint thread to be able to initialize, increment, and store the CanvasId. To finish up with the initial steps, we programmatically checked to make sure that each id that was processed by CanvasPaintThread was the same id that was provided when the thread was started (CanvasPaintThread::start).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
assert!(canvas_id == painter.canvas_id);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Running Servo===&lt;br /&gt;
After each successful build through our development process, we ran Servo as per the instructions on Servo’s Github repo.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./servo [url] [arguments] # if you run with nightly build&lt;br /&gt;
./mach run [url] [arguments] # if you run with mach&lt;br /&gt;
&lt;br /&gt;
# For example&lt;br /&gt;
./mach run https://www.google.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Performance===&lt;br /&gt;
Almost every time, http://slither.io/ ended up crashing. Other times, it performed very slowly. However, as of 4/2/2018, much more is left to be done (The Subsequent Steps). Our repo is [https://github.com/Brody-Eastwood/servo here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Conclusion==&lt;br /&gt;
So far we have associated each variant of a canvas message with a particular canvas id. Even though there is not much improvement is the performance of http://slither.io/, we believe that an improvement can be noticed after going through the Subsequent Steps. Here is a link to our [https://github.com/servo/servo/pull/20447 pull request]. On 4/2/2018, our contribution was merged into Servo's master branch!&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
#https://en.wikipedia.org/wiki/Servo_(layout_engine)&lt;br /&gt;
#https://www.rust-lang.org/en-US/&lt;br /&gt;
#https://github.com/servo/servo&lt;br /&gt;
#https://github.com/servo/servo/wiki/Canvas-rendering-project&lt;br /&gt;
#https://www.w3schools.com/graphics/canvas_intro.asp&lt;br /&gt;
#https://github.com/servo/servo/issues/10381&lt;br /&gt;
#https://github.com/servo/servo/issues/13879&lt;/div&gt;</summary>
		<author><name>Baeastwo</name></author>
	</entry>
</feed>