case study: how hotmail used "atlas" and asp.net to build a great user experience walter...
TRANSCRIPT
Case Study: How Hotmail Used "Atlas" and Case Study: How Hotmail Used "Atlas" and ASP.NET to Build a Great User Experience ASP.NET to Build a Great User Experience
Walter HsuehWalter HsuehPRSL02 PRSL02 Development LeadDevelopment LeadMicrosoft CorporationMicrosoft Corporation
2
Building The Microsoft Building The Microsoft Mail Beta In ASP.NET And Mail Beta In ASP.NET And "Atlas""Atlas"Web Mail LandscapeWeb Mail Landscape
Design Goals for Web Mail BetaDesign Goals for Web Mail Beta
Server and ClientServer and ClientProblem spaceProblem space
Issues that we faced and how we resolved.Issues that we faced and how we resolved.
"Atlas" Programming Model"Atlas" Programming ModelWhat is "Atlas" and why did we need it?What is "Atlas" and why did we need it?
How we converged on "Atlas"How we converged on "Atlas"
Tips and TricksTips and Tricks
3
The Internet Mail The Internet Mail LandscapeLandscapeCompetitive CharacteristicsCompetitive Characteristics
Cheap storageCheap storage
Large Inboxes, Large attachmentsLarge Inboxes, Large attachments
Unified Inbox, Unified StorageUnified Inbox, Unified Storage
Rich DHTML browser applicationsRich DHTML browser applications
4
Microsoft Web Mail BetaMicrosoft Web Mail Beta
Walter HsuehWalter HsuehDevelopment LeadDevelopment LeadHotmail FrontdoorHotmail Frontdoor
5
Web Mail Client Web Mail Client ArchitectureArchitectureBrowser Client GoalsBrowser Client Goals
Optimize the Perceived PerformanceOptimize the Perceived PerformanceThe user experience must seem fastThe user experience must seem fast
Non-postback design using XMLHTTPNon-postback design using XMLHTTPMinimize the wire (protocol) costMinimize the wire (protocol) cost
Pure data? HTML? XML?Pure data? HTML? XML?
Utilize the client capabilitiesUtilize the client capabilitiesCPU capacity and memory (move RegEx to client)CPU capacity and memory (move RegEx to client)The browser DOM as stateThe browser DOM as state
Leverage CSSLeverage CSSPositioning/layoutPositioning/layoutThemeing/typology Themeing/typology
6
Web Mail Client Web Mail Client ArchitectureArchitectureBuilt upon "Atlas", Part IBuilt upon "Atlas", Part I
MSN organizational driveMSN organizational driveDevelop a viable client development platform, or Develop a viable client development platform, or "JavaScript runtime""JavaScript runtime"Used across MSN properties (Hotmail, MSN.com Spaces, Used across MSN properties (Hotmail, MSN.com Spaces, Start.com)Start.com)
Strategic company alignmentStrategic company alignmentCombine company-wide JavaScript design patterns, Combine company-wide JavaScript design patterns, components, and frameworks into "Atlas"components, and frameworks into "Atlas"
Core set of system classes and objects in Core set of system classes and objects in JavaScript: JavaScript:
Namespaces, Eventing Model, Component ModelNamespaces, Eventing Model, Component ModelInheritance and interfaces, EnumerationsInheritance and interfaces, EnumerationsXMLHTTP stackXMLHTTP stack
7
Web Mail Client Web Mail Client ArchitectureArchitectureBuilt upon "Atlas", Part IIBuilt upon "Atlas", Part II
"Atlas" Bindings"Atlas" BindingsJavaScript object that encapsulates functionality that can be JavaScript object that encapsulates functionality that can be attached to DOM elements declaratively or programmaticallyattached to DOM elements declaratively or programmatically
Interface to browser eventsInterface to browser events
Unify client event model: use "Atlas" Bindings to capture and Unify client event model: use "Atlas" Bindings to capture and drive all UX inputdrive all UX input
Command BindingsCommand Bindings
<div class='Command' FireAnt:commandname='Reply'><img <div class='Command' FireAnt:commandname='Reply'><img src="images/i_reply.gif"><% src="images/i_reply.gif"><% Response.Write(StaticContentHelper.GetString("ReadMessage.Reply")); Response.Write(StaticContentHelper.GetString("ReadMessage.Reply")); %></div>%></div><div class='Command' FireAnt:commandname='ReadMessage' <div class='Command' FireAnt:commandname='ReadMessage' FireAnt:keycode='13' FireAnt:layout='InboxDefault' FireAnt:keycode='13' FireAnt:layout='InboxDefault' style='display:none'></div>style='display:none'></div>
<web:binding selector=".Command" type="FireAnt.Command" <web:binding selector=".Command" type="FireAnt.Command" namespace="FireAnt"></web:binding>namespace="FireAnt"></web:binding>
8
Web Mail Client Web Mail Client ArchitectureArchitectureBuilt upon "Atlas", Part IIIBuilt upon "Atlas", Part IIICommand Binding code-behindCommand Binding code-behindFireAnt.Command = function(boundElem, rgParams)FireAnt.Command = function(boundElem, rgParams){{ //boilerplate binding setup//boilerplate binding setup FireAnt.Command.inherit(this);FireAnt.Command.inherit(this); var m_obj = this, m_sCommandName = null, m_sKeyCode = null, m_sLayout = null, var m_obj = this, m_sCommandName = null, m_sKeyCode = null, m_sLayout = null, m_bCtrlKey = null;m_bCtrlKey = null; //public//public this.Init = function()this.Init = function() {{ //get the name of the command//get the name of the command m_sCommandName = rgParams.commandname.toString();m_sCommandName = rgParams.commandname.toString();
//connect a click handler//connect a click handler switch(boundElem.tagName)switch(boundElem.tagName) {{ case "SELECT":case "SELECT": boundElem.attachEvent("onchange", onchange);boundElem.attachEvent("onchange", onchange); boundElem.attachEvent("onmousewheel", onmousewheel);boundElem.attachEvent("onmousewheel", onmousewheel); break;break; default:default: boundElem.attachEvent("onclick", onclick);boundElem.attachEvent("onclick", onclick); break;break; }}......
9
Web Mail Client Web Mail Client ArchitectureArchitectureBuilt upon "Atlas", Part IVBuilt upon "Atlas", Part IVAutoComplete Binding:AutoComplete Binding:
<div unselectable="on" class="AutoCompleteList" FireAnt:id="<%=this.listId<div unselectable="on" class="AutoCompleteList" FireAnt:id="<%=this.listId%>" FireAnt:size="<%=this.listSize%>" style="position:absolute; overflow-%>" FireAnt:size="<%=this.listSize%>" style="position:absolute; overflow-x:hidden; overflow-y:scroll; display:none;">x:hidden; overflow-y:scroll; display:none;">
<web:binding selector=".AutoCompleteList" type="FireAnt.AutoCompleteList" <web:binding selector=".AutoCompleteList" type="FireAnt.AutoCompleteList" namespace="FireAnt"></web:binding>namespace="FireAnt"></web:binding>
Folder List Binding:Folder List Binding:<div id="ctlFolderList" class="FolderList Menu" tabindex="0" <div id="ctlFolderList" class="FolderList Menu" tabindex="0" FireAnt:paging=falseFireAnt:paging=falseFireAnt:multiselect=false FireAnt:itemtype="FolderItem“ FireAnt:multiselect=false FireAnt:itemtype="FolderItem“ FireAnt:menuname="Folders“ FireAnt:menuname="Folders“ FireAnt:menucommands="{key:'rename',cmd:'RenameFolder',icon:'i_rename.gif'FireAnt:menucommands="{key:'rename',cmd:'RenameFolder',icon:'i_rename.gif',label:‘Rename Folder'}, ,label:‘Rename Folder'}, {key:'delete',cmd:'DeleteFolder',icon:'i_folder_delete.gif',label:‘Delete {key:'delete',cmd:'DeleteFolder',icon:'i_folder_delete.gif',label:‘Delete Folder'}"></div>Folder'}"></div>
<web:binding selector=".FolderList" type="FireAnt.FolderList" <web:binding selector=".FolderList" type="FireAnt.FolderList" namespace="FireAnt"></web:binding>namespace="FireAnt"></web:binding>
10
Web Mail Client Web Mail Client ArchitectureArchitectureBuilt upon "Atlas", Part VBuilt upon "Atlas", Part V
What did "Atlas" solve for Web Mail Beta?What did "Atlas" solve for Web Mail Beta?"Atlas" Script Core"Atlas" Script Core
JavaScript extensions and common shared frameworkJavaScript extensions and common shared framework
Target single browser platform (compatibility layer)Target single browser platform (compatibility layer)
Web Mail's JavaScript classes, eventing model, and Web Mail's JavaScript classes, eventing model, and communications core directly leverage "Atlas"communications core directly leverage "Atlas"
"Atlas" Bindings"Atlas" BindingsConsistent, declarative design patternConsistent, declarative design pattern
Component design and reuseComponent design and reuse
No use of loose html attributes for eventsNo use of loose html attributes for events
Clean separation of UI and JavaScript codeClean separation of UI and JavaScript code
Cross-browser implementation of a DHTML behaviorCross-browser implementation of a DHTML behavior
Automation interface for testabilityAutomation interface for testability
11
Web Mail UX AutomationWeb Mail UX Automation
Walter HsuehWalter HsuehDevelopment LeadDevelopment LeadHotmail FrontdoorHotmail Frontdoor
12
Web Mail Client Web Mail Client ArchitectureArchitectureXMLHTTP RequirementsXMLHTTP Requirements
"FireAnt Proxy-Protocol" (FPP) design"FireAnt Proxy-Protocol" (FPP) designNon-postback design requires a browser client to invoke Non-postback design requires a browser client to invoke server functionality by XMLHTTPserver functionality by XMLHTTPAn auto-generated and easily maintainable set of client An auto-generated and easily maintainable set of client proxiesproxies representing server methods and server objects representing server methods and server objectsA A protocolprotocol that minimizes the over-the-wire cost that minimizes the over-the-wire cost
FPP Server PlatformFPP Server PlatformFramework for exposing C# methods and objects that Framework for exposing C# methods and objects that they can be called from JavaScriptthey can be called from JavaScriptSynchronous / Asynchronous C# methods are supported.Synchronous / Asynchronous C# methods are supported.
FPP Client PlatformFPP Client PlatformJavaScript components built upon "Atlas" Script CoreJavaScript components built upon "Atlas" Script CoreOOP supportOOP supportXMLHTTP supportXMLHTTP support
13
Web Mail Client Web Mail Client Architecture Architecture XMLHTTP Platform DesignXMLHTTP Platform DesignJavaScript JavaScript
Browser Browser ApplicationApplication
Atlas Script CoreAtlas Script Core
C# ApplicatonC# Applicaton
FPP PackagerFPP Packager
FPP JavaScript generatorFPP JavaScript generator
FPP DemarshallerFPP Demarshaller
FPP Parameter ParserFPP Parameter Parser
FPP Stub DispatcherFPP Stub Dispatcher
JavaScript eval()JavaScript eval()JavaScript stubsJavaScript stubs
14
Web Mail Client Web Mail Client Architecture Architecture XMLHTTP Implementation IXMLHTTP Implementation I
C# objects and methods are tagged as FPP C# objects and methods are tagged as FPP exportableexportable
Proxies are generatedProxies are generatedJavaScript objects and upstream serializationJavaScript objects and upstream serialization
Server demarshalling from JavaScriptServer demarshalling from JavaScript
Server marshalling into JavaScriptServer marshalling into JavaScript
JavaScript eval() operates as client JavaScript eval() operates as client demarshallerdemarshaller
System.Enum (C#) -> Web.Flags (JS)System.Enum (C#) -> Web.Flags (JS)
System.Object supportedSystem.Object supported
IDictionary -> JavaScript associative arrayIDictionary -> JavaScript associative array
15
Web Mail Client Web Mail Client Architecture Architecture XMLHTTP Implementation IIXMLHTTP Implementation II
C# method: GetFolderDataC# method: GetFolderData
[FppMethodBegin("GetFolderData", FppHttpVerbType.GET, 0)][FppMethodBegin("GetFolderData", FppHttpVerbType.GET, 0)]public IAsyncResult BeginGetFolderData(public IAsyncResult BeginGetFolderData( Guid folderId,Guid folderId, SortBy sortBy,SortBy sortBy, uint count,uint count, bool ascendingOrder,bool ascendingOrder, ListNavigateDirection direction,ListNavigateDirection direction, uint pageSize,uint pageSize, int totalMessages,int totalMessages, Guid anchorMessageID,Guid anchorMessageID, Guid selectedMessageID,Guid selectedMessageID, AsyncCallback asyncCallback,AsyncCallback asyncCallback, Object asyncStateObject asyncState ))
[FppMethodEnd("GetFolderData")][FppMethodEnd("GetFolderData")]public BootstrapData EndGetFolderData(IAsyncResult ar)public BootstrapData EndGetFolderData(IAsyncResult ar)
16
Web Mail Client Web Mail Client Architecture Architecture XMLHTTP Implementation IIIXMLHTTP Implementation III
JavaScript Proxy:JavaScript Proxy:
registerNamespace("HM");registerNamespace("HM");HM = new Web.Network.FppProxy();HM = new Web.Network.FppProxy();......HM.ListNavigateDirection = HM.ListNavigateDirection = Web.Flags.create("FirstPage",0,"LastPage",1,"NextPage",2,"PreviousPage",3,Web.Flags.create("FirstPage",0,"LastPage",1,"NextPage",2,"PreviousPage",3,"CurrentPage",4);"CurrentPage",4);HM.FolderType = Web.Flags.create("SYSTEM",0,"USER_DEFINED",1,"OIM",2);HM.FolderType = Web.Flags.create("SYSTEM",0,"USER_DEFINED",1,"OIM",2);......HM.registerFppClass("microsoft_msn_hotmail_bootstrapdata",HM.registerFppClass("microsoft_msn_hotmail_bootstrapdata",[Web.Network.FppProxy.__array("Folders"),Web.Network.FppProxy.__string("Me[Web.Network.FppProxy.__array("Folders"),Web.Network.FppProxy.__string("Meter"),Web.Network.FppProxy.__custom(HM.microsoft_msn_hotmail_hotmailaddrester"),Web.Network.FppProxy.__custom(HM.microsoft_msn_hotmail_hotmailaddressbookcontactsandgroups, sbookcontactsandgroups, "Contacts"),Web.Network.FppProxy.__array("Headers"),Web.Network.FppProxy._"Contacts"),Web.Network.FppProxy.__array("Headers"),Web.Network.FppProxy.__string("MessageHtml"),Web.Network.FppProxy.__string("FirstMessageId"),Web_string("MessageHtml"),Web.Network.FppProxy.__string("FirstMessageId"),Web.Network.FppProxy.__custom(HM.microsoft_msn_hotmail_bootstrapconfiguration.Network.FppProxy.__custom(HM.microsoft_msn_hotmail_bootstrapconfiguration, , "Configuration"),Web.Network.FppProxy.__primitive("SelectedMessageIndex")]"Configuration"),Web.Network.FppProxy.__primitive("SelectedMessageIndex")]););......
17
Web Mail Client Web Mail Client Architecture Architecture XMLHTTP Implementation IVXMLHTTP Implementation IV
Server demarshalling (inbound) stub:Server demarshalling (inbound) stub:public static IAsyncResult public static IAsyncResult Begin_Microsoft_Msn_Hotmail_MailBox_GetFolderData(Microsoft.Msn.Hotmail.MailBox Begin_Microsoft_Msn_Hotmail_MailBox_GetFolderData(Microsoft.Msn.Hotmail.MailBox @__fppMailBoxService, string folderId, string sortBy, string count, string @__fppMailBoxService, string folderId, string sortBy, string count, string ascendingOrder, string direction, string pageSize, string totalMessages, string ascendingOrder, string direction, string pageSize, string totalMessages, string anchorMessageID, string selectedMessageID, System.AsyncCallback asyncCallback, object anchorMessageID, string selectedMessageID, System.AsyncCallback asyncCallback, object asyncState)asyncState){{ // unmarshall parameters// unmarshall parameters System.Guid @__folderId = FireAntParamParser.ParseGuid(folderId);System.Guid @__folderId = FireAntParamParser.ParseGuid(folderId); Microsoft.Msn.Hotmail.SortBy @__sortBy = (Microsoft.Msn.Hotmail.SortBy) Microsoft.Msn.Hotmail.SortBy @__sortBy = (Microsoft.Msn.Hotmail.SortBy) Enum.Parse(typeof(Microsoft.Msn.Hotmail.SortBy), sortBy);Enum.Parse(typeof(Microsoft.Msn.Hotmail.SortBy), sortBy); uint @__count = (System.UInt32) uint @__count = (System.UInt32) Convert.ChangeType(FireAntParamParser.UnEscapeText(count), typeof(System.UInt32));Convert.ChangeType(FireAntParamParser.UnEscapeText(count), typeof(System.UInt32)); bool @__ascendingOrder = (System.Boolean) bool @__ascendingOrder = (System.Boolean) Convert.ChangeType(FireAntParamParser.UnEscapeText(ascendingOrder), Convert.ChangeType(FireAntParamParser.UnEscapeText(ascendingOrder), typeof(System.Boolean));typeof(System.Boolean));
......
// invoke __fppMailBoxService.BeginGetFolderData// invoke __fppMailBoxService.BeginGetFolderData return __fppMailBoxService.BeginGetFolderData(__folderId, __sortBy, __count, return __fppMailBoxService.BeginGetFolderData(__folderId, __sortBy, __count, __ascendingOrder, __direction, __pageSize, __totalMessages, __anchorMessageID, __ascendingOrder, __direction, __pageSize, __totalMessages, __anchorMessageID, __selectedMessageID, asyncCallback, asyncState);__selectedMessageID, asyncCallback, asyncState);}}
18
Web Mail Client Web Mail Client Architecture Architecture XMLHTTP Implementation VXMLHTTP Implementation VServer outbound stub:Server outbound stub:public static Microsoft.Msn.Hotmail.BootstrapData public static Microsoft.Msn.Hotmail.BootstrapData End_Microsoft_Msn_Hotmail_MailBox_GetFolderData(Microsoft.Msn.Hotmail.MailBox End_Microsoft_Msn_Hotmail_MailBox_GetFolderData(Microsoft.Msn.Hotmail.MailBox @__fppMailBoxService, out object[] outRefParams, System.IAsyncResult ar)@__fppMailBoxService, out object[] outRefParams, System.IAsyncResult ar){{ // invoke __fppMailBoxService.EndGetFolderData// invoke __fppMailBoxService.EndGetFolderData Microsoft.Msn.Hotmail.BootstrapData returnObject = Microsoft.Msn.Hotmail.BootstrapData returnObject = @__fppMailBoxService.EndGetFolderData(ar);@__fppMailBoxService.EndGetFolderData(ar); // create out/ref param holder object[]// create out/ref param holder object[] outRefParams = new object[0];outRefParams = new object[0]; return returnObject;return returnObject;}}
Server outbound ToJavaScript():Server outbound ToJavaScript():case "Microsoft.Msn.Hotmail.MailBox.GetFolderData":case "Microsoft.Msn.Hotmail.MailBox.GetFolderData":{{ stubReturn = stubReturn = _Stubs.End_Microsoft_Msn_Hotmail_MailBox_GetFolderData(microsoft_msn_hotmail_mailbox, _Stubs.End_Microsoft_Msn_Hotmail_MailBox_GetFolderData(microsoft_msn_hotmail_mailbox, out outRefParams, ar);out outRefParams, ar); break;break;}}......fppReturnValue = FppReturnPackage.ToJavaScript(fppStatus, stubReturn, outRefParams, fppReturnValue = FppReturnPackage.ToJavaScript(fppStatus, stubReturn, outRefParams, fppEx, string.Empty, fppProfile, _FireAntConvert.Converter);fppEx, string.Empty, fppProfile, _FireAntConvert.Converter);return fppReturnValue;return fppReturnValue;
19
Hotmail Server LoadHotmail Server LoadPerformance/Scalability Performance/Scalability RequirementsRequirements
Mail StatisticsMail Statistics~200M active users~200M active users
On a typical day...On a typical day...3.3B email messages3.3B email messages
1.5B spam messages blocked at router1.5B spam messages blocked at router1.0B deleted messages (detected as spam)1.0B deleted messages (detected as spam)0.5B sent to Junk Mail Folder0.5B sent to Junk Mail Folder
>100M sent messages/day>100M sent messages/day80M-100M logins/day80M-100M logins/day5000 peak logins/sec5000 peak logins/sec
20
Web Mail Server Web Mail Server Architecture Architecture Data requirementsData requirements
Average byte size of messages increasingAverage byte size of messages increasingIO (e.g., TCP, HTTP, disk) is limiting factorIO (e.g., TCP, HTTP, disk) is limiting factorDo not want to block threads waiting for Do not want to block threads waiting for long-running operations long-running operations
Thread exhaustionThread exhaustionInefficient CPU utilizationInefficient CPU utilization
MIME is a very inefficient storage formatMIME is a very inefficient storage format> 1.33x size increase due to encoding, MIME part > 1.33x size increase due to encoding, MIME part duplication.duplication.
Original MIME text must be preservedOriginal MIME text must be preservedStreamed and asynchronous approaches to Streamed and asynchronous approaches to manipulating large MIME buffersmanipulating large MIME buffers
21
Web Mail Server Web Mail Server Architecture Architecture Asynchronous Design, Part IAsynchronous Design, Part I
Fully asynchronous programming model Fully asynchronous programming model Increased data and IO access patternsIncreased data and IO access patternsSynchronous design limitations in existing HotmailSynchronous design limitations in existing Hotmail
Fixed-Size ASP.NET ThreadpoolFixed-Size ASP.NET ThreadpoolConsidered dedicated IO threadpool but not necessary for Considered dedicated IO threadpool but not necessary for performance objectivesperformance objectives
Async design avoids blocking on threads Async design avoids blocking on threads High throughput and thread utilizationHigh throughput and thread utilization
Async design drives good design patternsAsync design drives good design patternsLimits the use of global variablesLimits the use of global variablesPassing state ("context") from callback to callbackPassing state ("context") from callback to callbackexecution components and callbacksexecution components and callbacks
22
Web Mail Server Web Mail Server Architecture Architecture Asynchronous Design, Part IIAsynchronous Design, Part II
Significantly more difficult programming model Significantly more difficult programming model than synchronous designthan synchronous designDifficult to infer the call sequenceDifficult to infer the call sequence
Partial callstacks in async componentsPartial callstacks in async componentsRequires a callgraph structure to follow sequence Requires a callgraph structure to follow sequence of callback componentsof callback components
Harder to debug and profileHarder to debug and profileEntry and exit points split across functionsEntry and exit points split across functions
Deadlock and race conditions on thread attach Deadlock and race conditions on thread attach and detachand detachReconstruction of global variables (e.g., Reconstruction of global variables (e.g., HttpContext.Current) on thread entry/exitHttpContext.Current) on thread entry/exit
23
Web Mail Beta StatusWeb Mail Beta Status
Internally used within MicrosoftInternally used within Microsoft
Beta rollout underway, ramp up to Beta rollout underway, ramp up to scalescale
Sign up at the end of this session Sign up at the end of this session with your @hotmail.com account if with your @hotmail.com account if you would like to be part of the beta you would like to be part of the beta program.program.
Questions? [email protected]? [email protected]
24
Community ResourcesCommunity Resources
At PDCAt PDC[PRS312] ASP.NET: Future Directions for [PRS312] ASP.NET: Future Directions for Developing Rich Web Applications with Atlas Developing Rich Web Applications with Atlas (Part 1)(Part 1)
Wednesday 9/14 at 5:00pmWednesday 9/14 at 5:00pm
[PRS220]: ASP.NET: Future Directions for [PRS220]: ASP.NET: Future Directions for Developing Rich Web Applications with Atlas Developing Rich Web Applications with Atlas (Part 2)(Part 2)
Thursday 9/15 at 11:30amThursday 9/15 at 11:30am
[PRSL04] MSN: Extending Start.com Using [PRSL04] MSN: Extending Start.com Using WidgetsWidgets
Thursday 9/15 at 1:00pmThursday 9/15 at 1:00pm
Ask The Experts table: Thursday 9/15, 6:30pm-Ask The Experts table: Thursday 9/15, 6:30pm-9:00pm9:00pmPRS Track lounge: Wednesday 9/14 2:30-5pmPRS Track lounge: Wednesday 9/14 2:30-5pm
After PDCAfter PDCIf you missed this related session, watch it on If you missed this related session, watch it on the DVDthe DVD