1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-24 22:33:52 +03:00

Add a typesetter runner

This commit is contained in:
Tae Won Ha 2019-03-10 09:50:24 +01:00
parent d126786bbc
commit 038b593881
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
16 changed files with 223583 additions and 38 deletions

View File

@ -1,10 +1,7 @@
//
// AppDelegate.swift
// DrawerDev
//
// Created by Tae Won Ha on 25.08.18.
// Copyright © 2018 Tae Won Ha. All rights reserved.
//
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa

View File

@ -1,7 +1,7 @@
//
// Created by Tae Won Ha on 25.08.18.
// Copyright (c) 2018 Tae Won Ha. All rights reserved.
//
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation

View File

@ -1,7 +1,7 @@
//
// Created by Tae Won Ha on 25.08.18.
// Copyright (c) 2018 Tae Won Ha. All rights reserved.
//
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa

74405
NvimView/DrawerPerf/0.json Normal file

File diff suppressed because it is too large Load Diff

74405
NvimView/DrawerPerf/1.json Normal file

File diff suppressed because it is too large Load Diff

74405
NvimView/DrawerPerf/2.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,52 @@
//
// AppDelegate.swift
// DrawerPerf
//
// Created by Tae Won Ha on 10.03.19.
// Copyright © 2019 Tae Won Ha. All rights reserved.
//
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
import GameKit
import os
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
var result = Array<[[FontGlyphRun]]>(repeating: [], count: count)
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
var results = [CFTimeInterval]()
let repeatCount = 5
for _ in (0..<repeatCount) {
let rd = GKRandomDistribution(
randomSource: GKMersenneTwisterRandomSource(seed: 129384832),
lowestValue: 0,
highestValue: repeatCount - 1
)
let indices = (0..<count).map { i in rd.nextInt() % 3 }
let time = self.measure {
for i in (0..<count) { result[i] = self.perf.render(indices[i]) }
}
results.append(time)
}
self.log.default(
"\(results.reduce(0, +) / Double(results.count))s: \(results)"
)
NSApp.terminate(self)
}
private let perf = PerfTester()
private let log = OSLog(subsystem: "com.qvacua.DrawerPerf",
category: "perf-tester")
private func measure(_ body: () -> Void) -> CFTimeInterval {
let start = CFAbsoluteTimeGetCurrent()
body()
return CFAbsoluteTimeGetCurrent() - start
}
}
private let count = 500

View File

@ -1,7 +1,7 @@
//
// Created by Tae Won Ha on 25.08.18.
// Copyright (c) 2018 Tae Won Ha. All rights reserved.
//
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation

View File

