2010-12-15 4 views
8

Global.asax.cs에 빈 Session_Start 처리기를 만들면 브라우저에 페이지를 렌더링 할 때 상당한 영향을줍니다. Global.asax.cs의 Session_Start가 성능 문제를 일으키는 이유는 무엇입니까?

재현하는 방법 :

빈 ASP.NET MVC 3 웹 응용 프로그램을 (내가 MVC 3 RC2를 사용하고 있습니다)를 만듭니다. 다음이 코드를 홈 컨트롤러를 추가 :

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
    return View(); 
    } 
    public ActionResult Number(int id) 
    { 
    return Content(id.ToString()); 
    } 
} 

다음 뷰 홈/Index.cshtml를 만들고 본문 섹션에 다음과 같은 장소 :

@for (int n = 0; n < 20; n++) 
{ 
    <iframe src="@Url.Content("~/Home/Number/" + n)" width=100 height=100 /> 
} 

이 페이지를 실행하면 '를 페이지에 20 개의 IFRAME이 표시되며 각각 내부에 숫자가 표시됩니다. 여기서 내가하는 일은 장면 뒤에서 20 페이지 더 많은 페이지를로드하는 페이지를 만드는 것입니다. 계속하기 전에 20 페이지가 얼마나 빨리로드되는지 기록하십시오 (페이지를 몇 번 새로 고쳐로드를 반복하십시오).

다음이 Global.asax.cs로 이동 (예, 메소드 본문이 비어)이 방법을 추가

protected void Session_Start() 
{ 
} 

이제 페이지를 다시 실행합니다. 이번에는 20 개의 IFRAME이 약 1 초 간격으로 훨씬 느리게로드된다는 것을 알 수 있습니다. 이것은 Session_Start에서 실제로 아무것도하지 않기 때문에 이상합니다. 그것은 단지 비어있는 메소드입니다. 그러나 이것으로 모든 후속 페이지의 속도가 느려질 수 있습니다.

아무도 왜 이런 일이 벌어지고 있는지 알 수 있습니까? 더 나은 점은 누구나 수정/해결 방법이 있습니까? 내가 디버거가 연결되어있는 경우이 문제가 발생합니다 것을 발견했습니다

업데이트 (F5로 실행). 디버거가 연결되지 않은 상태에서 (Ctrl-F5) 실행하면 문제가없는 것 같습니다. 그래서, 아마도 중요한 문제는 아니지만 그것은 여전히 ​​이상합니다.

+0

SPA 응용 프로그램의 AJAX 요청에서이 문제가 발생했습니다. SessionState를 사용하지 말라고 조종했다. – voam

답변

10

TL; DR : 당신은 웹 양식과이 문제에 직면하고 @Page 지시에 EnableSessionState="ReadOnly"를 추가, 특정 페이지에서 세션 상태에 대한 쓰기 액세스를 필요로하지 않는 경우 도움이됩니다.


명백하게, Session_Start 혼자 힘 ASP.NET의 실존 동일한 세션 순차적 유래 모든 요청을 실행한다. 그러나 세션에 대한 쓰기 액세스가 필요하지 않은 경우 페이지 단위로 수정할 수 있습니다 (아래 참조).

이미지를 전송하기 위해 aspx 페이지를 사용하는 Webforms로 자체 테스트 설정을 만들었습니다.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GetImage.aspx.cs" Inherits="CsWebApplication1.GetImage" %> 

그리고 관련 부분 : 여기

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head><title></title></head> 
<body> 
    <div> 
     <img src="GetImage.aspx?text=A" /> 
     <img src="GetImage.aspx?text=B" /> 
     <img src="GetImage.aspx?text=C" /> 
     <img src="GetImage.aspx?text=D" /> 
     <img src="GetImage.aspx?text=E" /> 
     <img src="GetImage.aspx?text=F" /> 
     <img src="GetImage.aspx?text=G" /> 
     <img src="GetImage.aspx?text=H" /> 
     <img src="GetImage.aspx?text=I" /> 
     <img src="GetImage.aspx?text=J" /> 
     <img src="GetImage.aspx?text=K" /> 
     <img src="GetImage.aspx?text=L" /> 
    </div> 
</body> 
</html> 

는 영문 페이지 (GetImage.aspx)입니다 : 여기에 1

테스트 페이지 (일반 HTML, 프로젝트의 시작 페이지)의 숨김의 (GetImage.aspx.cs는 usingnamespace 스킵)

