02.Oracle/DataBase2014. 7. 23. 15:08
반응형

내가 지식이 얕은 건지, 어떻게든 돌아가게는 만든다는 주먹구구식 마인드 때문인지,
Oracle DB에 입력되어 있는 순차적인 데이터의 선택적 추출은
이 방법밖에 알지 못한다..

자, 이제 그 방법에 대해 알아보자.

먼저 MySQL 에서는 
# [MySQL]
SELECT a.love_id 
FROM love a
LIMIT 1000, 2000;


하면, 실제 입력된 데이터의 순서에 맞추어 1000번 부터 2000번까지의 데이터가 나온다.

하지만.... 망할 ORACLE 에는 없다는 거....

어떤 분들은 'rownum으로  WHERE rownum BETWEEN 1000 AND 2000 하면 되지 않느냐??'
라고 하는데..... 잘 찾아보면, rownum 은 결과 값에 매겨지는 상대적인 값이므로,
절대적인 신뢰감이 없고, 위의 수식도 먹지 않는다..... 
뭐.. 안 믿으시면 한 번 해보시라.. --;;

그럼.. 어떻게 해야할까?
우리의 친구 꼼수를 한 번 발동 시켜볼까?

* 해법 *
************************************************************************************************
# [Oracle]
1. 아래 쿼리는, 데이터가 실제적으로 들어간 순서에 맞게 rownum을 부여 하여,
그 값을 하나의 컬럼으로 출력될 수 있게 해준다.
SELECT a.rownum as rnum, a.love_id
FROM love a;

2. 1에서 만들어진 쿼리를 아래와 같이 서브쿼리화 하여, between 사용이 가능해진다.
SELECT b.love_id
FROM (SELECT a.rownum as rnum, a.love_id FROM love a) as b
WHERE b.rnum BETWEEN 1000 AND 2000;

************************************************************************************************

자, 그럼,, 저 위의 방식을 이용하여 마음껏(???) limit 인 척 해보자.


출처 : http://blackbull.tistory.com/25

Posted by 1010
02.Oracle/DataBase2014. 7. 23. 15:06
반응형

DBMS별 지원되는 최대 컬럼수(Oracle,ms-sql,mysql,db2)


지원되는 최대 컬럼수

사용된 DBMS
Oracle: Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
DB2   : DB2/NT 7.2.1
MySQL : 4.0.7-gamma-nt
MS-SQL: Microsoft SQL Server  2000 - 8.00.760 (Intel X86) 
            Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 3)