@ -0,0 +1,151 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*
* 0.json from: https://github.com/gshslatexintro/An-Introduction-to-LaTeX
* 1.json from @telemachus
* 2.json from http://generator.lorem-ipsum.info
*/
import Cocoa
import GameKit
import os
class PerfTester {
init() {
self.cellSize = FontUtils.cellSize(of: self.font, linespacing: 1.25)
for name in ["0", "1", "2"] {
guard let fileUrl = Bundle(for: PerfTester.self)
.url(forResource: name, withExtension: "json")
else {
preconditionFailure("Could not find \(name).json")
}
let decoder = JSONDecoder()
do {
let data = try Data(contentsOf: fileUrl)
self.ugrids.append(try decoder.decode(UGrid.self, from: data))
} catch {
preconditionFailure("Couldn't decode UGrid from \(name).json: \(error)")
}
}
self.initAttrs()
}
func render(_ index: Int) -> [[FontGlyphRun]] {
precondition(0 <= index && index <= 2, "Wrong index!")
let ugrid = self.ugrids[index]
let runs = self.runs(index,
forRowRange: 0...ugrid.size.height - 1,
columnRange: 0...ugrid.size.width - 1)
return runs.parallelMap(chunkSize: 50) { run in
let font = FontUtils.font(
adding: run.attrs.fontTrait, to: self.font
)
return self.typesetter.fontGlyphRunsWithLigatures(
nvimUtf16Cells: run.cells.map { Array($0.string.utf16) },
startColumn: run.cells.startIndex,
offset: .zero,
font: font,
cellWidth: 20)
}
}
private var ugrids = [UGrid]()
private let cellAttrsCollection = CellAttributesCollection()
private let typesetter = Typesetter()
private let font = NSFont.userFixedPitchFont(ofSize: 13)!
private let cellSize: CGSize
private func runs(
_ index: Int,
forRowRange rowRange: CountableClosedRange<Int>,
columnRange: CountableClosedRange<Int>
) -> [AttributesRun] {
precondition(0 <= index && index <= 2, "Wrong index!")
let ugrid = self.ugrids[index]
return rowRange.map { row in
ugrid.cells[row][columnRange]
.groupedRanges(with: { _, cell in cell.attrId })
.compactMap { range in
let cells = ugrid.cells[row][range]
guard let firstCell = cells.first,
let attrs = self.cellAttrsCollection.attributes(
of: firstCell.attrId
)
else {
// GH-666: FIXME: correct error handling
self.log.error("row: \(row), range: \(range): " +
"Could not get CellAttributes with ID " +
"\(String(describing: cells.first?.attrId))")
return nil
}
return AttributesRun(
location: CGPoint.zero,
cells: ugrid.cells[row][range],
attrs: attrs
)
}
}
.flatMap { $0 }
}
private let fontTraitRd = GKRandomDistribution(
randomSource: randomSource,
lowestValue: 0,
highestValue: 6
)
private let intColorRd = GKRandomDistribution(
randomSource: randomSource,
lowestValue: 0,
highestValue: 16777215
)
private let attrsRunRd = GKRandomDistribution(
randomSource: randomSource,
lowestValue: 0,
highestValue: 10
)
private let log = OSLog(subsystem: "com.qvacua.DrawerPerf",
category: "perf-tester")
private func initAttrs() {
for i in (1..<200) {
self.cellAttrsCollection.set(attributes: self.randomCellAttrs(), for: i)
}
}
private func randomCellAttrs() -> CellAttributes {
return CellAttributes(fontTrait: self.randomFontTrait(),
foreground: self.intColorRd.nextInt(),
background: self.intColorRd.nextInt(),
special: self.intColorRd.nextInt(),
reverse: false)
}
private func randomFontTrait() -> FontTrait {
switch self.fontTraitRd.nextInt() {
case 0: return []
case 1: return [.italic]
case 2: return [.bold]
case 3: return [.underline]
case 4: return [.undercurl]
case 5: return [.italic, .bold]
case 6: return [.bold, .underline]
default: return []
}
}
}
private let randomSource = GKMersenneTwisterRandomSource(seed: 95749272934)

View File