public partial class GetImage : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     Debug.WriteLine("Start: " + DateTime.Now.Millisecond); 
     Response.Clear(); 
     Response.ContentType = "image/jpeg"; 

     var image = GetDummyImage(Request.QueryString["text"]); 
     Response.OutputStream.Write(image, 0, image.Length); 
     Debug.WriteLine("End: " + DateTime.Now.Millisecond); 
    } 

    // Empty 50x50 JPG with text written in the center 
    private byte[] GetDummyImage(string text) 
    { 
     using (var bmp = new Bitmap(50, 50)) 
     using (var gr = Graphics.FromImage(bmp)) 
     { 
      gr.Clear(Color.White); 
      gr.DrawString(text, 
       new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular, GraphicsUnit.Point), 
       Brushes.Black, new RectangleF(0, 0, 50, 50), 
       new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }); 
      using (var stream = new MemoryStream()) 
      { 
       bmp.Save(stream, ImageFormat.Jpeg); 
       return stream.ToArray(); 
      } 
     } 
    } 
} 
빠른 페이지로드, 출력 창은 요청을 병렬로 처리받을 것을 의미 StartEnd s의 임의 혼합을 보여줍니다

테스트

  • 가 실행 한가 수정되지 않은 실행됩니다.

  • 실행이, 빈 Session_Startglobal.asax에 추가 (이 이유를 알 수없는, 브라우저에서 한 번 F5를 칠 필요) : StartEnd 대체를 요청이 sequentually 처리 얻을 것을 보여주는. 브라우저를 여러 번 새로 고치면 디버거가 연결되지 않은 경우에도 성능 문제가 있음을 알 수 있습니다. 실행 3

  • , 실행 2 만 GetImage.aspx@Page 지침에 EnableSessionState="ReadOnly"를 추가 같은 : 첫 번째 End 전에 디버그 출력이 여러 Start의를 보여줍니다. 우리는 다시 평행을 이루며 훌륭한 성과를 거두었습니다.


    1

예, 나는이 대신 ASHX 처리기으로 수행되어야한다는 것을 알고있다. 그것은 단지 예일뿐입니다.

+0

흥미 롭습니다 ... 디버거 외부에서 이러한 테스트를 실행할 때 (즉, F5가 아닌 Ctrl-F5로 실행) – Mike

+0

@Mike : 수행했습니다. 실행 2는 디버거가없는 경우에도 다른 것보다 느립니다 (차이점은 디버거만큼 강력하지 않지만 여전히 눈에.니다). – Heinzi

3

디버거가 무엇을하고 있는지 (intellitrace? 세부 로깅? 첫 번째 예외입니까?) 말할 수는 없지만 동시 요청을 처리 할 수있는 능력은 여전히 ​​세션에 있습니다.

ASP.NET 세션 상태에 대한 액세스는 세션마다 독점적입니다. 즉, 두 명의 서로 다른 사용자가 동시 요청을하면 각 개별 세션에 대한 액세스가 동시에 부여됩니다. 그러나 동일한 세션 ID 값을 사용하여 동일한 세션에 대해 두 개의 동시 요청이 이루어지면 첫 번째 요청은 세션 정보에 독점적으로 액세스합니다. 두 번째 요청은 첫 번째 요청이 완료된 후에 만 ​​실행됩니다. (첫 번째 요청이 잠금 시간 초과를 초과하여 정보의 독점 잠금이 해제 된 경우 두 번째 세션도 액세스 할 수 있습니다.) @ Page 지시문의 EnableSessionState 값이 ReadOnly로 설정된 경우 읽기 전용 요청 세션 정보 만이 세션 데이터에 독점적 인 잠금을 초래하지 않습니다. 그러나 세션 데이터에 대한 읽기 전용 요청은 세션 데이터가 지워지도록 읽기 - 쓰기 요청에 의해 설정된 잠금을 기다려야 할 수도 있습니다.

출처 : ASP.NET Session State Overview, 내 강조

+0

이것은 흥미로운 사실이지만 위에서 설명한 동작을 설명하지는 않습니다. Case # 1과 Case # 2의 유일한 차이점은 Global.asax.cs에 빈 Session_Start 메소드가 있다는 것입니다. 참조에 따르면 두 경우 모두 여전히 동일하게 동작해야합니다. – Mike

+0

분명히 Global.asax.cs에있는 비어있는'Session_Start' 메쏘드가 ASP.NET 직렬화 요청을하기에 충분합니다. 나는 Webforms와 비슷한 문제를 겪었고, 병렬 페이지 (나의 경우에는 이미지)를 제공하는 aspx 페이지의'@ Page' 지시어에서'EnableSessionState = "ReadOnly"를 설정함으로써 해결할 수 있음을 발견했다. 비슷한 옵션이 MVC에 존재하는지 모르겠습니다. – Heinzi

+0

@Heinzi 매우 흥미 롭습니다! 이 문제를 보여주는 문서/증거가 있습니까? 그렇다면 새 답안을 만들어 주시면 승인으로 표시하겠습니다. – Mike

관련 문제