Dart 2.15가 지난 9일에 발표되었습니다.
dart:core 라이브러리 내 하기와 같은 기능의 변화가 있습니다.
(오역으로 인한 오해를 막기 위해 영문으로 적겠습니다)
- Fast concurrency with worker isolates
- New constructor tear-off language feature
- Improved enum support
Fast concurrency with worker isolates
요즘에는 멀티 코어 CPU로 인하여 여러 개의 작업을 병렬로 실행할 수 있습니다.
Dart Runtime System은 기본적으로 모든 코드를 단일 코어에서 실행하지만, 파일 쓰기나 긴 시간의 네트워크 호출과 같은 비동기 입출력 작업을 위해서는 추가적인 코어를 사용합니다.
하지만 코드 또한 동시에 실행되어야 할 경우도 발생됩니다.
예를들어 연속된 애니메이션과 대용량의 JSON 파일 파싱이 동시에 발생할 때, UI 동작은 매우 느려집니다. 이러한 경우 JSON 파일 파싱 작업은 별도의 코어로 이동함으로써 UI(애니메이션)의 느려짐이나 중단 없이 주요 스레드에서 계속 실행될 수 있습니다.
동시성은 수많은 이슈를 발생할 수도 있기 때문에 독립된 실행 단위를 격리하여 실행해야 합니다. 격리된 공간은 공유되지 않고 메세지를 교환함으로 많은 버그를 방지 합니다.
Dart 2.15에서는 이러한 부분을 위해서 많은 개선을 했습니다. 작업을 분리하는 방법을 재설계하고 재실행함으로써 새로운 개념을 도입했습니다:
그룹을 분리하는 것입니다. 격리된 그룹으로 격리되어 실행 중인 프로그램의 다양한 내부 데이터 구조를 공유합니다. 이것은 매번 격리된 공간을 생성하는 것에 비하여 굉장히 많은 비용을 절감합니다. 매 번초기화할 필요가 없기 때문에 기존 격리 그룹에서 추가적인 분리 작업을 시작하는 것이 100배 이상 빠르며, 이를 통해 생성된 격리 작업은 메모리를 10~100배 더 적게 소모합니다.
격리된 그룹은 격리된 개체 간에 공유 액세스를 금지하지만, 그룹 내 공유된 힙을 구현하여 잠금을 해제할 수 있습니다. 개체를 격리된 공간에서 다른 격리된 공간으로 전달할 수 있습니다.
예를 들어, 데이터를 가져오기 위해 네트워크 호출을 하고, 그 데이터내 용량이 큰 JSON 객체로 파싱한 다음, JSON 객체를 Main isolate로 반환하는 Worker isolate가 있습니다.
다트 2.15 이전에는 이 결과를 온전히 복사해야 했으며, 복사하는 데 시간이 오래 걸리면서 UI junk가 발생할 수 있었습니다.
2.15에서 worker isolate는 Isolate.exit()를 호출하여 결과를 인수로 전달할 수 있습니다. 그런 다음 Dart Runtime이 Worker isolate로부터 결과를 포함하는 메모리를 복사하지 않고 Main isolate로 전달하며 Main isolate는 일정한 시간에 결과를 수신할 수 있습니다.
우리는 Isolate.exit()를 이용하기 위해 Flutdle 2.8의 compute() 유틸리티 함수를 업데이트 했습니다. compute()을 이미 사용 중인 경우 Flutdle 2.8로 업그레이드하면 이러한 성능이 자동으로 향상됩니다.
마지막으로, 우리는 분리 메시지 전달 메커니즘이 어떻게 구현되는지 재 작업하여 중소 규모의 메시지 전달을 약 8 배 더 빠르게 만들었습니다. 전송은 상당히 빠르며, 메시지 수신은 거의 항상 일정한 시간에 이루어진다. 또한 격리된 개체가 서로 보낼 수 있는 개체의 종류를 확장하고 함수 유형, 클로저 및 스택트레이스 개체에 대한 지원을 추가했습니다. 자세한 내용은 SendPort.send()의 API 문서를 참조하십시오.
격리 장치를 사용하는 방법에 대해 자세히 알아보려면 2.15에 대해 추가한 새로운 다트 동시성 문서를 참조하십시오. 우리는 또한 당신이 확인할 수 있는 많은 코드 샘플이 있습니다.
New constructor tear-off language feature
Dart에서는 함수의 이름만으로 다른 객체에 있는 함수를 가리키는 함수 개체를 만들 수 있습니다.
다음 예에서 main() 내 두 번째 줄은 'g'를 'm.greet'로 설정할 수 있습니다.
class Greeter {
final String name;
Greeter(this.name);
void greet(String who) {
print('$name says: Hello $who!');
}
}
void main() {
final m = Greeter('Michael');
final g = m.greet; // g holds a function pointer to m.greet.
g('Leaf'); // Invokes and prints "Michael says: Hello Leaf!"
}
이러한 함수 포인터(함수 분리라고도 함)는 Dart Core 라이브러리를 사용할 때 자주 나타납니다. 다음은 함수 포인터를 전달하여 반복 가능한 forEach()를 호출하는 예입니다.
final m = Greeter('Michael');['Lasse', 'Bob', 'Erik'].forEach(m.greet);// Prints "Michael says: Hello Lasse!", "Michael says: Hello Bob!",
// "Michael says: Hello Erik!"
과거에는 생성자에서 바로 함수 포인터를 생성하는 것을 지원하지 않았습니다.
다트 2.15부터는 이 구문이 지원된다. 다음은 .map()을 호출하여 Text 생성자에게 tell-off를 전달하여 세 개의 Text 위젯을 포함하는 Column 위젯을 작성하는 예입니다.
class FruitWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: ['Apple', 'Orange'].map(Text.new).toList());
}
}
Text.new는 Text 클래스의 기본 생성자를 나타냅니다. 또한 .map(Text.rich)과 같이 명명된 생성자를 참조할 수도 있습니다.
T id<T>(T value) => value;
var intId = id<int>; // New in 2.15.
int Function(int) intId = id; // Pre-2.15 workaround.
Generic 함수 객체를 특수화하여 일반 함수 객체가 아닌 함수 객체를 만들 수도 있습니다.
const fo = id; // Tear off `id`, creating a function object.
const c1 = fo<int>; // New in 2.15; error before.
var y = List; // Already supported.
var z = List<int>; // New in 2.15.
var z = typeOf<List<int>>(); // Pre-2.15 workaround.
Improved enum support
enum MyEnum {
one, two, three
}
void main() {
print(MyEnum.one.name); // Prints "one".
}
print(MyEnum.values.byName('two') == MyEnum.two); // Prints "true".
마지막으로 다음과 같은 모든 이름-값 쌍의 맵을 얻을 수 있습니다.
final map = MyEnum.values.asNameMap();
print(map['three'] == MyEnum.three); // Prints "true".
하기 문서를 참조하여 정리하였습니다.
https://medium.com/dartlang/dart-2-15-7e7a598e508a
'Flutter(플러터) > Dart' 카테고리의 다른 글
Dart Concurrency (동시성) (0) | 2022.01.04 |
---|
댓글