@ -9,10 +9,12 @@
/* Begin PBXBuildFile section */
1929B00C084F8EA5EF0BE6E2 /* NvimView+Geometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BD896D408673954F4AA2 /* NvimView+Geometry.swift */; };
1929B06F50B2585777FFBE48 /* NvimApiCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B002A03693B14B14BE34 /* NvimApiCommons.swift */; };
1929B0B1A64AA449F666FCC9 /* 1.json in Resources */ = {isa = PBXBuildFile; fileRef = 1929B8619FD13BC2570CBFB2 /* 1.json */; };
1929B14D2EBC34BCFEC78ACB /* CellAttributesCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB19DD03ECD6ECC35F94 /* CellAttributesCollection.swift */; };
1929B1A7CC32FD7D05646B98 /* AttributesRunDrawer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB7E3430BD3FD88A7698 /* AttributesRunDrawer.swift */; };
1929B2DB631E6EB5C3452B68 /* MyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BAF033A398BFBC2A7890 /* MyView.swift */; };
1929B2E9F089A9E2800B67F2 /* NimbleCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF88DE64FC62AFFCBC84 /* NimbleCommons.swift */; };
1929B326D5117A670105C209 /* 2.json in Resources */ = {isa = PBXBuildFile; fileRef = 1929B0522C47787B50071806 /* 2.json */; };
1929B36C51BCDFCCEE974EA2 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9C55A79D97272894F5D /* SwiftCommons.swift */; };
1929B3B70C96A78FD63DE737 /* NvimView+Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDC8F32F4A0D2299B5C5 /* NvimView+Debug.swift */; };
1929B40A751BDA2882D4FC94 /* NvimView+Objects.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B22A0CAD417EC3790F02 /* NvimView+Objects.swift */; };
@ -29,9 +31,11 @@
1929B7D2EB80FEA7BFBC3D2C /* Typesetter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B47330DAD129520A2273 /* Typesetter.swift */; };
1929B83EAD32DC419FEC68DB /* CocoaCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0C89838D8402BB80BFC /* CocoaCommons.swift */; };
1929B90E2CFEAADE0CEE1562 /* CursorModeShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA4C89E9FE90065C32F6 /* CursorModeShape.swift */; };
1929B922396A4EE7F070299A /* PerfTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B114CC85D012D7477D58 /* PerfTester.swift */; };
1929B953E76914DA984697DC /* FontUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B96A876229DA394F906E /* FontUtils.swift */; };
1929B9A949EE85C27FF66367 /* UGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D83D7E150F518D49FE /* UGrid.swift */; };
1929BA70C221E3C199833B8C /* UiBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B52174EC68D2974B5BAE /* UiBridge.swift */; };
1929BA918C7AB8DC411B82D2 /* 0.json in Resources */ = {isa = PBXBuildFile; fileRef = 1929B086022A7A2C99A65A21 /* 0.json */; };
1929BAB9A0399206FB7EBC76 /* CellAttributesCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB19DD03ECD6ECC35F94 /* CellAttributesCollection.swift */; };
1929BB552C9D99E9ED938759 /* CellAttributesCollectionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0B60CCAA00B08ACAB15 /* CellAttributesCollectionTest.swift */; };
1929BC8495028D66F0A7D618 /* AttributesRunDrawer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB7E3430BD3FD88A7698 /* AttributesRunDrawer.swift */; };
@ -191,9 +195,12 @@
/* Begin PBXFileReference section */
1929B002A03693B14B14BE34 /* NvimApiCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NvimApiCommons.swift; sourceTree = "<group>"; };
1929B0522C47787B50071806 /* 2.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = 2.json; sourceTree = "<group>"; };
1929B06A73BE6DAA2679AAA2 /* Runs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Runs.swift; sourceTree = "<group>"; };
1929B086022A7A2C99A65A21 /* 0.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = 0.json; sourceTree = "<group>"; };
1929B0B60CCAA00B08ACAB15 /* CellAttributesCollectionTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellAttributesCollectionTest.swift; sourceTree = "<group>"; };
1929B0C89838D8402BB80BFC /* CocoaCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CocoaCommons.swift; sourceTree = "<group>"; };
1929B114CC85D012D7477D58 /* PerfTester.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PerfTester.swift; sourceTree = "<group>"; };
1929B22A0CAD417EC3790F02 /* NvimView+Objects.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+Objects.swift"; sourceTree = "<group>"; };
1929B2CE622DF2B4D21D0C0E /* FontTrait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FontTrait.swift; sourceTree = "<group>"; };
1929B39C7DCDA4E9D5220CD8 /* OSLogCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OSLogCommons.swift; sourceTree = "<group>"; };
@ -201,6 +208,7 @@
1929B52174EC68D2974B5BAE /* UiBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiBridge.swift; sourceTree = "<group>"; };
1929B60D1775A75D7C0F6721 /* SimpleCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleCache.swift; sourceTree = "<group>"; };
1929B73455764E42DACF6BB8 /* Geometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Geometry.swift; sourceTree = "<group>"; };
1929B8619FD13BC2570CBFB2 /* 1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = 1.json; sourceTree = "<group>"; };
1929B8E176C11DD61A8DCE95 /* RxSwiftCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxSwiftCommons.swift; sourceTree = "<group>"; };
1929B9290D503536FFDA9C49 /* MessagePackCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackCommons.swift; sourceTree = "<group>"; };
1929B96A876229DA394F906E /* FontUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FontUtils.swift; sourceTree = "<group>"; };
@ -468,6 +476,10 @@
4BF01CD22235015E00411218 /* MainMenu.xib */,
4BF01CD52235015E00411218 /* Info.plist */,
1929B2CE622DF2B4D21D0C0E /* FontTrait.swift */,
1929B114CC85D012D7477D58 /* PerfTester.swift */,
1929B0522C47787B50071806 /* 2.json */,
1929B8619FD13BC2570CBFB2 /* 1.json */,
1929B086022A7A2C99A65A21 /* 0.json */,
);
path = DrawerPerf;
sourceTree = "<group>";
@ -666,6 +678,9 @@
files = (
4BF01CD12235015E00411218 /* Assets.xcassets in Resources */,
4BF01CD42235015E00411218 /* MainMenu.xib in Resources */,
1929B326D5117A670105C209 /* 2.json in Resources */,
1929B0B1A64AA449F666FCC9 /* 1.json in Resources */,
1929BA918C7AB8DC411B82D2 /* 0.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -803,6 +818,7 @@
4BF01CEC2235022300411218 /* CellAttributesCollection.swift in Sources */,
4BF01CCF2235015E00411218 /* AppDelegate.swift in Sources */,
1929B1A7CC32FD7D05646B98 /* AttributesRunDrawer.swift in Sources */,
1929B922396A4EE7F070299A /* PerfTester.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
version = "1.3">
<BuildAction>
<BuildActionEntries>
<BuildActionEntry
buildForRunning = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BF01CCB2235015E00411218"
BuildableName = "DrawerPerf.app"
BlueprintName = "DrawerPerf"
ReferencedContainer = "container:NvimView.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<LaunchAction
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BF01CCB2235015E00411218"
BuildableName = "DrawerPerf.app"
BlueprintName = "DrawerPerf"
ReferencedContainer = "container:NvimView.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<LocationScenarioReference
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
referenceType = "1">
</LocationScenarioReference>
</LaunchAction>
</Scheme>

View File

@ -1,10 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
version = "1.3">
<BuildAction>
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForRunning = "YES">
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BF01CCB2235015E00411218"
@ -15,11 +21,28 @@
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<LaunchAction
useCustomWorkingDirectory = "NO"
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BF01CCB2235015E00411218"
@ -28,9 +51,35 @@
ReferencedContainer = "container:NvimView.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
<LocationScenarioReference
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
referenceType = "1">
</LocationScenarioReference>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BF01CCB2235015E00411218"
BuildableName = "DrawerPerf.app"
BlueprintName = "DrawerPerf"
ReferencedContainer = "container:NvimView.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -337,9 +337,9 @@ public class NvimView: NSView,
}
@IBAction public func debug1(_ sender: Any?) {
self.log.debug("DEBUG 1 - Start")
// noop
self.log.debug("DEBUG 1 - End")
#if DEBUG
do { try self.ugrid.dump() } catch { self.log.error("Could not dump UGrid: \(error)") }
#endif
}
// MARK: - Internal

View File

@ -4,6 +4,7 @@
*/
import Foundation
import os
final class SimpleCache<K: Hashable, V> {

View File

@ -6,7 +6,7 @@
import Foundation
import os
struct UCell {
struct UCell: Codable {
var string: String
var attrId: Int
@ -20,7 +20,7 @@ struct UCell {
}
}
final class UGrid: CustomStringConvertible {
final class UGrid: CustomStringConvertible, Codable {
private(set) var cursorPosition = Position.zero
@ -28,6 +28,45 @@ final class UGrid: CustomStringConvertible {
private(set) var cells: [[UCell]] = []
enum CodingKeys: String, CodingKey {
case width
case height
case cells
}
init() {
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
let width = try values.decode(Int.self, forKey: .width)
let height = try values.decode(Int.self, forKey: .height)
self.size = Size(width: width, height: height)
self.cells = try values.decode([[UCell]].self, forKey: .cells)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.size.width, forKey: .width)
try container.encode(self.size.height, forKey: .height)
try container.encode(self.cells, forKey: .cells)
}
#if DEBUG
func dump() throws {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(self)
try data.write(to: URL(fileURLWithPath: "/tmp/ugrid.dump.json"))
}
#endif
var description: String {
let result = "UGrid.flatCharIndex:\n" + self.cells.reduce("") { result, row in
return result + "(\(row[0].flatCharIndex ... row[self.size.width - 1].flatCharIndex)), "

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>