사용된 질의
create table long_test
(
id1     varchar(10),
id2     varchar(10),
id3     varchar(10),
id4     varchar(10),
id5     varchar(10),
id6     varchar(10),
id7     varchar(10),
id8     varchar(10),
id9     varchar(10),
id10    varchar(10),
id11    varchar(10),
id12    varchar(10),
.
.
.



오라클과 ms-sql의 경우, 최대 1000, 1024개의 컬럼을 지원한다고 명시되어 있다.
MySQL의 경우, 명시적인 언급을 찾을 수 없어서 실험을 통해 얻은 값이다.
DB2의 경우는 table space의 페이지크기와 컬럼의 데이터타입에 따라 가변적이다.

오라클 : 1000
MySQL  : 3230
MS-SQL : 1024
DB2    : 가변적. 최대 컬럼수를 구하는 공식은 다음과 같다.
         4K page size allows a maximum of 500 columns 
         8K, 16K, and 32K page sizes allow a maximum of 1012 columns. 
         The actual number of columns for a table is determined by the following formula: 
         Total Columns * 8 + Number of LOB Columns * 12 + Number of Datalink Columns * 28 <= row size limits for page size. 

This article comes from dbakorea.pe.kr (Leave this line as is) 

출처 : https://www.linux.co.kr/home2/board/subbs/board.php?bo_table=lecture&wr_id=233&sca=3&page=9


Posted by 1010
반응형

if (ex instanceof DataAccessException) {

       SQLException se = (SQLException) ((DataAccessException) ex).getRootCause();

       msg = se.getMessage();

       LOGGER.debug("****** DataAccessException : {} // {}", se.getErrorCode(), se.getMessage());

}


if (ex instanceof BadSqlGrammarException) {

       SQLException se = ((BadSqlGrammarException) ex).getSQLException();

       LOGGER.debug("**BadSqlGrammarException {} ", se.getErrorCode());

}

else if (ex instanceof InvalidResultSetAccessException) {

       SQLException se = ((InvalidResultSetAccessException) ex).getSQLException();

       LOGGER.debug("**InvalidResultSetAccessException {} ", se.getErrorCode());

}

else if (ex instanceof DuplicateKeyException) {

       LOGGER.debug("**DuplicateKeyException {} ", ex.getMessage());

}

else if (ex instanceof DataIntegrityViolationException) {

       LOGGER.debug("**DataIntegrityViolationException {} ", ex.getMessage());

}

else if (ex instanceof DataAccessResourceFailureException) {

       LOGGER.debug("**DataAccessResourceFailureException {} ", ex.getMessage());

}

else if (ex instanceof CannotAcquireLockException) {

       LOGGER.debug("**CannotAcquireLockException {} ", ex.getMessage());

}

else if (ex instanceof DeadlockLoserDataAccessException) {

       LOGGER.debug("**DeadlockLoserDataAccessException {} ", ex.getMessage());

}

else if (ex instanceof CannotSerializeTransactionException) {

       LOGGER.debug("**CannotSerializeTransactionException {} ", ex.getMessage());

}

org.springframework.jdbc.support.SQLErrorcodesSQLExceptionTranslator Class


Posted by 1010
반응형

Index of /asdoc/mx/charts

 Name                    Last modified      Size  Description
Parent Directory - AreaChart.html 2014-05-03 13:10 304K AxisLabel.html 2014-05-03 13:10 13K AxisRenderer.html 2014-05-03 13:10 296K BarChart.html 2014-05-03 13:10 307K BubbleChart.html 2014-05-03 13:10 305K CandlestickChart.html 2014-05-03 13:10 304K CategoryAxis.html 2014-05-03 13:10 60K ChartItem.html 2014-05-03 13:10 28K ColumnChart.html 2014-05-03 13:10 313K DateTimeAxis.html 2014-05-03 13:10 101K GridLines.html 2014-05-03 13:10 252K HLOCChart.html 2014-05-03 13:10 303K HitData.html 2014-05-03 13:10 24K Legend.html 2014-05-03 13:21 418K LegendItem.html 2014-05-03 13:21 251K LineChart.html 2014-05-03 13:21 302K LinearAxis.html 2014-05-03 13:21 54K LogAxis.html 2014-05-03 13:21 51K PieChart.html 2014-05-03 13:21 294K PlotChart.html 2014-05-03 13:21 301K chartClasses/ 2014-05-03 13:35 - class-list.html 2014-05-03 13:10 2.0K effects/ 2014-05-03 13:35 - events/ 2014-05-03 13:35 - package-detail.html 2014-05-03 13:21 8.7K renderers/ 2014-05-03 13:35 - series/ 2014-05-03 13:35 - styles/ 2014-05-03 13:35 -
Apache/2.4.9 (Unix) OpenSSL/1.0.1h Server at flex.apache.org Port 80


Posted by 1010
카테고리 없음2014. 6. 24. 17:24
반응형

FlexLib component list

This wiki page contains a list of all components contained in the current build of flexlib. After adding new components to FlexLib, you should edit this page and include a short summary of the component and the links to the ASDoc documentation and the sample SWF file, if available. Include the names of contributors for each component.

package: flexlib.controls

Base64Image

An image component that renders base-64 encoded images.

Documentation | Example | Contributor: Stacy Young

CanvasButton

The CanvasButton is an extension of Button that lets you set the contents of the Button to any UI components, as opposed to only a single icon and label like the normal Button control allows.

Documentation | Example | Contributor: Doug McCune

CanvasButtonAccordionHeader

The CanvasButtonAccordionHeader allows you to use a CanvasButton component as the header renderer of an Accordion, meaning you have full control over the header renderer and can add additional UI control, etc.

Documentation | Example | Contributor: Doug McCune

ConvertibleTreeList

A control that combines the functionality of the Tree component and the List component. The ConvertibleTreeList allows you to use one control and have it display the dataProvider either as a Tree or as a List. You only have to set the dataProvider once. You can set the mode at any time to change the display mode.

Documentation | Example | Contributor: Doug McCune

Fire

A component to produce a simulated fire effect.

Documentation | Example | Contributor: Doug McCune

Highlighter

A component to highlight selected words or phrases within a text control

Documentation | Example | Contributor: Tom Lee

HSlider and VSlider

Alternatives to the HSlider and VSlider controls included in the Flex framework. This version of the HSlider and VSlider allows you to drag the region between the thumbs, if the slider has mutliple thumbs. If there is more than one thumb then the region between the leftmost thumb and the rightmost thumb is draggable.

Documentation | Example | Contributor: Doug McCune

IconLoader

The IconLoader component converts a Macintosh OS X (.icns) or Windows XP (.ico) icon file, along with its alpha mask, to a Flex 2 UIComponent.

Documentation | Example | Contributor: Tobias Patton

ImageMap

The ImageMap control is an implementation of a client-side image map component, like it is supported in HTML.

Documentation | Example | Contributor: Doug McCune

PromptingTextInput

The PromptingTextInput component is a small enhancement to standard TextInput. It adds the ability to specify a prompt value that displays when the text is empty, similar to how the prompt property of the ComboBox behaves when there is no selected value.

Documentation | Example | Contributor: Darron Schall

PromptingTextArea

The PromptingTextArea component is a small enhancement to standard TextArea. It adds the ability to specify a prompt value that displays when the text is empty, similar to how the prompt property of the ComboBox behaves when there is no selected value.

Documentation | Example | Contributor: Darron Schall

ScrollableArrowMenu

An extension of ScrollableMenu that uses two arrow buttons placed at the top and bottom of the menu for scrolling.

Documentation | Example | Contributor: Doug McCune

ScrollableMenu

An extension of mx.controls.Menu that allows the control to scroll vertically.

Documentation | Example | Contributor: Doug McCune

ScrollableMenuBar

ScrollableMenuBar is an extension of MenuBar that uses flexlib.controls.ScrollableMenu instead of using the original mx.controls.Menu. This allows us to specify a maxHeight for the ScrollableMenuBar and that maxHeight will be used to determine the maxHeight for all the menus that the component generates.

Documentation | Example | Contributor: Doug McCune

ScrollablePopUpMenuButton

ScrollablePopUpMenuButton is an extension of PopUpMenuButton that uses flexlib.controls.ScrollableMenu instead of using the original mx.controls.Menu, which adds scrolling functionality to the menu.

Documentation | Example | Contributor: Doug McCune

SuperTabBar

The SuperTabBar control extends the TabBar control and adds drag and drop functionality and closable tabs. Used by the SuperTabNavigator.

Documentation | Example | Contributor: Doug McCune

TreeGrid

A control that combines the functionality of the Tree component and the DataGrid component.

Documentation | Example | Contributor: Yaniv De Ridder

VerticalMenuBar

A VerticalMenuBar control defines a vertical, top-level menu bar that contains one or menu items, just like the horizontal MenuBar control.

Documentation | Example Contributor: Doug McCune

package: flexlib.containers

AdvancedForm

The Advanced Form component provides Reset, Undo and Redo functionality. Undo and Redo are accessed by pressing "ctrl-Z" and "ctrl-Y" respectively.

Documentation | Example | Contributor: Renaun Erickson

ButtonScrollingCanvas

This is a Container component that uses buttons placed over the edges of the container to do the scrolling of its children. These buttons can either scroll the children when the user moves the mouse over them, or via mouse click. The buttons can be fully skinned.

Documentation | Example | Contributor: Doug McCune

Docking ToolBar

The docking toolbar component collectively helps managing toolbars in an application. The toolbars can be docked to the top or bottom edges or kept floating within application area. The contents within a toolbar use a flow based layout approach.

Documentation | Example | Contributor: Adobe Flex Team (Bangalore)

DragScrollingCanvas

This is a Container component that allows the user to drag the contents to scroll the children, instead of or in addition to using the scrollbars.

Documentation | Example | Contributor: Doug McCune

HAccordion

A Horizontal Accordion component. Works exactly like the normal Accordion component, except the item headers are rotated and they cascade from left to right, instead of top to bottom.

Documentation | Example | Contributor: Doug McCune

FlowBox

The FlowBox is an extension of Box that implements a FlowLayout algorithm for layout out children. FlowBox will position children in a horizontal fashion. When the width of the child exceeds the width of the container, the child is placed on a new row.

Documentation | Example | Contributor: Darron Schall

SuperTabNavigator

The SuperTabNavigator is an extension of the TabNavigator navigation container. It functions exactly like the TabNavigator, but adds some functionality. Added functionality includes: 1. Draggable, re-orderable tabs, 2. Closable tabs, 3. Scrolling tab bar if too many tabs are open, 4. Drop-down list of tabs

Documentation | Example | Contributor: Doug McCune

WindowShade

The WindowShade is a container that displays a header button, which when clicked, will cause a panel to "unroll" beneath it like a windowshade being pulled down; or if the panel is already displayed it will be "rolled up" like a windowshade being rolled up.

Documentation | Example | Contributor: Dave Glasser, Doug McCune

package: flexlib.charts

DraggablePie

The DraggablePie is a chart a pie chart where each wedge is draggable the user. It is used so that users can manipulate the data displayed in a pie chart. The pie chart can be configured to dispatch changes while dragging, or when the dragging is complete.

Documentation | Example | Contributor: Billy Schoenberg

HorizontalAxisDataSelector

The HorizontalAxisDataSelector is a chart annotation that allows the user to select a value along the x axis of the chart. The selector dispatches a change event with the values of each of the y values of the chart series at the given x axis location.

Documentation | Example | Contributor: Darron Schall

package: flexlib.skins

EnhancedButtonSkin

This is the enhanced version of the Halo ButtonSkin that has been customized to support four numeric values in the corner, a more configurable border, and also a large number of colors in the gradient, individually specified for up, over, etc states.

Documentation | Example | Contributor: Daniel Wabyick

package: flexlib.scheduling

Put some better Scheduling Framework documentation here, or put a link to a separate wiki page?

Original Adobe Labs wiki entry

Documentation | Example 1 demo source | Example 2 demo source | Example 3 demo source | Example 4 demo source | Example 6 demosource | Example 7 demo source | Contributor: Adobe Consulting, Wim Roelens Contributor: Adobe Consulting



출처 : https://code.google.com/p/flexlib/wiki/ComponentList

Posted by 1010
반응형

There are a lot of Flex Explorer applications available on line. These explorers can really help when you want to refresh your knowledge on the Flex capabilities or when you plan to fine tune specific styles or effects.

Whether you’re trying to design a good looking button or data grid, configuring a fancy glow effect, implementing a complex regular expression, configuring a BlazeDS channel or just searching for inspiration; there is probably a Flex Explorer for you.

Here is my own list of explorers, that I also gathered in my Flex Tool Box page for quick and easy reference.

Flex Component Explorer

Flex Component Explorer screen capture
The Flex Component Explorer lets you browse through the huge list of available Flex core components. For each of them, a small sample application (corresponding code is available) shows how the component is rendered and behaves. Even if you can’t change the component configuration, this remains a useful tool when you’d like to learn more of a component that you never used so far.

Tour de Flex Explorer

Tour De Flex screen capture
The Tour De Flex Explorer is available on line but can also be installed as an AIR application. It extends the Flex 3 Component Explorer by adding Flex 4 Spark components description, coding techniques examples, Flex Data Access information, Flex frameworks introduction and much more.

Flex Chart Sampler

Flex Chart Sampler screen capture
The Flex Chart Sampler (from Ely Greenfield blog) lets you interactively discover the Flex Charting components.

Flex Style Explorer

Flex Style Explorer screen capture
The Flex Style Explorer is probably the one I use the most. You can use it to style interactively any component, see how looks the result and export the result as a CSS file that you can use in your projects.

Flex Enhanced Button Skin Explorer

Flex Enhanced ButtonSkin Explorer screen capture
The Flex Enhanced Button Skin Explorer(from Daniel Wabyick blog) is an explorer dedicated to the EnhancedButtonSkin available in FlexLib.

Adobe® Kuler™ Color Themes Explorer

Kuler Color Theme Explorer screen capture
The Adobe® Kuler™ Color Themes Explorerallows experimenting quickly with color variations and browse color themes from the Kuler community (can be downloaded as an AIR application).

Flex Filter Explorer

Flex Filter Explorer screen capture
The Flex Filter Explorer (from Joe Johnston blog) lets you define your flex filter interactively and generates the corresponding MXML to include in your projects.

Flex Easing Function Explorer

Flex Easing Function Explorer screen capture
The Flex Easing Function Explorer (fromJames Ward blog) allows experimenting with ease functions that allow applying non-linear motion to effects.

Flex Distortion Effect Explorer

Flex Distortion Effect Explorer screen capture
The Flex Distortion Effect Explorer (from Alex Uhlmann blog) demonstrates fancy distortion effects such as Flip, Pop, Cube rotate, Door and much more.

Flex Reflection Explorer

Flex Reflection Explorer screen capture
The Flex Reflection Explorer (from Wietse Veenstra blog) demonstrates beautiful reflection effects using the ReflectionManager provided class.

Efflex Explorer

Efflex Explorer screen capture
The Efflex Explorer (from Efflex.org) demonstrates the effects available when using the open source Efflex library.

Flex Regular Expression Explorer

Flex Regular Expression Explorer screen capture
The Flex Regular Expression Explorer (fromRyan Swanson blog) lets you define your regular expressions from the explorer and check immediately whether they work or not by providing test data and look at the result. This explorer also provides a very good on line help that should allow you not be afraid by regular expressions anymore.

BlazeDS Channel Designer

BlazeDS Channel Designer screen capture
The BlazeDSChannel Designer isn’t really an explorer but I thought it would be useful to mention it here. It provides an easy and interactive way to configure your BlazeDS channels and outputs the services-config.xml corresponding to your options.

Rating: 5.0/5 (8 votes cast)


Posted by 1010
반응형

출처 : http://hapina.tistory.com/10


플렉스에서 하나의 어플리케이션에 모듈을 여러개 로딩하여 사이즈를 줄이는 방법으로 프로젝트가 많이 진행됩니다.

그러나 가끔 마우스 다운 이벤트 및 드래깅 시 다음과 같은 에러가 발생합니다.

TypeError: Error #1034: 유형 강제 변환에 실패했습니다. mx.managers::DragManagerImpl@a23f6f1을(를) mx.managers.IDragManager(으)로 변환할 수 없습니다.

또는 다음과 같은 에러...

ReferenceError: Error #1065: 변수 mx.managers::DragManager이(가) 정의되어 있지 않습니다.

데이터그리드를 넣은 모듈을 로드하여 폴더 열기/닫기 할 때 처음 이 에러를 만났습니다.

이 문제의 원인과 해결책에 대해 알아봅시다.

원인 및 해결책.

플렉스 프레임웤 상 DragManager 는 싱글톤으로 하나의 인스턴스만 존재해야 합니다.

App 에는 Manager DB 가 존재하여 모든 Manager 를 관리합니다.(모든 메니저의 인스턴스가 아닌 클래스)

처음 모듈을 로딩할 때 DragManager 가 해당 모듈에서 인스턴화되면..

두번째 모듈에서는 해당 인스턴스를 알아낼 방법이 없어집니다. 즉 혼란이 생긴거죠.

모듈의 Applicatoin shared code 때문에 생기는 일입니다.

따라서 처음 드래그메니저의 인스턴스를 App 에서 생성되도록하여 모든 모듈이 드래그메니저의 인스턴스를 App 에서 참조하도록 설정합니다.

해결책으로 이를 방지하기 위해 어플리케이션에서 다음과 같이 DragManager 를 import 하세요.

이는 아마도 버그일 수 있습니다. 최초 App 에서 드래그메니저의 인스턴스를 생성하면 되는데 그렇지 않고 있기 때문이죠.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 <mx:Script>
  <![CDATA[

   import mx.managers.DragManager;
   private var dummy:DragManager;
   
....
...
...

  ]]>
 </mx:Script>

이 처럼 App 에서 DragManager 의 인스턴스를 생성하게 하여 클래스를 내포시킵니다.

그럼 굿럭!~

Posted by 1010
반응형

출처 : http://blog.jidolstar.com/666


Flash 애플리케이션을 제작할때 항상 고민되는 것은 메모리와 속도일 것이다. 이 문서는 이러한 고민을 했던 분들을 위해 본인의 경험을 반영하여 작성한 것이다. 주의할 것은 이 문서에서 다루는 Object Pool은 메모리, 속도 개선을 위한 하나의 방법일 뿐이지 전부는 아니다라는 것이다. Object Pool이 어떻게 당신의 애플리케이션의 속도와 메모리를 개선시켜줄 것인가 전달하는 것이 문서의 목표이다.

목차 

  1. 객체 관리에 대한 질문!
  2. new 연산자는 비싸다!
  3. Object Pool이란?
  4. Object Pool을 도입할 때 고려사항
  5. Object Pool을 사용해보자.
  6. Object Pool과 new 연산자 사용 비교
  7. 메모리 사용의 폭이 급격한 애플리케이션은 좋지 못하다.
  8. 재사용할 수 있는 클래스 제작
  9. 정리하며
  10. 참고글



1. 객체 관리에 대한 질문!
제작된 애플리케이션에 필요한 최소한의 메모리에 대해서 생각해 본적이 있는가? 하나의 애플리케이션에 들어가는 최소 자원(resource)은 얼마나 될까? 그 자원은 얼마나 자주 사용하고 버리는 것일까? 

슈팅 게임을 보면 동일한 적군전투기가 많이 나온다. 그 중에 적군전투기1이 있다고 하자. 적군전투기1이 한 화면에 5개가 나왔다. 아군전투기에 의해 죽든 화면에서 사라지든 어쨌든지 언젠간 화면에서 사라지고 쓸모없게 된다. 좀 있다가 또 적군전투기1이 3개가 나온다. 또 반복해서 사라진다. 당신이 이 슈팅 게임을 만든다면 적군전투기1 관리를 어떻게 할 것인가? 즉, 화면에 나타날때 new로 생성하고 사라지면 delete로 메모리에게 해지요청할 것인가? 아니면 어느 특정 영역에 화면에 나타날 전투기1을 미리 5개에서 10개 생성해놓고 필요할 때마다 재사용할 것인가? 

2. new 연산자는 비싸다!
new는 클래스를 통해 객체를 생성하는 연산자이다. 이는 비교적 비용이 비싼편이다. 비용이 비싸다는 말을 구체적으로 설명하자면 new를 통해 객체를 생성하여 메모리에 올리고 다 사용했다고 판단될때 delete이나 null등을 이용해 객체참조를 제거하여 가비지 컬렉터에 맡기게 되며 결과적으로 가비지 컬렉터는 이 객체를 어느 특정시점에 제거하는 일련의 객체 생성과 삭제까지 동작이 꽤 복잡하여 메모리, CPU연산등의 자원소비가 크다라는 것을 의미한다. 특히나 클래스의 크기가 크고 복잡하다면 그 비용은 더욱 갑절로 들게 된다. new 연산 사용은 이처럼 비싼 비용을 지불해야 하기 때문에 할 수 있다면 최소한으로 사용하도록 하는 것이 속도와 메모리 관리에 도움을 준다.

앞서 설명한 슈팅 게임을 보자면 적군전투기1은 수시로 보였다가 안보였다가 한다. 이 경우 new, delete를 반복한다면 경우에 따라서 엄청난(?) 비싼 비용을 지불하게 된다. 

다른 예를 들어보겠다. 본인은 얼마전에 스타플(http://starpl.com)이라는 사이트에서 제공하는 타임라인 애플리케이션을 Flash로 개발했다. 타임라인은 사용자의 기록, 앨범등을 시간순으로 보여주게 되며 좌우측으로 이동해서 내 인생의 기록을 보는듯한 느낌을 주도록 만들었다. 이때 화면에 보여지는 사용자의 기록들이 수시로 보여졌다가 사라진다. 이때 사용된 기록을 보여주는 시각객체(DisplayObject)를 new와 delete를 반복해서 생성 및 삭제한다면 너무 비싼 비용을 들이는 것과 같다. 

스타플의 타임라인

참고글 : 스타플 타임라인 업그레이드 및 앨범 기능 추가 소식

앞의 2가지 예에서 언급했듯이 자주 보여지고 사라지는 객체를 필요할 때마다 new연산자를 사용하는 것보다는 어느 특정 영역에 미리 생성해놓고 재사용을 반복하는 구조를 도입한다면 메모리와 CPU연산에 있어서 큰 비용절감을 기대할 수 있게 된다. 

3. Object Pool이란?
Object Pool(객체 풀)은 객체를 미리 만들어놓고 담아놓는 메모리 영역이다. 개발자는 이 Object Pool에 미리 만들어진 객체를 사용하고 다 사용한 뒤에는 다시 반환시킴으로서 재사용(또는 대여)을 하도록 한다. Object Pool을 사용하면 처음 객체를 생성할때와 더 필요한 객체가 있는 경우를 제외하고 new 연산을 최소화 할 수 있다. 

4. Object Pool을 도입할 때 고려사항 
Object Pool은 미리 객체를 생성하고 지속적으로 재사용하기 위해 사용한다. 이때 미리 객체를 생성한다는 것은 초반 애플리케이션 동작 퍼포먼스에 영향을 미칠 수 있다. 

Object Pool을 사용했을때 다음과 같은 장점을 얻을 수 있다.

1. new 연산자를 자주 사용해야하는 경우에 도입하면 애플리케이션 속도 향상을 기대할 수 있다. 
2. 가비지 컬렉터에 의존하지 않는 메모리 관리를 꾀할 수 있다.

하지만 일반적으로 10개가 필요한데 미리 100개를 만들어 항상 10% 미만 정도의 재사용률을 보인다면 그것은 메모리 낭비이다. 그러므로 다음과 같은 조건에서 Object Pool을 사용하고 관리하는 것이 좋겠다.

1. 비교적 큰 용량의 객체를 자주 사용되거나 반환해야하는 경우에 사용한다.
2. 미리 생성할 객체를 적당하게 정하도록 한다.

반대로 위 경우가 아니라면 쓸데없이 Object Pool을 사용하지 말자. 


5. Object Pool을 사용해보자.

폴리고널 lab에서 간단한 Object Pool을 공개했다. 아래 링크에서 다운로드 받을 수 있다.


사용 방법은 매우 간단하다. ObjectPool 클래스는 아래 코드처럼 특정 클래스를 할당(allocate)하면 된다.

var isDynamic:Boolean = true;

var size:int = 100;

var pool:ObjectPool = new ObjectPool(isDynamic);

pool.allocate(MyClass, size);


isDynamic 플래그는 Object Pool내의 객체가 비어있는가 체크하기 위해 사용한다. 즉, true이면 Pool은 자동적으로 정해진 크기(size)를 넘어서더라도 Pool의 크기를 확장하여 새로운 객체를 줄 수 있으나 false이면 정해진 크기만큼 객체를 이미 준 경우에는 Pool이 비게 되므로 Error를 발생시킨다. 

크기(size)를 100으로 지정했기 때문에 미리 Object Pool에 100개의 MyClass의 객체를 생성해 두도록 한다. 

이제부터 MyClass는 아래와 같은 방식으로 사용하면 되겠다.

myObjectArray[i] = new MyClass();

// 코드 대신 아래를 사용한다.

myObjectArray[i] = pool.instance;


다 사용한 MyClass객체는 Object Pool에 반환해줘야 한다. 이때 가비지 컬렉터의 기능을 이용하는게 아니라 재사용(recycle)을 위해서 다음과 같이 코딩하면 되겠다.

pool.instance = myObjectArray[i];


사용방법은 이게 전부다. 

원한다면 자신의 애플리케이션에 맞게 이 공개된 ObjectPool을 개선시킬 수 있다. 가령, 100개의 Pool을 만들어놓지만 처음부터 100개를 생성해놓지는 않겠고 필요할 때마다 생성해주는 구조인 게으른(lazy) 생성을 기대할 수 있을 것이다. 또는 DisplayObject의 경우라면 사용한다는 것을 DisplayObject.parent 속성으로 판단할 수 있다. 위 처럼 pool.instance = '다 사용한 객체'와 같은 형태로 반환하는 것보다 자신의 부모가 존재하지 않는다면 재사용할 객체로 판단하도록 만들면 일종의 자동 Object Pool을 만들 수 있다. 자동 Object Pool은 다음 링크를 참고하면 좋겠다. 

자동 풀링(auto pooling)을 구현해보자.



6. Object Pool과 new 연산자 사용 비교 

Object Pool을 사용해야하는 타당성은 퍼포먼스 실험을 통해 쉽게 알 수 있다.  이러한 점에서 폴리고널 랩에서 제공하는 실험은 매우 유용한 자료이다. 

실험 방법은 아래와 같다. (폴리고널 랩에서는 이 실험을 Window Vista, Flash Player 9.0.124에서 진행했다.) 그리고 Pool크기는 100으로 지정했다. 

첫번째로 아래 코드처럼 k수 만큼 Object Pool로 부터 객체를 get만 한다.

for (var i:int = 0; i < k; i++) instances[i] = p.instance;


두번째로 아래 코드처럼 k수 만큼 Object Pool로부터 객체를 get/set 한다.

for (i = 0; i < k; i++) instances[i] = p.instance;

for (i = 0; i < k; i++) p.instance = instances[i];


세번째로 아래 코드처럼 k수 만큼 Object Pool대신 new 연산자를 사용한다.

for (i = 0; i < k; i++) instances[i] = new MyClass();



결과는 다음과 같다.


네이티브 Object 클래스의 경우 Object Pool을 사용하는 것이 new 연산자를 사용한 것보다 5배 정도 빨랐다.


Object 보다 더 크고 복잡한 flash.geom.Point의 경우는 약간더 빠른 결과를 보인다.


 flash.display.Sprite 객체를 가지고 하면 무려 80배나 속도 개선이 되었다. 이는 복잡하고 큰 클래스에 Object Pool을 도입하면 효과적일 수 있다고 판단할 수 있다.

이 실험을 통해 적절한 방법으로 Object Pool을 사용하는 것은 애플리케이션의 퍼포먼스 증가에 지대한 영향을 줄 수 있다는 것을 깨달을 수 있다.


7. 메모리 사용의 폭이 급격한 애플리케이션은 좋지 못하다.
본인은 어떤 애플리케이션(Flash가 아니더라도)이든지 그 애플리케이션에 필요한 최소한의 메모리는 항상 존재한다고 생각한다. 무조건 메모리 사용을 줄여보겠다고 new, delete를 반복하는 것은 잘못된 것이다. new, delete를 반복하면 오히려 CPU 및 메모리 사용의 반복을 부축이며 애플리케이션의 전체적인 퍼포먼스를 저하시키는 경우가 발생할 수 있다. 실제로 new,delete를 반복하는 구조로 개발한 애플리케이션을 Flash Builder의 프로파일링 기능을 통해 메모리 사용을 살펴보면 큰폭으로 메모리 사용/해지가 일어난다는 것을 확인할 수 있다. 그러므로 몇몇 사람들이 Object Pool과 같은 개념과 같이 퍼포먼스 향상에 도움이 되는 개념을 전혀 사용하지 않고 Flash는 느리고 가비지 컬렉터 동작은 비정상적이다라고 말하는 것은 섣부른 판단이다라고 생각한다. 얼마든지 메모리를 효율적으로 사용하고 속도 개선을 할 수 있음에도 불구하고 잘못된 개발 방식때문에 전체적인 퍼포먼스가 나빠지는 것은 결국 개발자의 잘못인 것이다. 이는 Flash든 어떤 언어든 동일한 생각으로 접근해야 한다.

Flash Builder의 프로파일링 기능을 이용해 Object Pool과 new 연산자간의 메모리 변화를 확인할 수 있는 간단한 실험을 해보겠다. (프로파일링 기능을 사용하는 방법은 주제에서 벗어나므로 제외하겠다.)

먼저 Shape객체를 확장해서 크기와 색이 렌덤하게 그려지는 클래스를 만든다.

//화면에 출력할 Shape

class RandomShape extends Shape {

        static private var colorPool:Array = [0xff0000,0x00ffff,0x0000ff,0x00ff00,0x0f0f0f,0xf0f0f0,0xffff00,0xf00cf0,0x00fcaa,0xff0c9a];

        public function RandomShape():void {

        }

        public function draw():void {

               var radius:Number = Math.random() * 40;

               var color:uint = colorPool[ Math.floor(Math.random()*9) ];

               graphics.clear();

               graphics.beginFill(color,1.0);

               graphics.drawCircle( 0, 0, radius );

               graphics.endFill();

        }

}


위 클래스를 가지고 자동 Pool을 구현한 클래스를 만든다.(참고 : http://www.diebuster.com/?p=1000)

//Shape 자동 객체 Pool

class RandomShapeAutoPool {

        private var _pool:Vector.<RandomShape>;

        public function RandomShapeAutoPool() {

               //적당히 수로 초기화한다.

               _pool=new Vector.<RandomShape>();

        }

 

        public function getShape():RandomShape {

               var key:*, result:RandomShape;

               //먼저 기존의 pool에서 찾아본다.

               for (key in _pool) {

                       //만약 해당 객체가 null이라면 new 통해 생성한다.

                       if (_pool[key] === null) {

                              _pool[key]=new RandomShape;

                              result=_pool[key];

                              break;

                       //null 아니라면 parent 조사하여 사용가능한지 판단한다.

                       else if (_pool[key].parent === null) {

                              result=_pool[key];

                              break;

                       }

               }

               //기존의 pool안에서 쓸만한  찾지 못했다면

               if (result === null) {

                       result=new RandomShape;

                       _pool[_pool.length]=result;

               }

               //인스턴스를 반환한다.

               return result;

        }

}


이제 테스트할 수 있는 호스트코드를 제작해보겠다.

package {

        import flash.display.*;

        import flash.events.*;

        import flash.text.*;

        import flash.utils.*;

 

        [SWF(backgroundColor="#ffffff", frameRate="60", width="400", height="400")]

        public class ObjectPoolTest extends Sprite {

               private var pool:RandomShapeAutoPool=new RandomShapeAutoPool;

               private var poolFlag:Boolean = false;

               private var textPoolFlag:TextField;

               private var shapeCanvas:Sprite;

 

               public function ObjectPoolTest() {

                       addEventListener(Event.ADDED_TO_STAGE, ADDED_TO_STAGE);

               }

 

               private function ADDED_TO_STAGE($e:Event):void {

                       removeEventListener(Event.ADDED_TO_STAGE, ADDED_TO_STAGE);

                       stage.scaleMode=StageScaleMode.NO_SCALE;

                       stage.align=StageAlign.TOP_LEFT;

                       //rf)http://blog.jidolstar.com/656

                       if (stage.stageWidth === 0 && stage.stageHeight === 0) {

                              stage.addEventListener(Event.ENTER_FRAME,function($e:Event):void {

                                             if (stage.stageWidth > 0 || stage.stageHeight > 0) {

                                                     stage.removeEventListener($e.type, arguments.callee);

                                                     init();

                                             }

                                      });

                       else {

                              init();

                       }

               }

 

               private function init():void {

                       //shape 부모객체

                       shapeCanvas = new Sprite;

                       addChild( shapeCanvas );

                       //PoolFlag 상태표시

                       textPoolFlag = new TextField();

                       textPoolFlag.text = "poolFlag=" + poolFlag;

                       addChild(textPoolFlag);

                       //마우스 클릭 영역

                       graphics.beginFill(0x000000,0);

                       graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);

                       graphics.endFill();

                       addEventListener(MouseEvent.CLICK, MOUSE_CLICK);

                       //반복동작     

                       addEventListener(Event.ENTER_FRAME, ENTER_FRAME);

               }

 

               private function MOUSE_CLICK($e:MouseEvent):void {

                       //마우스 클릭때마다 poolFlag 상태를 전환

                       poolFlag = !poolFlag;

                       textPoolFlag.text = "poolFlag=" + poolFlag;

               }

              

               private function ENTER_FRAME($e:Event):void {

                       var shape:RandomShape, i:int, numChildren:int;

                       //poolFlag 따라서 new연산자 또는 Object Pool에서 객체 참조

                       shape = poolFlag ? pool.getShape() : new RandomShape;

                       shape.draw();

                       shape.x = Math.random() * stage.stageWidth;

                       shape.y = 0;

                       shapeCanvas.addChild( shape );

                       //계속 아래로 떨어뜨림화면에서 벗어나면 removeChild시킴

                       numChildren = shapeCanvas.numChildren;

                       for( i=0; i<numChildren;i++) {

                              shape = shapeCanvas.getChildAt(i) as RandomShape;

                              shape.y += 5;

                              if( shape.y > stage.stageHeight ) {

                                      shapeCanvas.removeChild( shape );

                                      i--;

                                      numChildren--;

                              }

                       }

               }

        }

}


동작은 매우 단순하다. poolFlag가 true이면 제작한 자동 Object Pool을 사용하겠다는 것이고 false이면 new 연산자를 사용해 RandomShape객체를 생성하겠다는 것이다. poolFlag 전환은 마우스 클릭으로 할 수 있다. 그리고 비가 내리는 것처럼 Shape 객체는 위에서 부터 아래로 떨어지며 맨 아래에 닿으면 removeChild 시킨다.

테스트 화면


실행 코드와 결과물은 http://wonderfl.net/code/805dc65d1f7800b7bee5dc3cd72ca21c0a87c2d6 에서도 볼 수 있다.

이제 Flash Builder의 프로파일링 기능을 이용해 메모리 변화 및 객체 생성빈도를 살펴보자.

먼저 new 연산자를 사용했을때 메모리 변화를 보자. 

new 연산자로 객체생성시 Memory Usage


new 연산자를 사용해 객체를 생성하고 필요없을때 removeChild를 하게 되면 가비지 컬렉션 처리가 되기 때문에 일정한 시점에 메모리가 해지되는 것을 반복하는 것을 확인할 수 있다.

new 연산자로 객체생성시 Live Object


위 표는 축적된 객체수(Cumulative Instances), 현재 객체수(Instances), 축적된 메모리(Cumulative Memory), 현재 메모리(Memory)를 나타낸다. 변화 무쌍하며 실제로 보여지지 않는 객체도 가비지 컬렉션 처리가 일어날때까지 메모리에 남아 있다. 분명 비효율적으로 보인다.

반대로 Object Pool을 이용했을때 메모리 변화이다.

Object Pool로 객체관리시 Memory Usage

new 연산자를 사용했을때와 비교가 안될 정도로 고요한 느낌이 든다. 거의 일직선의 메모리 사용율을 보인다.

Object Pool로 객체관리시 Live Object


축적되는 객체도 81개를 넘지 않는다. 그만큼 객체 생성과 삭제에 민감하지 않게 되고 가비지 컬렉터 도움을 받지 않고 객체관리가 되는 것을 확인할 수 있다.


8. 재사용할 수 있는 클래스 제작

Object Pool을 사용시 한가지 고려할 사항은 재사용할 수 있는 클래스를 만들어야 한다는 점이다. 왜냐하면 Object Pool은 단순히 재사용을 위한 공간만 제공하는 것이지 재사용을 하기 위한 어떤 기능을 클래스에게 줄 수 없기 때문이다. 그래서 재사용이 가능한 클래스를 설계하는 것은 하나의 기술적 이슈가 될 수 있다.  

재사용할 수 있는 클래스를 어떻게 만드는지 간단한 예를 들어보겠다.

final public class MyData {

        public var type:String;

        public var id:int;

        public var name:String;

}


위 클래스는 데이터를 담는 클래스이다. id, name은 실제 사용하는 데이타 값들이고 이 데이타의 종류는 type으로 구분한다. 이 데이타를 사용하는 인터페이스를 제작해보겠다.

public interface IMyClass {

        function init($data:MyData):void;

        function clear():void;

        function get data():MyData;

}


이 인터페이스는 앞으로 만들 MyClass01, MyClass02... 등을 구현하기 위한 것이다. 초기화 하기 위해 init()함수가 있고 인자로 위에서 제작한 MyData 객체를 받는다. 또한 사용할 필요가 없을때 내부 청소를 위해 clear()함수를 추가했다. 게다가 가지고 있는 data를 참고하기 위해 get data()도 만들었다. 이제 이 인터페이스를 구현한 클래스는 아래처럼 만든다.

final internal class MyClass01 extends Sprite implements IMyClass {

        private var _data:MyData;

        public function MyClass01() {

        }

        public function init($data:Mydata):void {

               _data = $data;

               //구현

        }

        public function clear():void {

               _data = null;

        }

        public function get data():MyData {

               return _data;

        }

}

 

final internal class MyClass02 extends Sprite implements IMyClass {

        private var _data:MyData;

        public function MyClass02() {

        }

        public function init($data:Mydata):void {

               _data = $data;

               //구현

        }

        public function clear():void {

               _data = null;

        }

        public function get data():MyData {

               return _data;

        }

}

 

final internal class MyClass03 extends Sprite implements IMyClass {

        private var _data:MyData;

        public function MyClass03() {

        }

        public function init($data:Mydata):void {

               _data = $data;

               //구현

        }

        public function clear():void {

               _data = null;

        }

        public function get data():MyData {

               return _data;

        }

}



코드가 길어보이지만 3개 클래스 모두 IMyClass를 구현했고 Sprite를 확장했다. 단지 클래스 이름만 다르며 실제 구현부는 알아서 구현하면 된다. 

개발자는 MyClass01, MyClass02, MyClass03은 매우 자주 new 연산자로부터 생성되는 클래스로 판단했고 그래서 Object Pool을 도입하겠다고 결정했다고 하자. 그럼 다음과 같이 시도해 볼 수 있다.

import de.polygonal.core.ObjectPool;

import flash.display.DisplayObject;

 

public class MyPool {

        private static var poolList:Object;

       

        static public function init():void {

               poolList = {

                       'type01':new ObjectPool(true),

                       'type02':new ObjectPool(true),

                       'type03':new ObjectPool(true),

               };

               poolList.type01.allocate(20, MyClass01);

               poolList.type02.allocate(10, MyClass02);

               poolList.type03.allocate(100, MyClass03);

        }

       

        static public function getObject($data:MyData):IMyClass {

               if( $data === null ) {

                       throw new Error('인자값은 null이면 안됩니다.');

               }

               try {

                       var object:IMyClass = poolList[$data.type].object;

                       object.init($data);

               catch {

                       throw new Error('데이타의 type값이 잘못된 값입니다.');

               }

               return object;

        }

       

        static public function returnObject($object:IMyClass):void {

               if( $object === null ) {

                       throw new Error('인자값은 null이면 안됩니다.');

               }

               $object.clear();

               if( DisplayObject($object).parent ) {

                       DisplayObject($object).parent.removeChild( DisplayObject($object) );

               }

               poolList[$object.data.type].object = $object;

        }

}



위에서 제작된 MyPool은 static클래스이며 ObjectPool을 이용해 IMyClass 인터페이스를 구현한 클래스를 init()함수에서 적당하게 할당하는 것을 확인할 수 있다. 또한 getObject()를 통해 인자값 data를 참고하여 참조할 Object Pool을 찾아 IMyClass를 구현한 각각의 클래스의 객체를 받아올 수 있으며 returnObject를 통해 다 사용한 객체를 반환한다. 

실제로 실무에서 이런 형태로 개발했고 이는 매우 유용했다. MyPool 클래스를 더 개선해서 더 많은 수 Object Pool을 감당할 수 있도록 확장할 수 있다면 더욱 유용해질 것이라 생각한다.


9. 정리하며 

Object Pool 개념은 Flash에만 국한되는 유용한 개념이 아니다. 이런 개념들에 대한 노하우를 계속 쌓아간다면 당신의 애플리케이션은 더욱 좋은 작품으로 탈바꿈할 수 있을 것이다. 

Flash Player가 느리고 메모리 관리가 안된다고 생각하지는 말자. Flash Player 태생자체가 그런것을 어찌하겠는가? 제작한 애플리케이션이 느리다면 그것은 결국 개발자가 잘못한 것임을 항상 인지하자. 중요한 것은 여전히 Flash Player는 유용하고 많이 사용되고 있으며 지금도 나날이 발전하여 Cross OS, Cross Browser를 넘어 Cross Device 세계로 뻗어가고 있다는 점이다.


10. 참고글

글쓴이 : 지돌스타(http://blog.jidolstar.com/666

Posted by 1010
반응형

TextInput 의 restrict property 에 대해...

<mx:TextInput id="txt" restrict="ㄱ-힣">

restrict = "ㄱ-힣"            :  한글만 입력가능.
restrict = "A-z"              :  영어만 입력가능.
restrict = "0-9"               :  숫자만 입력가능.
restrict = "0-9\-"           : 숫자와 '-'만 입력가능.
restrict = "^a-z"             : 소문자 a부터 z까지 제외한 모든문자 입력가능.
restrict = "A-z0-9\@\." : 이메일 형식만 입력가능.
restrict = "\\\"           : '\' 문자만 입력가능.
restrict = "\^"               :  '^' 문자만 입력가능.

여러가지 응용도 하실 수 있겠습니다.


출처 : http://2rang.tistory.com/15

Posted by 1010
반응형

 <mx:DataGridColumn headerText="선택" width="50">
              <mx:itemRenderer>
               <mx:Component>
                <mx:HBox horizontalAlign="center">
                 <mx:Script>
                  <![CDATA[
                               public override function set data(value:Object):void
                               {
                                   super.data = value;
                               }
                  ]]>
                 </mx:Script>
                 <mx:CheckBox id="cb1" selected="{data.chk}" change="{data.chk = cb1.selected}"/>
                </mx:HBox>
               </mx:Component>
              </mx:itemRenderer>
             </mx:DataGridColumn>


출처 : http://blog.naver.com/PostView.nhn?blogId=neodijkstra&logNo=50050005320

Posted by 1010