Skip to content

Instantly share code, notes, and snippets.

@KagamiChan
Last active July 21, 2017 13:40
Show Gist options
  • Save KagamiChan/f7e626f2e31db9bbb5d8f081eb5e83dc to your computer and use it in GitHub Desktop.
Save KagamiChan/f7e626f2e31db9bbb5d8f081eb5e83dc to your computer and use it in GitHub Desktop.
performance test
import fs from 'fs-extra'
import classnames from 'classnames'
import React from 'react'
import PropTypes from 'prop-types'
const readPngAsDataURL = path => {
const buf = fs.readFileSync(path)
return `data:image/png;base64,${buf.toString('base64')}`
}
const readSvgAsDataURL = path => {
const data = fs.readFileSync(path, 'utf-8')
return `data:image/svg+xml;utf8,${data}`
}
const getClassName = (props, isSVG) => {
const type = isSVG ? 'svg' : 'png'
return classnames(type, props)
}
const {ROOT, config} = window
const svgAvailableList = {}
const pngAvailableList = {}
const svgList = {}
const pngList = {}
class iconConf {
constructor() {
this.callbacks = new Map()
}
setConf = (val) => {
this.callbacks.forEach((f) => f(val))
}
reg = (key, func) => {
this.callbacks.set(key, func)
}
unreg = (key) => {
this.callbacks.delete(key)
}
}
const iconConfSetter = new iconConf()
const setIcon = (path, val) => {
if (path === 'poi.useSVGIcon') {
iconConfSetter.setConf(val)
}
}
config.addListener('config.set', setIcon)
window.addEventListener('unload', (e) => {
config.removeListener('config.set', setIcon)
})
export class SlotitemIcon extends React.Component {
static propTypes = {
slotitemId: PropTypes.number,
className: PropTypes.string,
alt: PropTypes.string,
}
state = {
useSVGIcon: config.get('poi.useSVGIcon', false),
}
name = 'SlotitemIcon'
shouldComponentUpdate = (nextProps, nextState) => (
!(nextProps.slotitemId === this.props.slotitemId &&
nextProps.className === this.props.className &&
nextState.useSVGIcon === this.state.useSVGIcon)
)
svgPath = () =>
`${ROOT}/assets/svg/slotitem/${this.props.slotitemId}.svg`
pngPath = () =>
`${ROOT}/assets/img/slotitem/${this.props.slotitemId + 100}.png`
getAvailable = () => {
const { useSVGIcon } = this.state
const { slotitemId } = this.props
try {
const path = useSVGIcon ? this.svgPath() : this.pngPath()
fs.statSync(path)
const read = useSVGIcon ? readSvgAsDataURL : readPngAsDataURL
;(useSVGIcon ? svgList : pngList)[slotitemId] = read(path)
return true
} catch (e) {
return false
}
}
setUseSvg = (val) => {
this.setState({
useSVGIcon: val,
})
}
componentDidMount = () => {
this.key = `${process.hrtime()[0]}${process.hrtime()[1]}`
iconConfSetter.reg(this.key, this.setUseSvg)
}
componentWillUnmount = () => {
iconConfSetter.unreg(this.key)
}
render() {
const { alt, slotitemId, className } = this.props
const { useSVGIcon } = this.state
const availableList = useSVGIcon ? svgAvailableList : pngAvailableList
const list = useSVGIcon ? svgList : pngList
if (!availableList[slotitemId]) {
availableList[slotitemId] = this.getAvailable()
}
return (
<img
alt={alt}
src={availableList[slotitemId] ? list[slotitemId] : `file://${ROOT}/assets/svg/slotitem/-1.${useSVGIcon ? 'svg' : 'png'}`}
className={getClassName(className, true)}
/>
)
}
}
export class MaterialIcon extends React.Component {
static propTypes = {
materialId: PropTypes.number,
className: PropTypes.string,
alt: PropTypes.string,
}
state = {
useSVGIcon: config.get('poi.useSVGIcon', false),
}
name = 'MaterialIcon'
shouldComponentUpdate = (nextProps, nextState) => (
!(nextProps.materialId === this.props.materialId &&
nextProps.className === this.props.className &&
nextState.useSVGIcon === this.state.useSVGIcon)
)
setUseSvg = (val) => {
this.setState({
useSVGIcon: val,
})
}
componentDidMount = () => {
this.key = `${process.hrtime()[0]}${process.hrtime()[1]}`
iconConfSetter.reg(this.key, this.setUseSvg)
}
componentWillUnmount = () => {
iconConfSetter.unreg(this.key)
}
render() {
let src = null
if (this.state.useSVGIcon) {
src = `file://${ROOT}/assets/svg/material/${this.props.materialId}.svg`
} else {
src = `file://${ROOT}/assets/img/material/0${this.props.materialId}.png`
}
return <img alt={this.props.alt} src={src} className={getClassName(this.props.className, this.state.useSVGIcon)} />
}
}
import React, { Component } from 'react'
import { resolve } from 'path'
import Perf from 'react-addons-perf'
import { SlotitemIcon } from 'views/components/etc/icon'
import _ from 'lodash'
const getRandom = (arr = new Array(100).fill(-1)) =>
arr.map((v) => {
let w = v
while (w === v) {
w = _.random(1, 42)
}
return w
})
class AirbaseView extends Component {
state = {
icons: new Array(10000).fill(-1),
}
componentDidUpdate = () => {
Perf.stop()
Perf.printInclusive()
Perf.printExclusive()
// Perf.printWasted()
// Perf.printOperations()
}
hanldePerf = () => {
let icons = this.state.icons.slice()
icons = getRandom(icons)
Perf.start()
this.setState({
icons,
})
}
render() {
const { icons } = this.state
return (
<div>
<div>
<input type="button" onClick={this.hanldePerf} value="perf" />
</div>
<div>
{
_.range(10000).map(index => (
<SlotitemIcon key={index} className="icon" slotitemId={icons[index]} />
))
}
</div>
</div>
)
}
}
export default AirbaseView
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment